总述

[算法] 排序算法总结_时间复杂度

 

 

 借图侵删

 

SHELL排序

时间复杂度:O(N^(X)) (X<=2)

又称“缩小增量排序”,是插入排序的进化版,其高效之处在于通过增量间隔的比较和交换,比朴素的插入排序减少了交换次数,从而提高了效率。感性认知来讲,确实可以提高算法效率,但是我不会证明该算法的时间复杂度。

 1 void Shell_sort(int l, int r)
 2 {
 3     int gap = r - l + 1;
 4     int tep = 0;
 5     do
 6     {
 7         gap = gap / 3 + 1;
 8         for (int i = l + gap; i <= r; ++i)
 9         {
10             if (a[i - gap] > a[i])
11             {
12                 tep = a[i];
13                 int j = i - gap;
14                 do 
15                 {
16                     a[j + gap] = a[j];
17                     j -= gap;
18                 } while (j >= l && a[j] > tep);
19                 a[j + gap] = tep;
20             }
21         }
22     }while (gap > 1);
23 }

 

 

归并排序

时间复杂度:O(N*logN)

分治的思想+O(N)合并有序数组。

22 void GB_sort(int l, int r)
23 {
24     if (l == r)    return;
25     int mid = (l + r) >> 1;
26     GB_sort(l, mid), GB_sort(mid + 1, r);
27     int t1 = l, t2 = mid + 1, t3 = l;
28     for (int i = l; i <= r; ++i)
29         if ((a[t1] <= a[t2] && t1 <= mid) || t2 == r + 1) b[t3] = a[t1], ++t1, ++t3;
30         else b[t3] = a[t2], ++t2, ++t3;
31     for (int i = l; i <= r; ++i)
32         a[i] = b[i];
33 }

 

堆排序

时间复杂度:O(N*logN)

本质上就是维护一个大根堆。也是选择排序的一种。

 

注意堆的初始化要自下而上!因为update函数是自上而下更新的,向下可以保证操作到位,而向上无法进行。

 1 void update(int x, int m)
 2 {
 3     int t = lson(x);
 4     if (t > m) return;
 5     if (t < m && a[t + 1] > a[t]) ++t;
 6     if (a[t] > a[x]) swap(a[x], a[t]);
 7     update(t, m);
 8 }
 9 
10 void HEAP_sort()
11 {
12     for (int i = n; i >= 1; --i)
13         update(i, n);
14     for (int i = n - 1; i >= 1; --i) // 每次取出最大值并维护堆
15     {
16         swap(a[i + 1], a[1]);
17         update(1, i);
18     }
19 }

 

快速排序

时间复杂度:平均O(N*logN)

交换排序的一种,具体流程如下:

选择基准值---将小于基准值的值置于基准值之前,将大于基准值的值置于基准值之后---递归

 

不难看出这个算法是很容易被卡成N^2的,故手写时应至少加一个随机化(虽然很少去手写)。

 1 void Quick_sort(int l, int r)
 2 {
 3     if (l >= r) return;
 4     int i = l, j = r;
 5     int x = a[i];
 6     while (i < j)
 7     {
 8         while (i < j && a[j] > x) --j;
 9         if (i < j) a[i++] = a[j];
10         while (i < j && a[i] < x) ++i;
11         if (i < j) a[j--] = a[i];
12     }
13     a[i] = x;
14     Quick_sort(l, i - 1);
15     Quick_sort(i + 1, r);
16     return;
17 }

 

 

所以为什么快速排序叫做快排?手写起来惨不忍睹还会被卡