:::info 將資料由小到大或由大到小排列,常見排序演算法有氣泡排序、選擇排序、插入排序、合併排序與快速排序等,其中以合併排序與快速排序的演算法效率比較好,但程式也較複雜。 ::: # 氣泡排序法(BubbleSort) :::warning Bubble Sort 的方式是從陣列的最前面開始,一次比較陣列中兩兩相鄰的元素,然後根據大小將它們調換順序,大的移到後面: 1. 當我們比較過所有元素一次後,可以確保數值最大的元素在最後面 2. 接著扣掉陣列中的最後一個元素(因為已經確定它是最大的),接著重複上面的步驟進行兩兩比較 3. 重複上述動作,直到排序完畢。假設這個陣列有 6 個元素一共需重複這個動作 5 次 ::: ![](https://i.imgur.com/hdgytLs.png) :::success 1. 隨機產生一個陣列10個1~10000的整數元素 2. 以氣泡排序演算法將這10個元素由小到大排序 3. 輸出元素兩兩間以一個空白隔開 4. 每行最多輸出5個元素 ::: ```cpp= #include <iostream> //取得自1970/1/1 12:00:00 開始至現在所經過的時間 #include <ctime> //srand(), rand() #include <cstdlib> //sort() #include <algorithm> using namespace std; const int SIZE = 10; const int NUM_PER_LINE = 5; int a[SIZE]; const int MAX_NUM = 10000; // 1.產生SIZE個整數(1~10000)的陣列 void generateArray(int SIZE) { //產生亂數種子(Bandom seed) //srand(time(NULL)); srand((unsigned int)time(NULL)); //產生10個 1~10000的數字存到a陣列中 for(int i=0; i<SIZE; i++){ //產生 1~10000的亂數整數 a[i] = rand()%MAX_NUM + 1; } } // 2.顯示陣列資料 // 輸出元素兩兩間以一個空白隔開,最後一個元素和不能有空白 // 每行最多顯示 NUM_PER_LINE 個元素 void displayArray(int SIZE, int NUM_PER_LINE) { /*解法1 for(int i=0; i<SIZE; i++) { if(i==(SIZE-1)) cout<<a[i]<<"\n"; else cout<<a[i]<<" "; } cout<<"\n"; //解法2 cout<<a[0]; for(int i=1; i<SIZE; i++) cout<<" "<<a[i]; cout<<"\n";*/ int counter=0; //紀錄已經顯示的個數 int firat = 1; //紀錄是否為每行的第一個元素 for(int i=0; i<SIZE; i++) //輸出SIZE個元素 { if(firat) //是每行的第一個元素 { firat=0; cout<<a[i]; } else //不是每行的第一個元素 { cout<<" "<<a[i]; } //1.先將counter+1 //2.counter 是否被NUM_PER_LINE整除 //3.判斷條件是否成立 if(!(++counter%NUM_PER_LINE)) { cout<<"\n"; firat=1; } } } // 3.開始排序 void bubbleSort(int a[], int SIZE) { for(int i=0; i<SIZE-1; i++) { for(int j=0; SIZE-1-i; j++) { if(a[j]>a[j+1]) { int tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; } } } } bool cmp(int p, int q){ return p>q; } int main() { // 1.產生SIZE個整數(1~10000)的陣列 generateArray(SIZE); // 2.顯示陣列資料 cout<<"Before sorting:\n";sort(a, a+SIZE); displayArray(SIZE, NUM_PER_LINE); // 3.開始排序 bubbleSort(a, SIZE); // 4.顯示陣列資料 cout<<"After ASC. sorted;\n"; displayArray(SIZE, NUM_PER_LINE); cout<<"\n\nUsing sort Algorithm:\n"; generateArray(SIZE); cout<<"Before DEC. sorting:\n"; displayArray(SIZE, NUM_PER_LINE); //sort(a, a+SIZE); //一定要加入algorithm標頭檔 sort(a, a+SIZE, cmp); //由大到小 cout<<"After sorted:\n"; displayArray(SIZE, NUM_PER_LINE); return 0; } ``` # 多鍵值排序(Multi-Key Sorting) :::warning 1.若同時間有多個鍵值需要比較,稱為多鍵值排序 2.程式也可以進行多鍵值排序,需要自訂結構(struct) 3.定義cmp 函式,最後使用STL 的sort 函式與cmp 函式進行多鍵值排序。 ::: :::success 請寫一個程式,隨機產生20個學生的國文、英文與數學成績 再依照國文、英文與數學排序,也就是若國文同分則比較英文,若英文同分則比較數學。 ::: ```cpp= #include <iostream> #include <ctime> //for time() #include <cstdlib> //for stand().rand() #include <algorithm>//for sort() #define NUMOFSTUDETS 20 #define MINSOORE 61 using namespace std; //int a[NUMOFSTUDETS]; //這是錯的因為這樣寫只能儲存一個key //定義學生分數的結構,包含國文、英文、數學3科分數 typedef struct _score{ int chi; int eng; int math; //int chi,eng,math簡寫 }SCORE; //宣告 儲存NUMOFSTUDENTS 的成績資料 SCORE a[NUMOFSTUDETS]; //1.利用亂數產生 SIZE個 學生成績資料 //隨機產生20個學生的 國文、英文與數學成績(61~100) void generateStudentData() { //取得 random seed srand(time(NULL)); //產生size 個學生的 國文、英文與數學成績(61~100) for(int i=0; i<NUMOFSTUDETS; i++){ a[i].chi = rand()% 40 + 61; a[i].eng = rand()% 40 + 61; a[i].math = rand()% 40 + 61; } } //2.顯示陣列資料 void displayStudentData() { for(int i=0; i<NUMOFSTUDETS; i++){ cout<<"Chinese = " <<a[i].chi<<" " <<"English = " <<a[i].eng<<" " <<"Math = " <<a[i].math<<"\n"; } } //3.自訂多key排序 //若國文同分級比較英文,若英文同分則比較數學 int cmp(SCORE p, SCORE q){ //如果 國文分數相同且英文也相同,則比較數學 if(p.chi==q.chi&& p.eng==q.eng) return p.math>p.math; //如果 國文相同,比較英文 else if(p.chi==q.chi) return p.eng>q.eng; else return p.chi>q.chi; //如果 沒有相同,比較國文 } int main() { //1.利用亂數產生 SIZE個 學生成績資料 generateStudentData(); //2.顯示亂數產生的學生原始資料 cout<<"Original data:\n"; displayStudentData(); //3.根據排序需求進行排序 sort(a, a+NUMOFSTUDETS, cmp); //4.顯示排序後資料 cout<<"\n\nSorted data:\n"; displayStudentData(); return 0; } ``` ![](https://i.imgur.com/DYN5qyP.png)