- 冒泡排序
- 原理:
- 從第一個數據開始,與第二個數據相比較,如果第二個數據小於第一個數據,則交換兩個數據的位置。
- 指針由第一個數據移向第二個數據,第二個數據與第三個數據相比較,如果第三個數據小於第二個數據,則交換兩個數據的位置。
- 依此類推,完成第一輪排序。第一輪排序結束后,最大的元素被移到了最右面。
- 依照上面的過程進行第二輪排序,將第二大的排在倒數第二的位置。
- 重復上述過程,沒排完一輪,比較次數就減少一次。
- 例子:
-
待排序數據:7, 6, 9, 8, 5,1
第一輪排序過程:指針先指向7,7和6比較,6<7,交換6和7的位置,結果為:6,7,9,8,5,1
指針指向第二個元素7,7和9比較,9>7,不用交換位置,結果仍為:6,7,9,8,5,1
指針指向第三個元素9,比較9和8,8<9,交換8和9的位置,結果為:6,7,8,9,5,1
指針指向第四個元素9,比較9和5,5<9,交換5和9,結果為:6,7,8,5,9,1
指針指向第五個元素9,比較9和1,1<9,交換1和9的位置,結果為6,7,8,5,1,9
第一輪排序結束后,最大的數字9被移到了最右邊。
進行第二輪排序,過程同上,只是由於最大的9已經放在最右邊了,因此不用在比較9了,少了一次比較,第二輪結束的結果為:6,7,5,1,8,9
第三輪結果:6,5,1,7,8,9
第四輪比較結果:5,1,6,7,8,9
第五輪比較結果:1,5,6,7,8,9
最終排序結果為:1,5,6,7,8,9,由上可知N個數據排序,需要進行N-1輪排序;第i輪排序需要的比較次數為N-i次。
-
- 思路:需要兩層循環,第一層循環i表示排序的輪數,第二層循環j表示比較的次數。
- 實現:
import java.util.Arrays; public class TestBubbleSort1 { //冒泡排序 public static void main(String[] args) { //定義數組 int[] arr = {7, 6, 9, 8, 5, 1}; //排序前的數組 System.out.print("排序前的數組:"); System.out.println(Arrays.toString(arr)); //排序 //大循環。循環n-1次 boolean flag = true; for (int i = 0; i < arr.length - 1; i++) { //小循環,每次比較相鄰的兩個元素 for (int j = 0; j < arr.length - 1; j++) { //如果前一個數大於第二個數 if (arr[j] > arr[j + 1]) { int temp; temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; flag = false; } } //判斷是否有序 if (flag) { break; } } //排序后的數組 System.out.print("排序前的數組:"); System.out.println(Arrays.toString(arr)); } } - 總結:
N個元素需要排序N-1輪;
第i輪需要比較N-i次;
N個元素排序,需要比較n(n-1)/2次;
冒泡排序的算法復雜度較高,為O(n*n)
- 圖片

- 原理:
- 選擇排序
- 原理
- 從第一個元素開始,分別與后面的元素向比較,找到最小的元素與第一個元素交換位置;
- 從第二個元素開始,分別與后面的元素相比較,找到剩余元素中最小的元素,與第二個元素交換;
- 重復上述步驟,直到所有的元素都排成由小到大為止。
- 例子
-
待比較數據:7, 6, 9, 8, 5,1
第一輪:此時指針指向第一個元素7,找出所有數據中最小的元素,即1,交換7和1的位置,排序后的數據為:1,6,9,8,5,7
第二輪:第一個元素已經為最小的元素,此時指針指向第二個元素6,找到6,9,8,5,7中最小的元素,即5,交換5和6的位置,排序后的結果為:1,5,9,8,6,7
第三輪:前兩個元素為排好序的元素,此時指針指向第三個元素9,找到9,8,6,7中最小的元素,即6,交換6和9的位置,排序后的結果為:1,5,6,8,9,7
第四輪:前三個元素為排好序的元素,此時指針指向第四個元素8,找到8,9,7中最小的元素,即7,交換8和7的位置,排序后的結果為:1,5,6,7,9,8
第五輪:前四個元素為排好序的元素,此時指針指向第五個元素9,找到9,8中最小的元素,即8,交換9和8的位置,排序后的結果為:1,5,6,7,8,9
到此,全部排序完成。
分析:從上面的原理可以看出,與冒泡排序不同,選擇排序每排完一輪都把最小的元素移到了最左面,然后下一輪排序的比較次數比上一輪減少一次,即第i輪排序需要比較N-i次。因此,和冒泡排序一樣,N個數據比較大小,需要排序N-1輪,第i輪排序需要比較N-i次。
- 思路:需要兩次循環,第一層循環i表示每輪指針指向的位置,將最小值min初始化為第i個元素,第二層循環從j=i+1開始,分別與min比較,如果小於min,則更新min的值,內層循環結束后;交換min元素和第i個元素的位置。以此類推進行下一輪循環,直到i=length時停止循環。當i=length時,說明小的元素已經全部移到了左面,因此無需進行內層循環了。
- 實現
import java.util.Arrays; public class TestBubbleSort2 { //選擇排序 public static void main(String[] args) { //定義數組 int[] arr = {7, 6, 9, 8, 5, 1}; //排序前的數組 System.out.print("排序前的數組:"); System.out.println(Arrays.toString(arr)); //排序 //大循環。循環n-1次 for (int i = 0; i < arr.length-1; i++) { //假設第i個元素最小 int minIndex = i; //i+1開始,依次用最小的比較 for (int j = i + 1; j < arr.length; j++) { if (arr[minIndex] > arr[j]) { minIndex = j; } } //第一趟比較完,比較最小值索引是不是第i個 if (minIndex != i) { int temp; temp = arr[minIndex]; arr[minIndex] = arr[i]; arr[i] = temp; } } //排序后的數組 System.out.print("排序前的數組:"); System.out.println(Arrays.toString(arr)); } }
- 總結
N個元素需要排序N-1輪;
第i輪需要比較N-i次;
N個元素排序,需要比較n(n-1)/2次;
選擇排序的算法復雜度仍為O(n*n);
相比於冒泡排序,選擇排序的交換次數大大減少,因此速度要快於冒泡排序
- 圖片

- 原理
- 插入排序
- 原理:
- 將指針指向某個元素,假設該元素左側的元素全部有序,將該元素抽取出來,然后按照從右往左的順序分別與其左邊的元素比較,遇到比其大的元素便將元素右移,直到找到比該元素小的元素或者找到最左面發現其左側的元素都比它大,停止;
- 此時會出現一個空位,將該元素放入到空位中,此時該元素左側的元素都比它小,右側的元素都比它大;
- 指針向后移動一位,重復上述過程。每操作一輪,左側有序元素都增加一個,右側無序元素都減少一個。
- 例子:
待比較數據:7, 6, 9, 8, 5,1
第一輪:指針指向第二個元素6,假設6左面的元素為有序的,將6抽離出來,形成7,_,9,8,5,1,從7開始,6和7比較,發現7>6。將7右移,形成_,7,9,8,5,1,6插入到7前面的空位,結果:6,7,9,8,5,1
第二輪:指針指向第三個元素9,此時其左面的元素6,7為有序的,將9抽離出來,形成6,7,_,8,5,1,從7開始,依次與9比較,發現9左側的元素都比9小,於是無需移動,把9放到空位中,結果仍為:6,7,9,8,5,1
第三輪:指針指向第四個元素8,此時其左面的元素6,7,9為有序的,將8抽離出來,形成6,7,9,_,5,1,從9開始,依次與8比較,發現8<9,將9向后移,形成6,7,_,9,5,1,8插入到空位中,結果為:6,7,8,9,5,1
第四輪:指針指向第五個元素5,此時其左面的元素6,7,8,9為有序的,將5抽離出來,形成6,7,8,9,_,1,從9開始依次與5比較,發現5比其左側所有元素都小,5左側元素全部向右移動,形成_,6,7,8,9,1,將5放入空位,結果5,6,7,8,9,1。
第五輪:同上,1被移到最左面,最后結果:1,5,6,7,8,9。
- 思路:需要兩層循環,第一層循環index表示上述例子中的指針,即遍歷從坐標為1開始的每一個元素;第二層循環從leftindex=index-1開始,leftindex--向左遍歷,將每一個元素與i處的元素比較,直到j處的元素小於i出的元素或者leftindex<0;遍歷從i到j的每一個元素使其右移,最后將index處的元素放到leftindex處的空位處。
- 實現
import java.util.Arrays; public class TestInsertionSort { //插入排序 public static void main(String[] args){ //定義數組 int[] arr = {7, 6, 9, 8, 5, 1}; //排序前的數組 System.out.print("排序前的數組:"); System.out.println(Arrays.toString(arr)); //排序 //大循環。循環n次 for (int i=0;i<arr.length;i++){ int temp=arr[i]; //用作比較的數據 int leftIndex=i-1; while (leftIndex>=0&&arr[leftIndex]>temp){ //當比到最左邊或者遇到比temp小的數據時,結束循環 arr[leftIndex+1]=arr[leftIndex]; leftIndex--; } arr[leftIndex+1]=temp; //把temp放到空位上 } //排序后的數組 System.out.print("排序前的數組:"); System.out.println(Arrays.toString(arr)); } } - 總結:時間復雜度,由於仍然需要兩層循環,插入排序的時間復雜度仍然為O(n*n)。
比較次數:在第一輪排序中,插入排序最多比較一次;在第二輪排序中插入排序最多比較二次;以此類推,最后一輪排序時,最多比較N-1次,因此插入排序的最多比較次數為1+2+...+N-1=N*(N-1)/2。盡管如此,實際上插入排序很少會真的比較這么多次,因為一旦發現左側有比目標元素小的元素,比較就停止了,因此,插入排序平均比較次數為N*(N-1)/4。 - 圖片

- 原理:
