排序总结

来源:互联网 发布:旧货市场淘宝 编辑:程序博客网 时间:2024/06/16 16:51

一、 插入排序

1,思想:将第 i 个记录插入到前面 i-1 个已经排序好的序列之中。

2,时间复杂度 O(n^2),空间复杂度 O(1)。

3,稳定性:稳定。

4,过程分析

     初始:    34    8    64   51   32   21

    第一趟: 8    34   64    51   32   21

    第二趟     8    34   64    51   32   21

    第三趟     8    34   51    64   32   21

    第四趟     8    32   34    51   64   21

    第五趟     8    21   32   34    51  64

5,伪码:

void insertionSort(vector<int> A){  for (int i = 1; i < A.size(); ++i){int tmp = A[i];int j = i;for (; j >0 && A[j - 1]>tmp; j--)A[j] = A[j - 1];A[j] = tmp;}}

二、希尔排序

1,思想:将待排序记录序列分割为若干稀疏的子序列,分别进行插入排序。

2,时间复杂度 O(n^(3/2)),空间复杂度 O(1)。

3,稳定性:不稳定。{2,4,1,2},2和1是一组,4和2是一组,进行希尔排序后,两个2的相对位置发生了变化。

4,过程分析: 

     初始:          81 94  11  96  12  35  17  95  28  58  41  75  15

  第一趟 d=5     35  17  11  28  12  41  75  15  96  58  81  94  95

  第二趟 d=3     28  12  11  35  15  41  58  17  94  75  81  96  95

  第三趟 d=1     11  12  15  17  28  35  41  58  75  81  94  95  96

5,伪码

void shellSort(vector<int> A){int N = A.size();int i, j, Incremnet;int tmp;for (Incremnet = N / 2; Incremnet > 0; Incremnet /= 2){for (int i = Incremnet; i < N; ++i){tmp = A[i];for (j = i; j >= Incremnet; j -= Incremnet){if (tmp < A[j - Incremnet])A[j] = A[j - Incremnet];elsebreak;}A[j] = tmp;}}}

三、堆排序

1,思想:将待排序的关键字存放在数组中,将这个数组看成是一棵完全二叉树的顺序表示,每个结点表示一个记录,第一个记录作为二叉树的根,以下各记录依次逐层从左到右顺序排列。

2,时间复杂度 O(nlogn),空间复杂度 O(1)。

3,稳定性:不稳定排序。{5,5,3}

4,过程分析

      对于堆排序,首先建初堆,再初始化大根堆,把栈顶元素和堆尾元素交换,最后对其前面的几个元素重新进行堆调整。

      http://www.cnblogs.com/chengxiao/p/6129630.html

5,伪码

#define leftChild(i) (2*(i)+1)void percDown(vector<int> A, int i,int N){int child;int tmp;for (tmp = A[i]; leftChild(i) < N; i = child){child = leftChild(i);if (child != N - 1 && A[child + 1]>A[child]) child++;if (tmp < A[child])A[i] = A[child];elsebreak;}A[i] = tmp;}void heapSort(vector<int> A, int N){int i;for (i = N / 2; i >= 0; i--)percDown(A, i,N);for (i = N - 1; i > 0; i--){swap(A[0], A[i]);percDown(A, 0,i);}}

四、归并排序

1,思想:将 n  个记录看成 n  个有序的子序列,每一个子序列的长度为 1,然后两两归并,得到 n/2 个长度为 2 的有序子序列,如此重复,直到得到一个长度为 n  的有序序列为止。

2,时间复杂度 O(nlogn)  , 空间复杂度 O(n)

3,稳定性:稳定排序。

4,过程分析

 初始         12  2  16  30  8  28  4  10  20  6  18

第一趟     (2  12)(16  30)(8  28)(4 10)(6  20)(18)

第二趟      (2  12  16  30)(4  8  10  28)(6  18  20)

第三趟      (2  4  8  10  12  16  28  30)(6  18  20)

第四趟       2  4  6  8  10  12  16  18  20  28  30

5,伪码

void mSort(vector<int> A, vector<int> tmp, int left, int right){int center;if (left < right){center = left + (right - left) / 2;mSort(A, tmp, left, center);mSort(A, tmp, center, right);Merge(A,tmp,left,center+1,right);}}void mergeSort(vector<int> A, int N){vector<int> tmp(N);mSort(A, tmp, 0, N - 1);}

五、快速排序

1,思想:从待排序记录中选取一个记录为枢纽元,其关键字为K,然后将其余关键字小于K的记录移到前面,而关键字大于K的记录移到后面,结果将待排序的记录序列分为两个子表,最后将关键字为K的记录插到其分界线的位置处。

      Tips:枢纽元的选择:一般做法是使用左端、右端和中心位置的三个元素的中值作为枢纽元。

2,时间复杂度:  平均 O(nlogn)    最坏 O(n^2).

3,稳定性:不稳定排序。{3,1,2,2}

4,过程分析

  初始         6  1  2  7  9  3  4  5  10  8

第一趟       8  1  2  7  9  3  4  5  10  6    (交换枢纽元和最后元素)

                   5  1  2  4  3  9  7  8  10  6    

第二趟       5  1  2  4  3  6  9  7  8  10    (枢纽元两边继续排序)

                   2  1  5  4  3  6  8  7  10  9

5,伪码

int median3(vector<int> A, int left, int right){  //  找出三个数中值并放在最后int center = left + (right - left) / 2;if (A[left] > A[center])swap(A[left], A[center]);if (A[left] > A[right])swap(A[left], A[right]);if (A[center] > A[right])swap(A[center], A[right]);swap(A[center], A[right]);return A[right];}#define Cutoff (3)void quickSort(vector<int> A,int left,int right){int i, j;int pivot;if (left + Cutoff <= right){pivot = median3(A, left, right);i = left, j = right;while (1){while (A[++i] < pivot){}while (A[--j] > pivot){}if (i < j)swap(A[i], A[j]);elsebreak;}swap(A[i], A[right]);quickSort(A, left, i - 1);quickSort(A, i + 1, right);}elseinsertionSort(A + left, right - left + 1); // 规模小于一定大小时,用插入排序}


0 0
原创粉丝点击