插入排序、氣泡排序、選擇排序、快速排序、堆排序、歸併排序演算法比較
阿新 • • 發佈:2019-02-08
//插入排序、氣泡排序、選擇排序、快速排序、堆排序、歸併排序 #include"stdio.h" #include"stdlib.h" #include"time.h" #define M 1000 int shu[M]; //存放要排序的陣列 int chang; //存放要排序的陣列的長度 //-------------------------顯示輸出---------------------------- void show() { printf("\n排序後的數為:\n"); for (int i=1; i<=chang; i++) printf("%d ", shu[i]); printf("\n\n排序結束!\n"); } //--------------------------插入排序----------------------------- void cha_ru() { for (int i=2, j; i<=chang; i++) if(shu[i] < shu[i-1]) { shu[0] = shu[i]; //將待查詢的數放入監視哨裡面 j = i - 1; while(shu[0] < shu[j]) //尋找插入位置 { shu[j+1] = shu[j]; j--; } shu[j+1] = shu[0]; //將元素插入 } } //--------------------------氣泡排序--------------------------- void mao_pao() { int change = 1; //標記一輪遍歷後是否有元素進行交換 for (int i=1; i<=chang && change; i++) { change = 0; for (int j=1; j<=chang-i; j++) if(shu[j] > shu[j+1]) { shu[0] = shu[j]; shu[j] = shu[j+1]; shu[j+1] = shu[0]; change = 1; } } } //--------------------------選擇排序---------------------------- void xuan_ze() { int min; //每次測試時最小的變數的代號 int temp; for (int i=1; i<=chang; i++) { min = i; //shu[min]記錄最小的shu[i] for (int j=i+1; j<=chang; j++) if(shu[j] < shu[min]) min = j; //修改min if(min != i) //若min!=i 則將shu[min]與shu[i]進行交換 { temp = shu[min]; shu[min] = shu[i]; shu[i] = temp; } } } //--------------------------快速排序------------------------------ int kuaisu_pass(int low, int high)//快速排序過程 { int x = shu[low]; while(low < high) { while(low<high && shu[high]>=x) //high從右到左找小於x的記錄 high--; if(low < high) //找到小於x的記錄進行交換 { shu[low] = shu[high]; low++; } while(low<high && shu[low]<=x) //low從左到右找大於x的記錄 low++; if(low < high) //找到大於x的記錄進行交換 { shu[high] = shu[low]; high--; } } shu[low] = x; return low; } void kuai_su(int low, int high) //快速排序主函式 { int pos; if(low < high) { pos = kuaisu_pass(low, high); kuai_su(low,pos-1); kuai_su(pos+1,high); } } //----------------------------堆排序------------------------------ void chong_jian_dui(int k, int m) //重建堆 { int x = shu[k]; //暫存“根”記錄 int i = k; int j = 2 * k; int finished = 0; while (j<=m && !finished) { if(j<m && shu[j]<shu[j+1]) //若存在右子樹,且右子樹根的關鍵字大,則延右分支“篩選" j = j + 1; if(x > shu[j]) //篩選完畢 finished = 1; else { shu[i] = shu[j]; i = j; j = 2 * i; } } shu[i] = x; //將shu[k]填到恰當的位置 } void jian_dui() //建堆 { int n = chang; for (int i=n/2; i>=1; i--) //自第【n/2】個記錄開始進行篩選建堆 chong_jian_dui(i,n); } void dui() //堆排序主函式 { int n = chang; //將要排序的數儲存到N中 int temp; jian_dui(); //將堆建立 for (int i=n; i>=2; i--) //將堆頂記錄和堆中的最後一個記錄交換 { temp = shu[1]; shu[1] = shu[i]; shu[i] = temp; chong_jian_dui(1,i-1); //進行調整,使得shu[1]到shu[i-1]變成堆 } } //--------------------------歸併排序------------------------------- void gui_bing_way(int temp1[], int temp2[], int begin, int half, int end)//二路歸併過程 { for (int j=half+1,k=begin; begin<=half && j<=end; k++) { //將temp2[]中的記錄由小到大地併入temp1[]中 if (temp2[begin] < temp2[j]) temp1[k] = temp2[begin++]; else temp1[k] = temp2[j++]; } for(; begin<=half;begin++, k++) //將剩餘的temp2[begin...half]複製到到temp1[]中 temp1[k] = temp2[begin]; for(; j<=end; j++, k++) //將剩餘的temp2[j....end]複製到temp1[]中 temp1[k] = temp2[j]; } void gui_bing(int temp1[],int temp2[],int begin, int end) //歸併排序 { int half; if(begin == end) temp2[begin] = temp1[begin]; else { half = (begin + end) / 2; //將temp2[begin...end]平分為temp2[begin...half]和temp2[half+1....end] gui_bing(temp1,temp2,begin,half); //遞迴將temp2[begin...half] 歸併 gui_bing(temp1,temp2,half+1,end); //遞迴將temp2[half+1...end] 歸併 gui_bing_way(temp1,temp2,begin,half,end); //將temp2[begin..half]和temp2[half+1..end]歸併到temp1[begin..end]中 } for (int i=1; i<=chang; i++) //將歸併後的數存入temp2[]中 temp2[i] = temp1[i]; } //------------------------------主函式----------------------------- int main() { int temp_shu[M]; int choise; //排序方式的選擇 int temp = 1; printf("請輸入要排序的隨機數的個數:"); scanf("%d", &chang); srand((unsigned)time(NULL)); for (int i=1; i<=chang; i++) shu[i] = rand()%1000; printf("隨即數的初始狀態為:\n"); for (i=1; i<=chang; i++) //將隨機數儲存到temp_shu[]中,並顯示 { temp_shu[i] = shu[i]; printf("%d ", shu[i]); } printf("\n\n請選擇要排序的方式:\n1.插入排序\n2.氣泡排序\n3.選擇排序\n4.快速排序\n5.堆排序\n6.歸併排序\n請選擇:"); scanf("%d", &choise); while(temp) { switch(choise) { case 1: //插入排序 cha_ru(); temp = 0; break; case 2: //氣泡排序 mao_pao(); temp = 0; break; case 3: //選擇排序 xuan_ze(); temp = 0; break; case 4: //快速排序 kuai_su(1,chang); temp = 0; break; case 5: //堆排序 dui(); temp = 0; break; case 6: //歸併排序 gui_bing(shu,temp_shu,1,chang); temp = 0; break; default: //其他錯誤輸入 printf("輸入錯誤,請重新輸入!\n"); printf("\n請選擇要排序的方式:\n1.插入排序\n2.氣泡排序\n3.選擇排序\n4.快速排序\n5.堆排序\n6.歸併排序\n"); scanf("%d", &choise); break; } } show(); //顯示輸出 return 0; }