一、 插入排序
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];
else
break;
}
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];
else
break;
}
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]);
else
break;
}
swap(A[i], A[right]);
quickSort(A, left, i - 1);
quickSort(A, i + 1, right);
}
else
insertionSort(A + left, right - left + 1); // 规模小于一定大小时,用插入排序
}