在我大一的時候自學c語言和數據結構,我當時就接觸到了冒泡排序(當時使用的是C語言編寫的)。如今大三了,想要在暑假找到一份實習的工做,又要回顧一下數據結構與算法的知識點了。算法
排序對咱們來講是一點也不陌生了,當你打王者榮耀的時候也會有段位之分,當你打Dota的時候也有天梯分。從高往下數,這個排名是有規律的,就是一種排序。數組
我最開始接觸的就是冒泡排序,因此這篇博文主要講的是冒泡排序。微信
來源百度百科:數據結構
冒泡排序(Bubble Sort,臺灣譯爲:泡沫排序或氣泡排序)是一種簡單的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,若是他們的順序錯誤就把他們交換過來。走訪數列的工做是重複地進行直到沒有再須要交換,也就是說該數列已經排序完成。這個算法的名字由來是由於越大的元素會經由交換慢慢「浮」到數列的頂端,故名。測試
算法描述:優化
i
從0開始,i
與i+1
比較,若是i>i+1
,那麼就互換i
不斷增長,直到i<n-1
(n是數組元素的個數,n-1
是數組已經最後一個元素) ,一趟下來,可讓數組元素中最大值排在數組的最後面從最簡單開始,首先咱們建立一個數組,該數組有5位數字:spa
int[] arrays = {2, 5, 1, 3, 4};
下面咱們根據算法的描述來進行代碼驗算 (第一趟排序):code
//使用臨時變量,讓兩個數互換 int temp; //第一位和第二位比 if (arrays[0] > arrays[1]) { //交換 temp = arrays[0]; arrays[0] = arrays[1]; arrays[1] = temp; } //第二位和第三位比 if (arrays[1] > arrays[2]) { temp = arrays[1]; arrays[1] = arrays[2]; arrays[2] = temp; } //第三位和第四位比 if (arrays[2] > arrays[3]) { temp = arrays[2]; arrays[2] = arrays[3]; arrays[3] = temp; } //第四位和第五位比 if (arrays[3] > arrays[4]) { temp = arrays[3]; arrays[3] = arrays[4]; arrays[4] = temp; }
若是前一位的數比後一位的數要大,那麼就交換,直到將數組的全部元素都比較了一遍!排序
通過咱們第一趟比較,咱們能夠發現:最大的值就在數組的末尾了!遞歸
第二趟排序跟第一趟排序同樣,也是用前一位與後一位比較,若是前一位比後一位要大,那就交換。值得注意的是:並不須要與最後一位比較了,由於在第一趟排序完了,最後一位已是最大的數了。同理,咱們第二趟排序完了以後,倒數第二位也是第二大的數了。
第二趟排序的代碼以下:
//第一位和第二位比 if (arrays[0] > arrays[1]) { //交換 temp = arrays[0]; arrays[0] = arrays[1]; arrays[1] = temp; } //第二位和第三位比 if (arrays[1] > arrays[2]) { temp = arrays[1]; arrays[1] = arrays[2]; arrays[2] = temp; } //第三位和第四位比 if (arrays[2] > arrays[3]) { temp = arrays[2]; arrays[2] = arrays[3]; arrays[3] = temp; } //第四位不須要和第五位比了,由於在第一趟排序結束後,第五位是最大的了。
結果:咱們的第二大數已經排在了倒數第二位了
值得說明的是:上面的結果看起來已是排序好的了,實際上是我在測試時數據還不足夠亂,若是數據足夠亂的話,是須要4(n-1)趟排序的!
但咱們從上面的代碼就能夠發現:第一趟和第二趟的比較、交換代碼都是重複的,而且咱們的比較都是寫死的(0,1,2,3,4),並不通用!
咱們的數組有5位數字
咱們能夠根據上面規律推斷出:
再從上面的規律能夠總結出:5位數的數組須要4躺排序的,每躺排序以後次數減1(由於前一趟已經把前一趟數的最大值肯定下來了)!
因而咱們能夠根據for循環和變量將上面的代碼進行簡化:
int temp; //外層循環是排序的趟數 for (int i = 0; i < arrays.length - 1 ; i++) { //內層循環是當前趟數須要比較的次數 for (int j = 0; j < arrays.length - i - 1; j++) { //前一位與後一位與前一位比較,若是前一位比後一位要大,那麼交換 if (arrays[j] > arrays[j + 1]) { temp = arrays[j]; arrays[j] = arrays[j + 1]; arrays[j + 1] = temp; } } }
從上面的例子咱們能夠看出來,若是數據足夠亂的狀況下是須要通過4躺比較才能將數組完整排好序。可是咱們在第二躺比較後就已經獲得排好序的數組了。
可是,咱們的程序在第二趟排序後仍會執行第三趟、第四趟排序。這是沒有必要的,所以咱們能夠對其進行優化一下:
代碼以下:
//裝載臨時變量 int temp; //記錄是否發生了置換, 0 表示沒有發生置換、 1 表示發生了置換 int isChange; //外層循環是排序的趟數 for (int i = 0; i < arrays.length - 1; i++) { //每比較一趟就從新初始化爲0 isChange = 0; //內層循環是當前趟數須要比較的次數 for (int j = 0; j < arrays.length - i - 1; j++) { //前一位與後一位與前一位比較,若是前一位比後一位要大,那麼交換 if (arrays[j] > arrays[j + 1]) { temp = arrays[j]; arrays[j] = arrays[j + 1]; arrays[j + 1] = temp; //若是進到這裏面了,說明發生置換了 isChange = 1; } } //若是比較完一趟沒有發生置換,那麼說明已經排好序了,不須要再執行下去了 if (isChange == 0) { break; } }
C語言實現第一種方式:
void bubble ( int arr[], int n) { int i; int temp; for (i = 0; i < n - 1; i++) { if (arr[i] > arr[i + 1]) { temp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = temp; } } } void bubbleSort ( int arr[], int n) { int i; for (i = n; i >= 1; i--) { bubble(arr, i); } }
C語言實現第二種方式遞歸:
void bubble ( int arr[], int L, int R) { if (L == R) ; else { int i; for (i = L; i <= R - 1; i++)//i只能到達R-1 if (arr[i] > arr[i + 1]) { int temp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = temp; } bubble(arr, L, R - 1);//第一輪已排好R } }
測試代碼:
int main () { int arr[] = {2, 3, 4, 511, 66, 777, 444, 555, 9999}; bubbleSort(arr, 8); for (int i = 0; i < 9; i++) cout << arr[i] << endl; return 0; }
若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:Java3y