排序
思考:堆排为什么比快排慢?:http://mindhacks.cn/2008/06/13/why-is-quicksort-so-quick/
总结各种排序算法的经典实现:
#include<stdio.h> #define MAXV 1E9 /* ** N是正整数 ** 讨论从小到大 ** 基于排序的比较 ** 只讨论内部排序 ** 稳定性:任意两个相等的数据排序前后相对位置不发生变化 ** 没有一种排序是任何情况下都表现最好的 ** 逆序对:对于i<j,A[i] > A[j] ** 任意N个不同元素组成的序列平均具有 N(N-1)/4 */ void PercDown( ElementType A[], int p, int N ) { int Parent, Child; ElementType X; X = A[p]; /* 取出根结点存放的值 */ for( Parent=p; (Parent*2+1)<N; Parent=Child ) { Child = Parent * 2 + 1; if( (Child!=N-1) && (A[Child]<A[Child+1]) ) Child++; /* Child指向左右子结点的较大者 */ if( X >= A[Child] ) break; /* 找到了合适位置 */ else /* 下滤X */ A[Parent] = A[Child]; } A[Parent] = X; } int ScanForMin(A,i,N-1){ int minnum = MAXV; int minposition = -1; for(i; i <= N-1; i++){ if(A[i] < res){ res = A[i]; minposition = i; } } return minposition; } void Bubble_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]); flag = 1; } } if( flag == 0) break; } } // best:T = O(N); worse:T = O(N^2); 稳定。 void Insertion_Sort( ElementType A[], int N){ for(int P = 1; P < N; P++){ int Tmp = A[P]; for(int i = P; i > 0 && A[i-1] > Tmp; i--){ A[i] = A[i-1]; } A[i] = Tmp; } } // best:T = O(N); worse:T = O(N^2); 稳定。 /* 逆序对:对于i<j,A[i] > A[j]*/ /* 任意N个不同元素组成的序列平均具有 N(N-1)/4 */ void Shell_Sort(ElementType A[], int N){ for( int D = N/2; D > 0; D/=2){ for(int P = D;P < N; P++){ int Tmp = A[P]; for(int i = P; i >= D && A[i-D] > Tmp; i -= D){ A[i] = A[i-D]; } A[i] = Tmp; } } } //Sedgewick 增量序列可以加速;不稳定。 void Selection_Sort ( ElementType A[]; int N){ for(int i = 0; i < N; i++){ int MinPosition = ScanForMin(A,i,N-1); Swap( &A[i],&A[MinPosition]); } }// T = O(N^2); 可用堆加速。 void Heap_Sort ( ElementType A[]; int N){ 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); } } // 适合数据量大,适合部分排序,找出最大或最小的N个数 void Merge(ElementType A[], ElempentType TmpA[],int L, int R,int RightEnd){ int leftEnd = R - 1; int Tmp = L; //存放结果的数组初始位置 NumElements = 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( i = 0; i < NumElements; i++, RightEnd -- ){ A[RightEnd] = TmpA[RightEnd]; } } void Msort( ElementType A[], ElementType TmpA[], int L, int RightEnd ) { int Center; if ( L < RightEnd ) { Center = (L+RightEnd) / 2; Msort( A, TmpA, L, Center ); /* 递归解决左边 */ Msort( A, TmpA, Center+1, RightEnd ); /* 递归解决右边 */ Merge( A, TmpA, L, Center+1, RightEnd ); /* 合并两段有序序列 */ } } //T(N) = O(NlogN);稳定。 void Merge_Sort1( ElementType A[], int N ) { /* 归并排序 */ ElementType *TmpA; TmpA = (ElementType *)malloc(N*sizeof(ElementType)); if ( TmpA != NULL ) { Msort( A, TmpA, 0, N-1 ); free( TmpA ); } else printf( "空间不足" ); } //稳定;需要额外空间;一般用于外排序 void Merge_pass( ElementType A[], ElementType TmpA[], int N, int length ) { /* 两两归并相邻有序子列 */ int i, j; for ( i=0; i <= N-2*length; i += 2*length ) Merge( A, TmpA, i, i+length, i+2*length-1 ); //可优化,merge可不必执行最后一步。 if ( i+length < N ) /* 归并最后2个子列*/ Merge( A, TmpA, i, i+length, N-1); else /* 最后只剩1个子列*/ for ( j = i; j < N; j++ ) TmpA[j] = A[j]; } void Merge_Sort2( ElementType A[], int N ) //非递归merge { int length; ElementType *TmpA; length = 1; /* 初始化子序列长度*/ TmpA = 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 printf( "空间不足" ); }