排序算法Part1

41 阅读2分钟

1. Bubble sort

  • 每一趟,比较相邻元素,较大的元素后移。

  • 稳定

  • 时间复杂度

    最好最坏平均
    O(n)O(n)O(n2)O(n^2)O(n2)O(n^2)
  • 实现

    void BubbleSort(int *arr, int n)
    {
        for(int t = 0; t < n; t++)
        {
            for(int i = 0; i < n - 1 - t; i++)
            {
                if(arr[i] > arr[i+1])
                {
                    swap(arr[i], arr[i+1]);
                }
            }
        }
    }
    

2. Selection Sort

  • 不同于冒泡排序不停的交换元素

  • 每一趟选择最小的元素,与当前元素交换,

  • 稳定

  • 时间复杂度

    最好最坏平均
    O(n2)O(n^2)O(n2)O(n^2)O(n2)O(n^2)
  • 实现

    void SelectSort(int *arr, int n)
    {
        for(int i = 0; i < n; i++)
        {
            int min_idx = i;
            for(int j = i + 1; j < n; j++)
            {
                if(arr[min_idx] > arr[j])
                {
                    min_idx = j;
                }
            }
            if(min_idx != i)
            {
                swap(arr[min_idx], arr[i]);
            }
        }
    }
    

3. Straight Insert Sort

  • 把当前元素插入到前面的有序序列中。

  • 插入的具体方式,前方有序序列中的从后往前,所有大于当前元素的元素后依次后移移位。

  • 稳定

  • 对有序的序列,效率高

  • 时间复杂度

    最好最坏平均
    O(n)O(n)O(n2)O(n^2)O(n2)O(n^2)
  • 实现

    void InsertSort(int *arr, int n)
    {
        for(int i = 1; i < n; i++)
        {
            int tmp = arr[i];
            int j = i - 1;
            for(; j >=0 && arr[j] > tmp; j--)
            {
                arr[j+1] = arr[j];
            }
            arr[j+1] = tmp;
        }
    }
    

4. 希尔排序 Shell Sort

  • 一种改进的插入排序(利用插入排序对有序序列高效)
  • 增量递减,多种增量计算的方案(knuth, Sedgewick)
  • 不稳定
  • 时间复杂度
    最好最坏平均
    O(n)O(n)O(n2)O(n^2)O(n1.3)O(n^{1.3})
  • 实现
    void ShellSort(int *arr, int n)
    {
        // for(int gap = n >> 1; gap > 0; gap >>= 1)
        for(int gap = n / 3 + 1; gap > 0; gap = gap / 3)
        {
            for(int i = gap; i < n; i++)
            {
                int tmp = arr[i];
                int j = i - gap;
                for(; j >=0 && arr[j] > tmp; j -= gap)
                {
                    arr[j+gap] = arr[j];
                }
                arr[j + gap] = tmp;
            }
        }
    }
    

5. 计数排序-Counting Sort

  • 不进行元素之间的比较

  • 统计元素数量

  • 利用辅助空间,并把元素值作为下标

  • 使用前缀和确定排序后元素的位置

  • 稳定

  • 时间复杂度

    最好最坏平均
    O(n+k)O(n+k)O(n+k)O(n+k)O(n+k)O(n+k)
  • 实现

    void CountingSort(int *arr, int n)
    {
        int cnt[10];
        memset(cnt, 0, sizeof(cnt));
        //统计数量
        for(int i = 0; i < n; i++)
        {
            cnt[arr[i]]++;
        }
        // 前缀和
        for(int i = 1; i < 10; i++)
        {
            cnt[i] += cnt[i-1];
        }
    
        int b[10];
        for(int i = n-1; i >=0 ;i--)
        {
            b[--cnt[arr[i]]] = arr[i];
        }
        memcpy(arr, b, sizeof(int) * n);
    }