排序基础算法总结与c++实现

默认都是从小到大排序。有必要注释。

总结

分类 时间 空间 稳定性
选择 好、坏、平均都是O(n^2) O(1) 不稳定
插入 平均、坏O(n^2),好O(n) O(1) 稳定
冒泡 平均、坏O(n^2),好O(n) O(1) 稳定
快排 平均、好O(nlogn),坏O(n^2) O(logn) 不稳定
好、坏、平均都是O(nlogn) O(1) 不稳定
归并 好、坏、平均都是O(nlogn) O(n) 稳定

选择排序

思想

每次从未排序集合中选出最大的,与未排序集合末端元素交换,直到未排序集合空。

cpp实现

void select_sort(vector<int>& arr){
    for(int len = arr.size(); len > 0; --len){//len表示未排序集合大小
        int max = 0;//max用来记录未排序集合中最大数的下标
        for(int i = 0; i < len; ++i){
            if(arr[i]>arr[max]) max = i;
        }
        swap(arr[max], arr[len-1]);//将最大数与未排序集合末端元素交换
    }
}

主要优点

数据移动次数。
若某个元素位于正确的最终位置上,则该元素不会被移动。

复杂度分析

一般是说不稳定。(本实现也是。不过,对于数组,把本实现中的内层for循环倒过来,即从后往前找最大,就稳定了…)
空间O(1) 原地操作(优点);
时间O(n^2) 好、坏、平均都一样。
主要受比较次数制约:n(n-1)/2,与初始状态无关。
移动(交换)次数最好0次,最多n-1次。
与冒泡比较:n值较小时,选择排序快于冒泡。
因为冒泡移动次数为n^2,一般来说,一次移动(交换)时间长于一次比较时间。

插入排序

思想

将无序区间中的元素依次插入有序区间中的适当位置,直到无序区间长度变为零。

cpp实现

void insert_sort(vector<int>& arr){
    for(int len = 1; len < arr.size(); ++len){
        int i = 0;
        while(i<len && arr[len]>arr[i]) ++i;
        if(i<len){
            int t = arr[len];
            for(int j = len; j > i; --j) arr[j] = arr[j-1];
            arr[i] = t;
        }
    }
}

快排

常考中的常考,要会手写,且做到快速、无bug。

思想

白话:“挖洞填数+分治”
(0)首先选择哨兵元素,将该元素“挖”出来赋给x,并将该位置作为第一个“洞”(同一时间只会存在一个“洞”)。本实现选择左界元素为哨兵。
(1)先从右往左,找比哨兵x小的元素a,将其“挖”出,填入“洞”中,此时a的位置变成了新的“洞”。
(2)再从左往右,找比哨兵x大的元素b,将其“挖”出,填入“洞”中,此时b的位置变成了新的“洞”。
(3)重复执行(1-2)直到左右相遇,此时相遇位置即最后一个“洞”就是哨兵元素x最终有序位置。
(4)将哨兵元素x最终有序位置左右分别进行快排,即分治,直到当前区段长度为零。

cpp实现

void quick_sort(vector<int>& arr, int l, int h){
    if(l>=h) return;
    int i = l, j = h;
    int x = arr[l];
    while(i<j){
        while(i<j && arr[j]>=x) --j;
        if(i<j) arr[i++] = arr[j];
        while(i<j && arr[i]<=x) ++i;
        if(i<j) arr[j--] = arr[i];
    }
    arr[i] = x;
    quick_sort(arr, l, i-1);
    quick_sort(arr, i+1, h);
}

堆排序

HeapSort堆排序C++实现及相关背景知识

归并排序

MergeSort归并排序递归、迭代、原地 c++实现

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章