几种排序算法
来源:互联网 发布:常熟淘宝村 编辑:程序博客网 时间:2024/05/01 13:55
本帖依据学习进度持续更新
《数据结构与算法分析-c语言描述》学到第七章,是时候该系统的学习一下排序算法了。首先学到的是插入排序,算法就不赘述了,书上博客上到处都有。书上的两个定理还不太明白:
插入排序
定理7.1
N个互异数的数组的平均逆序数是N(N-1)/4。
定理7.2
通过交换相邻元素进行排序的任何算法平均需要Ω(N^2)时间。
插入排序的算法复杂度应该为O(N^2)才对。
下面是我的测试用例:
void insertionSort(elementType A[], int N){Int j, P;elementType Tmp;for(P = 1; P < N; P++){Tmp = A[P];for(j = P; j > 0 && A[j – 1] > Tmp; j--)A[j] = A[j – 1];A[j] = Tmp;}}
希尔排序
希尔排序的最后一样增量是1,所以是直接插入排序,但移动次数比直接插入排序少,代入数组测试:
#include<stdio.h>#define elementType intvoid shellSort(elementType A[], int N){ int i, j, Increment; elementType Tmp; for(Increment = N/2; Increment > 0; Increment /= 2) for(i = Increment; i < N; i++) { Tmp = A[i]; for(j = i; j >= Increment && Tmp < A[j-Increment]; j -= Increment) A[j] = A[j-Increment]; A[j] = Tmp; }}void main(){ int i; int a[] = {81,94,11,96,12,35,17,95,28,58,41,75,15}; shellSort(a, 13); for(i = 0; i < 13; i++) printf("%d ", a[i]);}
堆排序
我们为了找出一列数第K个最小的数引入二叉堆,最小堆总能从根节点输出最小值,一直使用deleteMin函数就能输出一列排序好的数,因为最小值最先输出,所以这个数列是递减的。由此我们可以得出如果建一个最大堆,使用deleteMax函数就能输出一列递增的序列。时间复杂度为O(NlogN)。
#include<stdio.h>#define leftChild(i) (2*i+1)void Swap(int *a, int *b){int Tmp = *a;*a = *b;*b = Tmp;}void percDown(int A[], int i, int N){int Child, Tmp;for(Tmp = A[i]; leftChild(i) < N; i = Child){Child = leftChild(i);if(Child != N-1 && A[Child + 1] > A[Child])Child++;if(A[Child] > Tmp)A[i] = A[Child];elsebreak;}A[i] = Tmp;}void heapSort(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);}}void main(){int i;int a[] = {81,94,11,96,12,35,17,95,28,58,41,75,15}; heapSort(a, 13);for(i = 0; i < 13; i++)printf("%d ", a[i]);}
归并排序
该算法是经典的分治策略,基本的操作是合并两个已排序的表,放到第三个表中。而已排序的表又可以通过归并排序本身递归得到。
#include<stdio.h>#include<stdlib.h>#define elementType intvoid Merge(elementType A[], elementType Tmp[], int Lpos, int Rpos, int rightEnd){ int i, leftEnd, numElements, Tmppos; leftEnd = Rpos - 1; Tmppos = Lpos; numElements = rightEnd - Lpos + 1; while(Lpos <= leftEnd && Rpos <= rightEnd) if(A[Lpos] <= A[Rpos]) Tmp[Tmppos++] = A[Lpos++]; else Tmp[Tmppos++] = A[Rpos++]; while(Lpos <= leftEnd) Tmp[Tmppos++] = A[Lpos++]; while(Rpos <= rightEnd) Tmp[Tmppos++] = A[Rpos++]; for(i = 0; i < numElements; i++, rightEnd--) A[rightEnd] = Tmp[rightEnd];}void Msort(elementType A[], elementType Tmp[], int Left, int Right){ int Center; if(Left < Right) { Center = (Left + Right) / 2; Msort(A, Tmp, Left, Center); Msort(A, Tmp, Center + 1, Right); Merge(A, Tmp, Left, Center + 1, Right); }}void mergeSort(elementType A[], int N){ elementType *Tmp; Tmp = malloc(N * sizeof(elementType)); if(Tmp != NULL) { Msort(A, Tmp, 0, N - 1); free(Tmp); } else printf("No space for Tmp array");}void main(){ int i; int a[] = {81,94,11,96,12,35,17,95,28,58,41,75,15}; mergeSort(a, 13); for(i = 0; i < 13; i++) printf("%d ", a[i]);}
快速排序
书上的一种以三数中值作为基准值的快速排序,当数组长度小于3的时候选用插入排序,用的递归实现。
#include<stdio.h>#define Cutoff 3void Swap(int *a, int *b){ int Tmp = *a; *a = *b; *b = Tmp;}void insertionSort(int A[], int N){ int tmp; int j, p; for( p = 1; p < N; p++ ) { tmp = A[p]; for( j = p; j > 0 && A[j -1] > tmp; j -- ) A[j] = A[j-1]; A[j] = tmp; } }int Median3(int A[], int Left, int Right){int Center = (Left + Right) / 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 - 1]);return A[Right - 1];}void Qsort(int A[], int Left, int Right){ int i, j, Pivot; if(Left + Cutoff <= Right) {i = Left;j = Right - 1;Pivot = Median3(A, Left, Right);for(; ; ){while(A[++i] < Pivot){}while(A[--j] > Pivot){}if(i < j)Swap(&A[i], &A[j]);elsebreak;}Swap(&A[i], &A[Right - 1]); Qsort(A, Left, i - 1);Qsort(A, i + 1, Right);}elseinsertionSort(A + Left, Right - Left + 1);}void quickSort(int A[], int N){ Qsort(A, 0, N - 1);}void main() { int i; int a[] = {81,94,11,96,12,35,17,95,28,58,41,75,15}; quickSort(a, 13); for(i = 0; i < 13; i++) printf("%d ", a[i]); }
下面是自己写的以第一个数作为基准值的快速排序。实际上这中基准值的选取是非常糟糕的,如果输入是预排序的或是反序的,第一次分割就总是分割到一边,时间复杂度为O(N^2),仅作为编程练习。
#include<stdio.h>#define Cutoff 3void Swap(int *a, int *b){ int Tmp = *a; *a = *b; *b = Tmp;}void Qsort(int A[], int Left, int Right){ int i, j, Pivot; <span style="white-space:pre"></span>if(Left < Right) {Pivot = A[Left];i = Left;j = Right - 1;Swap(&A[Left], &A[Right]);while(i <= j){while(A[i] < Pivot)i++;while(A[j] > Pivot)j--;if(i < j){Swap(&A[i], &A[j]);i++;j--;}elsebreak;}Swap(&A[i], &A[Right]);Qsort(A, Left, i - 1);Qsort(A, i + 1, Right);}}void quickSort(int A[], int N){ Qsort(A, 0, N - 1);}void main() { int i; int a[] = {81,94,11,96,12,35,17,95,28,58,41,75,15}; quickSort(a, 13); for(i = 0; i < 13; i++) printf("%d ", a[i]); }
//以第一个元素作为基准,单向划分的快速排序#include<stdio.h>void Swap(int *a, int *b){ int Tmp = *a; *a = *b; *b = Tmp;}void Qsort(int A[], int Left, int Right){ int i, j, Pivot; if(Left >= Right) return; Pivot = A[Left]; int pos = Left; for(i = Left+1; i <= Right; ++i) {if(A[i] < Pivot) Swap(&A[++pos], &A[i]); } Swap(&A[pos], &A[Left]); Qsort(A, Left, pos - 1); Qsort(A, pos + 1, Right);}void quickSort(int A[], int N){ Qsort(A, 0, N - 1);}
0 0
- 几种排序算法
- 几种排序算法!
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 几种排序算法
- 09-1. Hashing
- Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI
- iOS 自定义无限循环滚动广告动画控件
- asmca可以看到磁盘,dbca看不到磁盘使用情况
- js中substring和substr的用法
- 几种排序算法
- Android java.lang.StackOverflowError
- 最值钱的30句话,总有一句让你有收获
- String类,练习
- Valid Palindrome
- 最全模板的分享功能插件
- TCP/IP协议解析与进阶
- 回答的很好,收藏了
- matlab高斯1D模糊+差分(频域实现)