1. 問題
學過編程的朋友應該對冒泡排序不陌生,這里就不多講了,直接提一個有意思的問題:
冒泡排序中,如果經過某一趟冒泡排序后,該序列已經排序好了,那么此時就可以提前退出了。
2. 分析
2.1 如何判斷序列已經是有序的呢?
看一個有序數列{1, 2, 3, 4, 5},如果用冒泡法來排序,我們發現一趟冒泡沉底過程中,是不會發生任何交換的,因為每個數an都比an+1小,所以如果一趟冒泡沉底過程中,沒有發生過交換,那么這個序列就是有序的
2.2 如果只發生一次交換呢?
假設:如果一趟冒泡沉底過程中,只發生一次沉底交換,那么這次交換完畢后,這個序列是有序的
證明:
設只在ax處發生了一次交換,那么根據2.1的結論,a1~ax的序列就一定是有序的,交換后,而且ax+1~an的序列也是有序的,而ax和ax+1交換后也是有序的,
但如果ax+1小於x前面的任何一個數,則該數列仍然是無序的,如{1, 4, 5, 3, 6, 7},第一趟沉底過程中只需交換5和3一次,但交換后數列為{1, 4, 3, 5, 6, 7},仍然是無序的
3. code
//Improve bubble sort //When it do not need to change any number in one bubble sort, all the sequence sort completely int ImproveBubbleSort(int nSequenceArray[], int nSize) { int nTime = 0; for (int i = nSize - 1; i > 0 ; i--) { int nExchanged = 0; for (int j = 0; j < i; j++) { if (nSequenceArray[j] > nSequenceArray[j + 1]) { int nTemp = nSequenceArray[j]; nSequenceArray[j] = nSequenceArray[j + 1]; nSequenceArray[j + 1] = nTemp; nExchanged++; } nTime++; } if (nExchanged <= 0) { break; } } return nTime; } void Test() { int nSequenceArray[] = {2, 8, 19, 3, 4, 7, 11, 37, 5, 4}; //int nSequenceArray[] = {11, 3, 5, 7, 37, 4, 19, 8, 2, 4}; int nSize = sizeof(nSequenceArray) / sizeof(nSequenceArray[0]); int nTime = ImproveBubbleSort(nSequenceArray, nSize); printf("After sort %d times, the sequence is : ", nTime); for (int i = 0; i < nSize; i++) { printf("%d, ", nSequenceArray[i]); } }
4. 結果
4.1 未優化的冒泡排序(循環45次)
4.2 以交換次數為0作為退出條件的冒泡排序(循環42次)
改進后的冒泡排序,在數列本身有一定的順序的情況下,是可以顯著提高排序效率的