当前位置:   article > 正文

十种常见排序算法的思想、应用场景、C++代码实现及时间效率直观对比_c++ 排序算法的应用场景及选择

c++ 排序算法的应用场景及选择

前言:

写在这篇博客前面,最近发现自己做事学东西远没有以前的踏实,往往学过之后很快就忘记,包括基础的排序算法,虽然看过几遍,但是却没有真正掌握,到了突然需要自己抛开书本手写的时候,发现自己对它们其实挺陌生的。所以希望借写这篇博客的机会,让自己好好复习一下基本的排序算法,也希望自己从现在开始能做到学东西像之前一样踏实。

这篇博客中包含的排序算法主要有冒泡排序,插入排序,希尔排序,选择排序,堆排序,归并排序,快速排序,计数排序,基数排序,桶排序。


冒泡排序

冒泡排序是一种很简单的排序算法,也是大多数人所学的第一种排序算法,其基本思想是“比较相邻元素,将大的元素放后边,小的放前边,每一轮比较,总有一个最大元素被‘冒’到数组最后边。”N轮比较下来,就完成了排序。

  • 时间复杂度:O(n2)
  • 空间复杂度:原址排序
  • 是否稳定:是
  • 应用场景:优化后的冒泡排序可用于当数据已经基本有序,且数据量较小时。
  • 优化措施:设置一个标志,每轮比较时,如果发现没有进行交换操作,说明数组已经有序,退出循环,停止比较。
  • 代码:
/*冒泡排序*/
void BubbleSort(vector<int>& arr) {
    int len = arr.size();
    if (len == 0)
        return;
    bool change = false;
    for (int i = 0; i < len; i++) {
        for (int j = 1; j < len - i; j++) {
            if (arr[j] < arr[j - 1]) {
                swap(arr[j], arr[j - 1]);
                change = true;
            }
        }
        if (!change)
            break;
    }
    return;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

插入排序

插入排序也是一种基本的排序算法,它的基本思想类似于我们抓扑克牌。开始时,我们的左手为空,然后我们每次从牌堆中拿走一张牌并插入到正确的位置;为了找到每一张牌的正确位置,需要将它从右到左与每一张牌比较,直到找到小于它的那张牌,保证左手的牌随时都是有序的,同样N轮插入操作下来,数组有序。

  • 时间复杂度:O(n2)
  • 空间复杂度:原址排序
  • 是否稳定:是
  • 应用场景:若数组基本有序且数据规模较小时,选用插入排序较好.
  • 优化措施:由于每次插入是向已排序数组中插入,可使用二分查找查找到相应位置进行插入.
  • 代码:
/*插入排序*/
void InsetionSort(vector<int>& arr) {
    int len = arr.size();
    for (int i = 1; i < len; i++) {
        int idx = i;
        while (idx > 0 && arr[idx - 1] > arr[idx]) {
            int ntmp = arr[idx];
            arr[idx] = arr[idx - 1];
            arr[idx - 1] = ntmp;
            idx--;
        }
    }
    return;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

希尔排序

希尔排序是对插入排序的一种改进,其改进思想来源于“序列越基本有序,插入排序效率越高”;该算法是第一批突破O(n2)时间复杂度的排序算法。基本思想:先将整个待排记录序列分割成若干列,即若干子序列,分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

  • 时间复杂度:小于O(n4/3)
  • 空间复杂度:原址排序
  • 是否稳定:否
  • 注:对于希尔排序涉及到一个增量步长的选择,具体选择标准可参照WIKI Gap_sequence
  • 应用场景:数据量较小且基本有序时
  • 代码:
/*希尔排序*/
void ShellSort(vector<int>& arr) {
    int len = arr.size();
    if (len == 0)
        return;
    vector<int> gaps = { 1,3,7,15,31,63,127,255,511,1023 };
    int idx = gaps.size() - 1;
    while (idx >= 0) {
        int span = gaps[idx];                                   //从第二行开始对每列数进行插入排序
        for (int i = span; i < len; i++) {
            for (int j = i; j >= span; j -= span) {
                if (arr[j] >= arr[j - span])
                    break;
                int ntmp = arr[j];
                arr[j] = arr[j - span];
                arr[j - span] = ntmp;
            }
        }
        idx--;
    }
    return;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

选择排序:

选择排序也是一种简单直观的排序算法,它的基本思想也很简单直观:每次总是选择未排序序列中最小(或最大)的元素,放置在已排序序列最后或最前即可。

  • 时间复杂度:O(n2)
  • 空间复杂度:原址排序
  • 是否稳定:否
  • 应用场景:当数据规模较小时,选择排序性能较好
  • 优化措施:每次寻找最小或最大元素时,同时记录最小最大元素的位置,每次使用3次比较寻找两个元素的位置,而不是4次比较
  • 代码:
/*选择排序*/
void SelectionSort(
  • 1
  • 2
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号