排序算法总结

时间:2020-05-28
本文章向大家介绍排序算法总结,主要包括排序算法总结使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

排序算法

排序算法比较

排序算法 平均时间复杂度 最差时间复杂度 空间复杂度 数据对象稳定性
冒泡排序 O(n2) O(n2) O(1) 稳定
选择排序 O(n2) O(n2) O(1) 数组不稳定,链表稳定
插入排序 O(n2) O(n2) O(1) 稳定
快速排序 O(nlog2n) O(n2) O(log2n) 不稳定
归并排序 O(nlog2n) O(nlog2n) O(n) 稳定
希尔排序 O(nlog2n) O(n2) O(1) 不稳定
堆排序 O(nlog2n) O(nlog2n) O(1)
计数排序 O(n+k) O(m+n) O(k) 稳定
桶排序 O(n+k) O(n) O(n+k) 稳定
基数排序 O(n*k) O(n2) O(n+k) 稳定
锦标赛排序

起泡排序

  • 起泡排序思路:
    1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
    3. 针对所有的元素重复以上的步骤,除了最后一个。
    4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
void swap(int & a, int & b) {
    int c = a;
    a = b;
    b = c;
}
int bubble(int *num, int m) {
    int flag = 0;
    for (int i = 1; i < m; i++) {
        if (num[i-1] > num[i]) {
            swap(num[i-1], num[i]);
            flag = i;
        }
    }
    return flag;
}
void bubbleSort(int *num, int n) {
    int fl = bubble(num, n);
    while (fl) {
        fl = bubble(num, fl);
    }
}

选择排序

  • 选择排序思路:
    1. 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
    2. 从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾
    3. 以此类推,直到所有元素均排序完毕
void SelectionSort(vector<int>& v) {
    int min, len = v.size();
    for (int i = 0; i < len - 1; ++i) {
        min = i;
        for (int j = i + 1; j < len; ++j) {
            if (v[j] < v[min]) {    // 标记最小的
                min = j;
            }
        }
        if (i != min)  // 交换到前面
            swap(v[i], v[min]);
    }
}

// 模板实现
template<typename T> 
void Selection_Sort(std::vector<T>& arr) {
    int len = arr.size();
    for (int i = 0; i < len - 1; i++) {
        int min = i;
        for (int j = i + 1; j < len; j++)
            if (arr[j] < arr[min])
                min = j;
        if(i != min)
            std::swap(arr[i], arr[min]);
    }
}

插入排序

  • 插入排序思路:
    1. 从第一个元素开始,该元素可以认为已经被排序
    2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
    3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
    4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
    5. 将新元素插入到该位置后
    6. 重复步骤2~5
void InsertSort(vector<int>& v)
{
  int len = v.size();
    for (int i = 1; i < len - 1; ++i) {
        int temp = v[i];
        for(int j = i - 1; j >= 0; --j)
        {
            if(v[j] > temp)
            {
                v[j + 1] = v[j];
                v[j] = temp;
            }
            else
                break;
        }
    }
}

快速排序

  • 快速排序思路:
    1. 选取第一个数为基准
    2. 将比基准小的数交换到前面,比基准大的数交换到后面
    3. 对左右区间重复第二步,直到各区间只有一个数
int partition(vector<int> & num, int lo, int hi) {
    int pivot = num[lo];
    int temp = lo;
    while (lo < hi) {
        while ((lo < hi) && (pivot <= num[hi]))
            hi--;
        num[lo] = num[hi];
        while ((lo < hi) && (pivot >= num[lo]))
            lo++;
        num[hi] = num[lo];
        //std::swap(num[hi], num[lo]);
    }
    num[lo] = pivot;
    //std::swap(num[lo], num[temp]);
    //for (auto w : num)
    //  cout << w << "  ";
    //cout << endl;
    return lo;
}

void quickSo(vector<int> & num, int lo, int hi) {
    if (hi - lo < 2)
        return;
    int mi = partition(num, lo, hi - 1);
    quickSo(num,lo, mi);
    quickSo(num,mi + 1, hi);
}

void quickSort(vector<int> & num) {
    quickSo(num, 0, num.size());
}
// ----------------------------------------------------

