给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。
本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:
数据1:只有1个元素;数据2:11个不相同的整数,测试基本正确性;数据3:103个随机整数;数据4:104个随机整数;数据5:105个随机整数;数据6:105个顺序整数;数据7:105个逆序整数;数据8:105个基本有序的整数;数据9:105个随机正整数,每个数字不超过1000。输入格式: 输入第一行给出正整数N(≤100000 ),随后一行给出N个(长整型范围内的)整数,其间以空格分隔。
输出格式: 在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。
输入样例:
11 4 981 10 -17 0 -20 29 50 8 43 -5输出样例:
-20 -17 -5 0 4 8 10 29 43 50 981i从0开始递增,如果第i个元素小于后一个元素,就交换它们的位置,这样可以让最大的元素移动到最后。然后让次大的元素移动到倒数第二个位置,一直循环。
时间复杂度:最好情况(顺序)T=O(N);最坏情况(逆序) T=O(N2) 稳定性:稳定 。
前面i-1个元素是有序的,插入第i个元素,寻找合适的位置,让这i个元素也是有序的。
时间复杂度:最好情况(顺序)T=O(N);最坏情况(逆序) T=O(N2) 稳定性:稳定 关于逆序对:冒泡排序法和插入排序法每次都消除一个 逆序对,所以其时间复杂度和数据规模以及逆序对的数量I有关。T(N,I)=O(N,I).所以如果元素基本有序,那么插入排序是简单且高效的。 任意N个不同元素组成的序列平均有N(N-1)/4个逆序对,所以如果仅以交换相邻两元素来排序的算法,其平均时间复杂度为Ω(N2)。
第一行相同颜色数字的间隔为5,每一种颜色单独进行插入排序。然后间隔为3,每一种颜色单独进行插入排序。最后间隔为1进行排序,相当于一次插入排序。
时间复杂度:如果增量序列是D=N/2,然后每次D除以2,最坏情况是T=θ(N2)。原因是相邻的D不互质,小的D可能不会发挥作用。 使用其他的增量序列,Hibbard序列和Sedgewick序列可以有效减小时间复杂度。 稳定性:不稳定。比如2 10 8 8,在增量元素是2,也就是间隔为2进行排序时,第二个8会和10交换位置,导致两个8的相对位置也发生了变化。
找到未排序部分的最小元素,换到先前有序部分的末尾后一个,此时有序部分多了一个元素,未排序部分少了一个元素。
时间复杂度:用直接扫描所有元素的方式找最小,时间复杂度为T=θ(N2) 稳定性:不稳定。比如序列5 8 5 2 9,第一次扫描最小是2,2将和第一个5进行交换,这样两个5的相对位置发生了改变。
1.最小堆排序。建立最小堆,每次弹出根结点元素到临时数组,最后再把临时数组的元素都复制回原来的数组。 2.最大堆排序。建立最大堆,然后将最大堆头结点和最后一个结点交换,也就是把最大元素放到了数组的尾巴上。
时间复杂度:最小堆排序需要临时数组,复制数据也需要时间。T(N)=O(NlogN) 最大堆排序平均时间复杂度为2NlogN-O(NloglogN),可以看出比NlogN小一点 稳定性:不稳定。比如序列1 7 3 7,整理成最大堆时,第一个7会到堆顶,然后会被换到数组末尾,这样两个7的相对位置就发生了改变。
基本思想是把两个有序序列归并成一个有序序列。如果采用递归算法,就是将一整个序列分成左右两个,先把左右序列都调整成有序的,然后归并左右序列。如果采用非递归算法,使用一个变量length,先归并length=1的序列,然后归并length=2的序列,一直到length大于N.
递归算法:
void Merge(int A[], int *temp, int L, int R, int RightEnd) { int LeftEnd = R - 1, tmp = L, Num = RightEnd - L + 1, i; while( L <= LeftEnd && R <= RightEnd ){ if( A[L] <= A[R] ) temp[tmp++] = A[L++]; else temp[tmp++] = A[R++]; } while( L <= LeftEnd ) temp[tmp++] = A[L++]; while( R <= RightEnd ) temp[tmp++] = A[R++]; for( i=0; i<Num; ++i,--RightEnd ) A[RightEnd] = temp[RightEnd]; } void MSort(int A[], int *temp, int L, int RightEnd) { int center; if( L < RightEnd ){ center = (L + RightEnd) / 2; MSort( A, temp, L, center ); MSort( A, temp, center+1, RightEnd ); Merge( A, temp, L, center+1, RightEnd ); } } void Merge_Sort1(int A[], int N) { int *temp; temp = (int*)malloc(N*sizeof(int)); if(temp!=NULL){ MSort(A, temp, 0, N-1); free(temp); } }非递归算法:
void Merge(int A[], int *temp, int L, int R, int RightEnd) { int LeftEnd = R - 1, tmp = L, Num = RightEnd - L + 1, i; while( L <= LeftEnd && R <= RightEnd ){ if( A[L] <= A[R] ) temp[tmp++] = A[L++]; else temp[tmp++] = A[R++]; } while( L <= LeftEnd ) temp[tmp++] = A[L++]; while( R <= RightEnd ) temp[tmp++] = A[R++]; for( i=0; i<Num; ++i,--RightEnd ) A[RightEnd] = temp[RightEnd]; } void Merge_pass(int A[], int *temp, int N, int length) { int i, j; for( i=0; i<=N-2*length; i+=2*length ) Merge( A, temp, i, i+length, i+2*length-1 ); if( i+length < N ) Merge( A, temp, i, i+length, N-1 ); else for( j=i; j!=N; ++j ) temp[j] = A[j]; } void Merge_sort2(int A[], int N) { int length; int *temp; length = 1; temp = (int *)malloc(N*sizeof(int)); if( temp!=NULL ){ while( length < N ){ Merge_pass( A, temp, N, length ); length *= 2; Merge_pass( temp, A, N, length ); length *= 2; } free( temp ); } }时间复杂度:T(N)=O(NlogN) 稳定性:稳定
