简单排序
1、冒泡排序
void bulle_sort(ElementType A[], int N){
for(int p = N-1; p >= 0; p--){
int flag = 0;
for(int i = 0; i < p; i++){
if(A[i] > A[i+1]){
swap(A[i], A[i+1]);
int flag = 1;
}
}
if(flag == 0) break;
}
}
2、插入排序
void insertion_sort(ElementType A[], int N){
for(int p = 1; p < N; p++){
tem = A[p];
//这里的i > 0必须放在前面,否则有可能会出现下标越界的错误。
for(int i = p; i >= 1 && A[i-1] > tem; i--)
A[i] = A[i-1];
A[i] = tem;
}
}
时间复杂度下界
定理: 任意N个不同元素组成的序列,平均有N(N-1)/4个逆序对。
交换两个相邻元素正好消去一个逆序对。
定理: 任何仅以交换相邻两元素来排序的算法,其平均时间复杂度下届为 N的平方 级。
3、希尔排序
void shell_sort(ElementType A[], int N){
for(int D = N/2; D > 0; D /= 2){
//对每一个D做一次选择排序
for(p = D; p < N; p++){
tem = A[p];
for(int i = p; i >= D && A[i-D] > tem; i -= D)
A[i] = A[i-D];
A[i] = tem;
}
}
}
4、选择排序
void selection_sort(ElementType A[], int N){
for(int i = 0; i < N; i++){
//从i到N-1中找到最小值
MinPosition = ScanForMin(A, i, N-1);
Swap(A[i], A[MinPosition]);
}
}
5、堆排序
void heap_sort(ElementType A[], int N){
//构造最大堆,其中PercDown是一个"向下过滤函数",i=N/2表示i为最后一个节点的父节点。
for(int i = N/2; i >= 0; i--)
//此函数就是将一个堆调整为最大堆的函数
//第二个参数表示以此节点为根节点调整最大堆,第三个参数表示这个最大堆一共有几个元素。
PercDown(A, i, N);
for(int i = N-1; i>0; i--){
Swap(A[0], A[i]);
PercDown(A, 0, i);
}
}
6、归并排序
// L 左边起始位置,R 右边起始位置, RightEnd 右边终点位置
void merge(ElementType A[], ElementType TmpA[], int L, int R, int RightEnd){
//假设左右两列紧挨着
int LeftEnd = R - 1;
Tmp = L;
ElementNum = RightEnd - L + 1;
while( L <= LeftEnd && R <= RightEnd ){
if( A[L] < A[R] )
TmpA[Tmp++] = A[L++];
else
TmpA[Tmp++] = A[R++];
}
while( L <= LeftEnd )
TmpA[Tmp++] = A[L++];
while( R <= RightEnd )
TmpA[Tmp++] = A[R++];
for( int i = 0; i < ElementNum; i++, RightEnd--)
A[RightEnd] = TmpA[RightEnd];
}
//递归的调用merge方法,完成归并排序
void Msort(ElementType A[], ElementType TmpA[], int L, int RightEnd){
int center = (RightEnd + L) / 2;
if(L < RightEnd){
Msort(A, TmpA, L, center);
Msort(A, TmpA, center+1, RightEnd);
merge(A, TmpA, L, center+1, RightEnd);
}
}
//统一排序的接口
void merge_sort(ElementType A[], int N){
ElementType *TmpA;
TmpA = (ElementType)malloc(N * sizeof(ElementType));
if(TmpA != NULL){
Msort(A, TmpA, 0, N-1);
free(TmpA);
}else
Error("空间不足");
}
非递归算法
void merge_pass(ElementType A[], ElementType TmpA[], int N, int length){
//这一步只排前面成对的,最后一段剩下。
for(int i = 0; i < N - 2*length; i += 2*length )
//这个merge1比起merge来,不把最后的结果复制到A中,而是保留在TmpA中
merge1(A, TmpA, i, i+length, i + 2*length-1);
if( i + length < N)
merge1(A, TmpA, i, i+length, N-1);
else
for(int j = i; j < N; j++) TmpA[j] = A[j];
}
//统一排序的接口
void merge_sort(ElementType A[], int N){
int length = 1;
ElementType *TmpA;
TmpA = (ElementType)malloc(N * sizeof(ElementType));
if(TmpA != NULL){
while(length < N){
merge_pass(A, TmpA, N, length);
length *= 2;
merge_pass(TmpA, A, N, length);
length *= 2;
}
free(TmpA);
}else
Error("空间不足");
}
7、快速排序
快速排序适合大规模数据,如果数据规模小,可以不做快排,直接调用简单排序解决问题。
//第一步,选主元,取头、中、尾的中位数
ElementType Median3(ElementType 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 QuickSort(ElementType A[], int Left, int Right){
if( Cottoff <= Right - Left ){
//调整好主元位置。
ElementType Pivot = Median3(A, Left, Right);
//设置好指针位置
int i = Left;
int j = Right-1;
for(;;){
while(A[++i] < Pivot){}
while(A[--j] > Pivot){}
if( i < j )
Swap(A[i], A[j]);
else
break;
}
Swap(A[i], A[Right-1]);
QuickSort(A, Left, i-1);
QuickSort(A, i+1, Right);
}
else
insertion_sort(A + Left, Right - Left + 1);
}
//第三步,封装
void quick_sort(ElementType A[], int N){
QuickSort(A, 0, N-1);
}
8、其他排序
表排序:
当一个元素非常大,不能忽略元素交换的时间的时候,需要使用表排序,一种间接排序,会得出一个下标的顺序,不去改变元素本身的顺序。
基数排序:
适用于多关键字排序,按照不同的关键字多次利用桶排序完成多关键字排序。