#include "stdio.h " #include "stdlib.h " #define Max 100 //假设文件长度 typedef struct{ //定义记录类型 int key; //关键字项 }RecType; typedef RecType SeqList[Max+1]; //SeqList为顺序表,表中第0个元素作为哨兵 int n; //顺序表实际的长度 //==========直接插入排序法====== void InsertSort(SeqList R) { //对顺序表R中的记录R[1¨n]按递增序进行插入排序 int i,j; for(i=2;i <=n;i++) //依次插入R[2],……,R[n] if(R[i].key <R[i-1].key){ //若R[i].key大于等于有序区中所有的keys,则R[i]留在原位 R[0]=R[i];j=i-1; //R[0]是R[i]的副本 do { //从右向左在有序区R[1¨i-1]中查找R[i] 的位置 R[j+1]=R[j]; //将关键字大于R[i].key的记录后移 j--; }while(R[0].key <R[j].key); //当R[i].key≥R[j].key 是终止 R[j+1]=R[0]; //R[i]插入到正确的位置上 }//endif } //==========冒泡排序======= typedef enum{FALSE,TRUE} Boolean; //FALSE为0,TRUE为1 void BubbleSort(SeqList R) { //自下向上扫描对R做冒泡排序 int i,j; bool exchange; //交换标志 for(i=1;i <n;i++) { //最多做n-1趟排序 exchange=false; //本趟排序开始前,交换标志应为假 for(j=n-1;j> =i;j--){ //对当前无序区R[i¨n] 自下向上扫描 if(R[j+1].key <R[j].key){ //两两比较,满足条件交换记录 R[0]=R[j+1]; //R[0]不是哨兵,仅做暂存单元 R[j+1]=R[j]; R[j]=R[0]; exchange=true; //发生了交换,故将交换标志置为真 } if(! exchange) return; //本趟排序未发生交换,提前终止算法 }// endfor(为循环) } //==========快速排序======= //1.========一次划分函数===== int Partition(SeqList R,int i,int j) { // 对R[i¨j]做一次划分,并返回基准记录的位置 RecType pivot=R[i]; //用第一个记录作为基准 while(i <j) { //从区间两端交替向中间扫描,直到i=j while(i <j &&R[j].key> =pivot.key) //基准记录pivot相当与在位置i上 j--; //从右向左扫描,查找第一个关键字小于pivot.key的记录R[j] if(i <j) //若找到的R[j].key < pivot.key,则 R[i++]=R[j]; //交换R[i]和R[j],交换后i指针加1 while(i <j &&R[i].key <=pivot.key) //基准记录pivot相当与在位置j上 i++; //从左向右扫描,查找第一个关键字小于pivot.key的记录R[i] if(i <j) //若找到的R[i].key > pivot.key,则 R[j--]=R[i]; //交换R[i]和R[j],交换后j指针减1 } R[i]=pivot; //此时,i=j,基准记录已被最后定位 return i; //返回基准记录的位置 } //2.=====快速排序=========== void QuickSort(SeqList R,int low,int high) { //R[low..high]快速排序 int pivotpos; //划分后基准记录的位置 if(low <high) { //仅当区间长度大于1时才排序 pivotpos=Partition(R,low,high); //对R[low..high]做一次划分,得到基准记录的位置 QuickSort(R,low,pivotpos-1); //对左区间递归排序 QuickSort(R,pivotpos+1,high); //对右区间递归排序 } } //======直接选择排序======== void SelectSort(SeqList R) { int i,j,k; for(i=1;i <n;i++){ //做第i趟排序(1≤i≤n-1) k=i; for(j=i+1;j <=n;j++) //在当前无序区R[i¨n]中选key最小的记录R[k] if(R[j].key <R[k].key) k=j; //k记下目前找到的最小关键字所在的位置 if(k!=i) { //交换R[i]和R[k] R[0]=R[i];R[i]=R[k];R[k]=R[0]; } //endif } //endfor } //======堆排序======== //==========大根堆调整函数======= void Heapify(SeqList R,int low,int high) { // 将R[low..high]调整为大根堆,除R[low]外,其余结点均满足堆性质 int large; //large指向调整结点的左、右孩子结点中关键字较大者 RecType temp=R[low]; //暂存调整结点 for(large=2*low; large <=high;large*=2){ //R[low]是当前调整结点 //若large> high,则表示R[low]是叶子,调整结束;否则先令large指向R[low]的左孩子 if(large <high && R[large].key <R[large+1].key) large++; //若R[low]的右孩子存在且关键字大于左兄弟,则令large指向它 //现在R[large]是调整结点R[low]的左右孩子结点中关键字较大者 if(temp.key> =R[large].key) //temp始终对应R[low] break; //当前调整结点不小于其孩子结点的关键字,结束调整 R[low]=R[large]; //相当于交换了R[low]和R[large] low=large; //令low指向新的调整结点,相当于temp已筛下到large的位置 } R[low]=temp; //将被调整结点放入最终位置上 } //==========构造大根堆========== void BuildHeap(SeqList R) { //将初始文件R[1..n]构造为堆 int i; for(i=n/2;i> 0;i--) Heapify(R,i,n); //将R[i..n]调整为大根堆 } //==========堆排序=========== void HeapSort(SeqList R) { //对R[1..n]进行堆排序,不妨用R[0]做暂存单元 int i; BuildHeap(R); //将R[1..n]构造为初始大根堆 for(i=n;i> 1;i--){ //对当前无序区R[1..i]进行堆排序,共做n-1趟。 R[0]=R[1]; R[1]=R[i];R[i]=R[0]; //将堆顶和堆中最后一个记录交换 Heapify(R,1,i-1); //将R[1..i-1]重新调整为堆,仅有R[1]可能违反堆性质。 } } //==========二路归并排序=========== //===将两个有序的子序列R[low..m]和R[m+1..high]归并成有序的序列R[low..high]=== void Merge(SeqList R,int low,int m,int high) { int i=low,j=m+1,p=0; //置初始值 RecType *R1; //R1为局部量 R1=(RecType *)malloc((high-low+1)*sizeof(RecType)); //申请空间 while(i <=m && j <=high) //两个子序列非空时取其小者输出到R1[p]上 R1[p++]=(R[i].key <=R[j].key)? R[i++]:R[j++]; while(i <=m) //若第一个子序列非空,则复制剩余记录到R1 R1[p++]=R[i++]; while(j <=high) //若第二个子序列非空,则复制剩余记录到R1中 R1[p++]=R[j++]; for(p=0,i=low;i <=high;p++,i++) R[i]=R1[p]; //归并完成后将结果复制回R[low..high] } //=========对R[1..n]做一趟归并排序======== void MergePass(SeqList R,int length) { int i; for(i=1;i+2*length-1 <=n;i=i+2*length) Merge(R,i,i+length-1,i+2*length-1); //归并长度为length的两个相邻的子序列 if(i+length-1 <n) //尚有一个子序列,其中后一个长度小于length Merge(R,i,i+length-1,n); //归并最后两个子序列 //注意:若i≤n且i+length-1≥n时,则剩余一个子序列轮空,无须归并 } //========== 自底向上对R[1..n]做二路归并排序=============== void MergeSort(SeqList R) { int length; for(length=1;length <n;length*=2) //做[lgn]趟排序 MergePass(R,length); //有序长度≥n时终止 } //==========输入顺序表======== void input_int(SeqList R) { int i; printf( "Please input num(int): "); scanf( "%d ",&n); printf( "Plase input %d integer: ",n); for(i=1;i <=n;i++) scanf( "%d ",&R[i].key); } //==========输出顺序表======== void output_int(SeqList R) { int i; for(i=1;i <=n;i++) printf( "%4d ",R[i].key); } //==========主函数====== void main() { int i; SeqList R; input_int(R); printf( "/t******** Select **********/n "); printf( "/t1: Insert Sort/n "); printf( "/t2: Bubble Sort/n "); printf( "/t3: Quick Sort/n "); printf( "/t4: Straight Selection Sort/n "); printf( "/t5: Heap Sort/n "); printf( "/t6: Merge Sort/n "); printf( "/t7: Exit/n "); printf( "/t***************************/n "); scanf( "%d ",&i); //输入整数1-7,选择排序方式 switch (i){ case 1: InsertSort(R); break; //值为1,直接插入排序 case 2: BubbleSort(R); break; //值为2,冒泡法排序 case 3: QuickSort(R,1,n); break; //值为3,快速排序 case 4: SelectSort(R); break; //值为4,直接选择排序 case 5: HeapSort(R); break; //值为5,堆排序 case 6: MergeSort(R); break; //值为6,归并排序 case 7: exit(0); //值为7,结束程序 } printf( "Sort reult: "); output_int(R); }