排序算法:(1) 直接插入排序 (2) 折半插入排序(3) 冒泡排序 (4) 简单选择排序 (5) 快速排序(6) 堆排序 (7) 归并排序【算法分析】(1)直接插入排序;它是一种最简单的排序方法,它的基本操作是将一个记录插入到已排好的序的有序表中,从而得到一个新的、记录数增加1的有序表。
(2)折半插入排序:插入排序的基本操作是在一个有序表中进行查找和插入,我们知道这个查找操作可以利用折半查找来实现,由此进行的插入排序称之为折半插入排序。
折半插入排序所需附加存储空间和直接插入相同,从时间上比较,折半插入排序仅减少了关键字间的比较次数,而记录的移动次数不变。
(3)冒泡排序:比较相邻关键字,若为逆序(非递增),则交换,最终将最大的记录放到最后一个记录的位置上,此为第一趟冒泡排序;对前n-1记录重复上操作,确定倒数第二个位置记录;……以此类推,直至的到一个递增的表。
(4)简单选择排序:通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之。
(5)快速排序:它是对冒泡排序的一种改进,基本思想是,通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
(6)堆排序: 使记录序列按关键字非递减有序排列,在堆排序的算法中先建一个“大顶堆”,即先选得一个关键字为最大的记录并与序列中最后一个记录交换,然后对序列中前n-1记录进行筛选,重新将它调整为一个“大顶堆”,如此反复直至排序结束。
(7)归并排序:归并的含义是将两个或两个以上的有序表组合成一个新的有序表。
假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种排序称为2-路归并排序。
【算法实现】(1)直接插入排序:void InsertSort(SqList &L){for(i=2;i<=L.length ;i++)if(L.elem[i]<L.elem[i-1]){L.elem[0]=L.elem [i]; //复制为哨兵 L.elem [i]=L.elem [i-1];for(j=i-2;L.elem [j]>L.elem[0];j--)L.elem [j+1]=L.elem [j];L.elem [j+1]=L.elem[0];}}(2)折半插入排序:void BInsertSort(SqList &L){//对顺序表L作折半插入排序for(i=2;i<=L.length ;i++){L.elem[0]=L.elem [i];low=1; high=i-1;while(low<=high){m=(low+high)/2;if(L.elem [0]>L.elem [m]) low=m+1;else high=m-1;}for(j=i-1;j>=high+1;j--)L.elem [j+1]=L.elem [j];L.elem [high+1]=L.elem[0];}}(3)冒泡排序:void BubbleSort(SqList &L){for(i=L.length;i>=2;i--)for(j=1;j<i;j++)if(L.elem[j]>L.elem [j+1])L.elem [j]↔L.elem [j+1];}(4)简单选择排序:void SelectSort(SqList &L){for(int i=1;i<=L.length-1 ;i++){j=SelectMinKey(L,i); //在L.elem[i..L.length]中选择最小记录if(i!=j) L.elem [i]↔L.elem [index];}}(5)快速排序:int Partition(SqList &L,int low,int high){//将L.elem[low...high]一分为二pivot=L.elem[low];while(low<high){while(low<high&&L.elem[high]>=pivot) high--;L.elem[low]↔L.elem[high];while(low<high&&L.elem[high]<=pivot) low++;L.elem[low]↔L.elem[high];}return low;}void QSort(SqList &L,int low,int high){//对顺序表L中的子序列L.elem[low...high]进行快速排序if(low<high){pivot=Partition(L,low,high);QSort(L,low,pivot-1);QSort(L,pivot+1,high);}}void QuickSort(SqList &L) {//对顺序表L作快速排序QSort(L,1,L.length);}(6)堆排序:void HeapAdjust(SqList &L,int s,int m){L.elem[0]=L.elem[s];for(j=2*s;j<=m;j*=2){if(j<m&&L.elem[j]<L.elem[j+1]) j++;if(!(L.elem[0]<L.elem[j])) break;L.elem[s]=L.elem[j];s=j;}L.elem[s]=L.elem[0];}void HeapSort(SqList &L){for(i=L.length/2;i>0;i--)HeapAdjust(L,i,L.length);for(i=L.length;i>1;i--){LL.elem[1]↔ L.elem[i];HeapAdjust(L,1,i-1);}}(7)归并排序:void Merge(SqList L,SqList &L1,int i,int m,int n){//将有序的L[i..m]和L[m+1..n]归并为有序的L1[i..n] for(j=m+1,k=i;i<=m&&j<=n;++k)if(L.elem[i]<L.elem[j]) L1.elem[k]=L.elem[i++];else L1.elem[k]=L.elem[j++];if(i<=m) L1[k..n] =L[i..m];if(j<=n) L1[k..n] =L[j..n];}void MSort(SqList L,SqList &L1,int s,int t){//将L[s..t]归并排序为L1[s..t]。
if(s==t) L1.elem[s]=L.elem[s];else{m=(s+t)/2;MSort(L,L2,s,m);MSort(L,L2,m+1,t);Merge(L2,L1,s,m,t);}}void MergeSort(SqList &L){//对顺序表L作归并排序MSort(L,L,1,L.length);}【源代码】见.cpp文件。
【算法分析】【总结】简单排序中直接插入排序最好,快速排序最快,当文件为正序,直接插入排序和冒泡排序均最佳。
排序算法的选择:1.若n(待排序的记录数)较小,可采用直接插入排序或选择排序。
当记录规模较小时,直接插入排序较好:否则因为选择移动的记录数少于直接插入,应选选择排序。
2.若文件初始状态基本有序(正序),则应选用直接插入排序、冒泡排序或快速排序。
3.若n较大,则应采用时间复杂度为O(nlgn)的排序算法:快速排序、堆排序极品归并排序。
当待排序的关键字是随机分布时,快速排序的平均时间最短;堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。
这两种排序都是不稳定的;若要求排序稳定,则可选用归并排序。
#include<stdio.h>#include<stdlib.h>typedef struct //顺序表存储结构{int * elem;int length;}SqList;int main(void){SqList L;SqList L1;void InsertSort(SqList &L); //直接插入排序 void BInsertSort(SqList &L); //折半插入排序void BubbleSort(SqList &L); //冒泡排序void SelectSort(SqList &L); //简单选择排序void QuickSort(SqList &L); //快速排序void QSort(SqList &L,int low,int high);int Partition(SqList &L,int low,int high);void HeapSort(SqList &L); //堆排序void HeapAdjust(SqList &L,int s,int m);void MergeSort(SqList &L); //归并排序void MSort(SqList L,SqList &L1,int s,int t);void Merge(SqList L,SqList &L1,int i,int m,int n);int n;int * p;printf("请输入顺序表的长度:");scanf("%d",&n);if((p=(int *)malloc((n+1)*sizeof(int)))==0) //动态分配顺序表存储空间{printf("Not able to allocate memory.\n");exit(1);}L.length=n;if((p=(int *)malloc((n+1)*sizeof(int)))==0) //动态分配顺序表存储空间{printf("Not able to allocate memory.\n");exit(1);}L1.elem=p;L1.length=n;printf("请输入%d个整数:\n",n); //输入一组待排序的数据for(int i=1;i<=L.length;i++)scanf("%d",&L.elem[i]);printf("选择排序算法:\n");printf("1 直接插入排序\n");printf("2 折半插入排序\n");printf("3 冒泡排序\n");printf("4 简单选择排序\n");printf("5 快速排序\n");printf("6 堆排序\n");printf("7 归并排序\n");int change=0;scanf("%d",&change);switch(change){case 1: InsertSort(L);break;case 2: BInsertSort(L);break;case 3: BubbleSort(L);break;case 4: SelectSort(L);break;case 5: QuickSort(L);break;case 6: HeapSort(L);break;case 7: MergeSort(L);break;default:break;}printf("排序后为:");for(i=1;i<=L.length;i++)printf("%6d",L.elem[i]);printf("\n");return 0;}void InsertSort(SqList &L){int i=0,j=0;for(i=2;i<=L.length ;i++)if(L.elem[i]<L.elem[i-1]){L.elem[0]=L.elem [i]; //复制为哨兵L.elem [i]=L.elem [i-1];for(j=i-2;L.elem [j]>L.elem[0];j--)L.elem [j+1]=L.elem [j];L.elem [j+1]=L.elem[0];}}void BInsertSort(SqList &L){int i=0,j=0,low=0,high=0,m=0;for(i=2;i<=L.length ;i++){L.elem[0]=L.elem [i];low=1;high=i-1;while(low<=high){m=(low+high)/2;if(L.elem [0]>L.elem [m])low=m+1;elsehigh=m-1;}for(j=i-1;j>=high+1;j--)L.elem [j+1]=L.elem [j];L.elem [high+1]=L.elem[0];}}void BubbleSort(SqList &L){int i=0,j=0;for(i=L.length;i>=2;i--)for(j=1;j<i;j++){if(L.elem[j]>L.elem [j+1]){L.elem[0]=L.elem [j];L.elem [j]=L.elem [j+1];L.elem [j+1]=L.elem[0];}}}void SelectSort(SqList &L){int index=0;for(int i=1;i<=L.length-1 ;i++){index=i;for(int j=i+1;j<=L.length ;j++)if(L.elem [j]<L.elem [index])index=j;if(i!=index){L.elem[0]=L.elem [i];L.elem [i]=L.elem [index];L.elem [index]=L.elem[0];}}}//快排int Partition(SqList &L,int low,int high){//将L.elem[low...high]一分为二int pivot=0; //用子表第一个记录作枢轴pivot=L.elem[low];while(low<high){while(low<high&&L.elem[high]>=pivot)high--;L.elem[0]=L.elem[low];L.elem[low]=L.elem[high];L.elem[high]=L.elem[0];while(low<high&&L.elem[high]<=pivot)low++;L.elem[0]=L.elem[low];L.elem[low]=L.elem[high];L.elem[high]=L.elem[0];}return low;}void QSort(SqList &L,int low,int high){//对顺序表L中的子序列L.elem[low...high]进行快速排序 int pivot=0;if(low<high){pivot=Partition(L,low,high);QSort(L,low,pivot-1);QSort(L,pivot+1,high);}}void QuickSort(SqList &L){QSort(L,1,L.length);}//堆排void HeapAdjust(SqList &L,int s,int m){int j=0;L.elem[0]=L.elem[s];for(j=2*s;j<=m;j*=2){if(j<m&&L.elem[j]<L.elem[j+1])j++;if(!(L.elem[0]<L.elem[j]))break;L.elem[s]=L.elem[j];s=j;}L.elem[s]=L.elem[0];}void HeapSort(SqList &L){int i=0;for(i=L.length/2;i>0;i--)HeapAdjust(L,i,L.length);for(i=L.length;i>1;i--){L.elem[0]=L.elem[1];L.elem[1]=L.elem[i];L.elem[i]=L.elem[0];HeapAdjust(L,1,i-1);}}//归并void Merge(SqList L,SqList &L1,int i,int m,int n){int j=0,k=0,p=0,q=0;for(j=m+1,k=i;i<=m&&j<=n;++k){if(L.elem[i]<L.elem[j])L1.elem[k]=L.elem[i++];elseL1.elem[k]=L.elem[j++];}if(i<=m)for(p=k,q=i;q<=m;p++,q++)L1.elem[p]=L.elem[q];if(j<=n)for(p=k,q=j;q<=n;p++,q++)L1.elem[p]=L.elem[q];}void MSort(SqList L,SqList &L1,int s,int t){SqList L2;int * p;if((p=(int *)malloc((t-s+1)*sizeof(int)))==0) //动态分配顺序表存储空间{printf("Not able to allocate memory.\n");exit(1);}L2.elem=p;L2.length=t-s+1;int m=0;if(s==t)L1.elem[s]=L.elem[s];else{m=(s+t)/2;MSort(L,L2,s,m);MSort(L,L2,m+1,t);Merge(L2,L1,s,m,t);}}void MergeSort(SqList &L){MSort(L,L,1,L.length);}。