C++实现常见排序算法(堆排序,快速排序,归并排序,希尔排序,插入排序,冒泡排序,选择排序)

  • 选择排序
vector<int> selectionSort(vector<int> v){
    int temp ;
    int size = (int)v.size();
    if(size<2) return v;
    for(int i=0; i<=size-2;++i){
        for(int j=i+1; j<=size-1;++j){
            if(v[i]>v[j]){
                temp = v[j];
                v[j] = v[i];
                v[i] = temp;
            }
        }
    }
    return v;
}

对于任何输入,时间为O(n*n);

  • 冒泡排序
vector<int> bubbleSort(vector<int> v){
    int size = (int)v.size();
    if(size<2) return v;
    int temp;
    bool finish ;
    for(int i = size-1;i>0; --i){
        finish =  true;
        for(int j = 0; j<i; ++j){
            if(v[j]>v[j+1]){
                temp = v[j];
                v[j] = v[j+1];
                v[j+1] = temp;
                finish = false;
            }
        }
        if(finish)
            break;
    }
    return v;
}

最优(对于升序的数组,因为加入了一个跳出判断):O(n),平均:O(n*n), 最差:O(n*n)

  • 插入排序
vector<int> insertionSort(vector<int> v){
    int size = (int)v.size();
    if(size<2) return v;
    int temp ;
    for(int i=1; i<size;++i){
        int j = i-1;
        temp = v[i];
        while(j>=0){
            if(temp<v[j]){
                v[j+1]=v[j];
                --j;
            }else{
                break;
            }
        }
        v[j+1]=temp;
        }
    return v;
}

最优(升序的数组):O(n), 最差(严格递减的数组):O(n*n),平均(比最差性能快一倍):O(n*n)
(遇到基本有序的数组时能表现出优异的性能)

  • 希尔排序
void shellSort(vector<int>& v)
{
    int size = (int)v.size();
    if(size<2) return;
    int incre = size/2;
    int temp;
    for(; incre>=1; incre/=2)
    {
        for(int i=incre; i<size;++i)
        {
            int j = i - incre;
            temp = v[i];
            while(j>=0&&temp<v[j])
            {
                v[j+incre] = v[j];
                j -= incre;
            }
            v[j+incre] = temp;
        }
    }
}
  • 归并排序
void mergeSort(vector<int>& v, int begin, int end){
    int size = end-begin;
    if(size<2) return;
    int mid = (end-begin)/2+begin;
    mergeSort(v, begin, mid);
    mergeSort(v,  mid, end);
    merge(v, begin, mid, end);
}
void merge(vector<int>& v, int begin, int mid, int end){
    vector<int>va;
    va.assign(v.begin()+begin, v.begin()+mid);
    vector<int>vb;
    vb.assign(v.begin()+mid, v.begin()+end);
    int i=0, j=0;
    int size_a = (int)va.size();
    int size_b = (int)vb.size();
    while(i<size_a&&j<size_b){
        if(va[i]<vb[j]){
            v[begin+i+j]=va[i];
            ++i;
        }else{
            v[begin+i+j]=vb[j];
            ++j;
        }
    }
    while(i<size_a){
        v[begin+i+j]=va[i];
        ++i;
    }
    while(j<size_b){
        v[begin+i+j]=vb[j];
        ++j;
    }
}

最优与平均与最差都是:O(n*log n)
优点在于其稳定性,缺点是需要额外的空间

  • 快速排序
void quickSort(vector<int> &v, int begin, int end){
    if(end-begin<2) return;
    int i = begin;
    int j = end-1;
    int key = v[begin];
    while(i<j){
        while(i<j&&v[j]>key){
            --j;
        }
        if(i<j){
            v[i]=v[j];
        }
        while(i<j&&v[i]<key){
            ++i;
        }
        if(i<j){
            v[j]=v[i];
        }
    }
    v[i]=key;
    quickSort(v, begin, i);
    quickSort(v, i+1, end);
}

最优:O(n*log n) , 平均:O(n*log n) ,最差(严格递增的数组,这时插入排序能表现出优异性能):O(n*n) => 引入随机性即使用随机的元素作为中轴能解决这个窘境(随机快速排序)

  • 归并排序对子数组的划分非常快速,时间耗在合并上,
    而快速排序时间则耗在子数组的划分上。
  • 堆排序
vector<int> heapSort(vector<int> &v){
    int size = (int)v.size();
    if(size<2)return v;
    heapBottomUp(v);
    int temp;
    vector<int> sortedVector;
    for(int i=0;i<size;++i){
        temp = getTheHeadTop(v);
        sortedVector.insert(sortedVector.begin(), temp);
    }
    return sortedVector;
}
//自底向上(即从无序到有序)构造最大堆
// 自底向上与自顶向下的区别:
//自顶向下:从无到有的构造 ; 自底向上:从无序到有序的构造
void heapBottomUp(vector<int> &v){
    //默认根节点的号码为1, 而向量vector的索引起始为0,注意错位
    int size = (int)v.size();
    if(size<2)return ;
    int i, k, j,  fatherValue;
    bool heap = false;
    for( i=size/2;i>=1; --i){
        k = i;
        fatherValue = v[k-1];
        heap = false;
        while(!heap && 2*k<=size){
            j = 2*k;
            if(j+1<=size){ //存在两个子女
                j = v[j-1]<v[j+1-1]? j+1:j;
            }
            if(fatherValue>v[j-1]){
                heap=true;
            }else{
                v[k-1]=v[j-1];
                k=j;
            }
        }
        v[k-1] = fatherValue;
    }
}
//获取最大堆顶上的数字
int getTheHeadTop(vector<int>& v){
    int size = (int)v.size();
    if(size<1) return 0;
    int result = v[0];
    if(size==1){
        v.pop_back();
        return result;
    }
    v[0]=v[size-1];
    v.pop_back();
    //堆复原处理
    int i = 1; //根节点号码
    int fatherValue = v[i-1];
    int k;
    while(2*i<=size){
        k=2*i;
        if(k+1<=size){
            k = v[k-1]<v[k+1-1]?k+1:k;
        }
        if(fatherValue>v[k-1]){
            break;
        }else{
            v[i-1]=v[k-1];
        }
        i=k;
    }
    v[i-1]=fatherValue;
    return result;
}
  • 堆排序与归并排序的性能差不多,不管平均还是最差情况下都是:O(n*log n)
    但堆排序是可以在位的,即不需要额外的存储空间,相比归并排序更省空间。
    针对随机文件的计时实验指出,堆排序比快速排序运行得慢。但与归并排序相差无几。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容