// 模板实现快速排序(迭代)
struct Range {
    int start, end;
    Range(int s = 0, int e = 0) {
        start = s, end = e;
    }
};
template <typename T> // 整數或浮點數皆可使用,若要使用物件(class)時必須設定"小於"(<)、"大於"(>)、"不小於"(>=)的運算子功能
void quick_sort(T arr[], const int len) {
    if (len <= 0)
        return; // 避免len等於負值時宣告堆疊陣列當機
    // r[]模擬堆疊,p為數量,r[p++]為push,r[--p]為pop且取得元素
    Range r[len];
    int p = 0;
    r[p++] = Range(0, len - 1);
    while (p) {
        Range range = r[--p];
        if (range.start >= range.end)
            continue;
        T mid = arr[range.end];
        int left = range.start, right = range.end - 1;
        while (left < right) {
            while (arr[left] < mid && left < right) left++;
            while (arr[right] >= mid && left < right) right--;
            std::swap(arr[left], arr[right]);
        }
        if (arr[left] >= arr[range.end])
            std::swap(arr[left], arr[range.end]);
        else
            left++;
        r[p++] = Range(range.start, left - 1);
        r[p++] = Range(left + 1, range.end);
    }
}

归并排序

  • 核心思想:分而治之
  • 实现步骤: void MergeSort(){
    递归条件
    分组1
    分组2
    归并
    }
template<typename T>
void merge(vector<T> &num, int lo, int mi, int hi) {
    int lb = mi - lo;
    int lc = hi - mi;
    T *pa = &num[lo];
    T *pb = new T[lb];
    T *pc = &num[mi];
    for (int i = 0; i < lb; i++) {
        pb[i] = pa[i];
    }
    for (int m = 0, n = 0, k = 0; (m < lb) || (n < lc);) {
        if ((m < lb) && ((n >= lc) || (pb[m] < pc[n])))
            pa[k++] = pb[m++];
        else
            pa[k++] = pc[n++];
    }
}
template <typename T>
void mergeSort(vector<T> & A,int lo, int hi) {
    if (hi - lo < 2)        //递归条件
        return;
    int mi = (hi + lo) >> 1;
    mergeSort(A,lo, mi);
    mergeSort(A,mi, hi);
    merge(A,lo, mi, hi);
}
template<typename T>
void merge_sort(T arr[], int len) {
    T* a = arr;
    T* b = new T[len];
    for (int seg = 1; seg < len; seg += seg) {
        for (int start = 0; start < len; start += seg + seg) {
            int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);
            int k = low;
            int start1 = low, end1 = mid;
            int start2 = mid, end2 = high;
            while (start1 < end1 && start2 < end2)
                b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
            while (start1 < end1)
                b[k++] = a[start1++];
            while (start2 < end2)
                b[k++] = a[start2++];
        }
        T* temp = a;
        a = b;
        b = temp;
    }
    if (a != arr) {
        for (int i = 0; i < len; i++)
            b[i] = a[i];
        b = a;
    }
    delete[] b;
}

希尔排序

算法思想
算法思想来源于插入排序,
先将n个待排序的序列分割成n/2组数据分别进行插入排序,
然后依次分割成n/4组,n/8组,
直至最后只能分成一组数据进行插入排序
算法演示

算法实现:

//希尔排序
void shellSort(int *p, int n) {
    int temp = n;
    while (temp >>= 1) {
        for (int i = temp; i < n; i++) {
            for (int j = i; j > 0; j -= temp) {
                if (p[j] < p[j - temp]) {
                    Swap(p[j], p[j - temp]);
                    break;
                }
            }
        }
    }
}

计数排序

算法思想
对值比较集中的数据进行排序先统计每个数据个数,再根据个数进行排序

算法图解

算法实现

//计数排序
void countSort(int *p, int n) {
    int max = p[0];
    int min = p[0];
    for (int i = 0; i < n; i++) {       //找到最小与最大值
        if (max < p[i])
            max = p[i];
        if (min > p[i])
            min = p[i];
    }
    int space = max - min + 1;          
    int *num = new int[space]();        //申请辅助空间
    for (int i = 0; i < n; i++) {       //统计
        num[p[i] - min]++;
    }
    int j = 0;
    for (int i = 0; i < space; i++) {   //排序
        while (num[i]--) {
            p[j++] = i+min;
        }
    }
    delete[]num;
}

桶排序

基数排序

堆排序

原文地址:https://www.cnblogs.com/hellocxz/p/pai-xu-suan-fa-zong-jie.html