1. 程式人生 > >八大經典排序算法的代碼實現

八大經典排序算法的代碼實現

heapsort 最後一個元素 數據量 可能 一位 需要 存在 urn show

冒泡排序:

技術分享圖片
 1 //冒泡排序
 2 //時間復雜度為O(N^2),空間復雜度為O(N)
 3 public class BubbleSort {
 4     public static void bubbleSort(int[] arr) {
 5         if (arr.length == 0 || arr.length == 1) {
 6             return;
 7         } else {
 8 //            隨著每輪比較的進行,都有一個大數沈到後面排好序,因此外層的循環長度應該遞減
 9             for (int
end = arr.length - 1; end > 0; end--) { 10 for (int i = 0; i < end; i++) { 11 if (arr[i] > arr[i + 1]) { 12 swap(arr, i, i + 1); 13 } 14 } 15 } 16 } 17 18 } 19 20
static void swap(int[] arr, int i, int j) { 21 // 不利用第三個變量交換兩變量的位置。1.a和同一個數異或運算兩次得到a本身 2.異或運算滿足交換律 22 arr[j] = arr[j] ^ arr[i]; 23 arr[i] = arr[j] ^ arr[i]; 24 arr[j] = arr[j] ^ arr[i]; 25 } 26 27 public static void main(String[] args) { 28 int
[] a = {2, 1, 7, 10, 3, 9, 5, 4, 6, 8}; 29 bubbleSort(a); 30 for(int i:a) 31 System.out.print(i+","); 32 } 33 }
冒泡排序

插入排序:

技術分享圖片
 1 //插入排序
 2 //復雜度和數據狀況有關系,如果本來數組的有序性就比較好則復雜度低
 3 public class InsertSort {
 4     public static void insertSort(int[] arr) {
 5         if (arr == null || arr.length < 2) {
 6             return;
 7         } else {
 8             for (int i = 1; i < arr.length; i++) {
 9 //如果數組的有序性比較好,如1,2,3,4,5,則arr[j + 1] < arr[j]這個條件可以使得比較提前終止,
10 //如果數組剛好是逆序的,如5,4,3,2,1,則需要從j一直比較到i=0;
11                 for (int j = i - 1; j >= 0 && arr[j + 1] < arr[j]; j--) {
12                     swap(arr, j, j + 1);
13                 }
14             }
15         }
16     }
17 
18     static void swap(int[] arr, int i, int j) {
19         arr[j] = arr[j] ^ arr[i];
20         arr[i] = arr[j] ^ arr[i];
21         arr[j] = arr[j] ^ arr[i];
22     }
23 
24     public static void main(String[] args) {
25         int[] a = {2, 1, 7, 10, 3, 9, 5, 4, 6, 8};
26         insertSort(a);
27         for (int i : a)
28             System.out.print(i + ",");
29     }
30 }
插入排序

選擇排序:

技術分享圖片
 1 //選擇排序
 2 //時間復雜度為O(N^2),空間復雜度為O(1)
 3 public class SelectionSort {
 4     public static void selectionSort(int[] arr) {
 5         if (arr == null || arr.length < 2) {
 6             return;
 7         } else {
 8 //            每輪都從未排序的數列中取出一個數,將其與後面所有未排序的數作比較,得到這些未排序數列裏面的最小數,將它換到已排好序數列的後面,並擴大已排好序數列的範圍。
 9             for (int i = 0; i < arr.length - 1; i++) {
10                 int minIndex = i;
11 //                i = 0作為第一個已排序列
12                 for (int j = i + 1; j < arr.length; j++) {
13                     minIndex = arr[j] < arr[minIndex] ? j : minIndex;
14                 }
15                 swap(arr, i, minIndex);
16             }
17         }
18     }
19 
20     static void swap(int[] arr, int i, int j) {
21 //        此處不能用異或來完成交換,因為如果i=j, 兩個相同的數異或等於0,“arr[j] = arr[j] ^ arr[i]”會將arr[i]和arr[j]同時置為0,這樣就丟失了所有信息。
22 //        如果i和j不相等,但a[i]==a[j]是可以完成異或交換功能的,因為0和任何數異或等於其本身
23 //        arr[j] = arr[j] ^ arr[i];
24 //        arr[i] = arr[j] ^ arr[i];
25 //        arr[j] = arr[j] ^ arr[i];
26         int tmp = arr[i];
27         arr[i] = arr[j];
28         arr[j] = tmp;
29     }
30 
31     public static void main(String[] args) {
32         int[] a = {2, 1, 7, 10, 3, 9, 5, 4, 6, 8};
33         selectionSort(a);
34         for (int i : a)
35             System.out.print(i + ",");
36     }
37 }
選擇排序

歸並排序:

技術分享圖片
 1 //歸並排序
 2 //時間復雜度O(NlogN),空間復雜度O(N)
 3 //分治+外排的方法
 4 public class MergeSort {
 5     public static void mergeSort(int[] arr) {
 6         if (arr == null || arr.length < 2)
 7             return;
 8         else
 9             sortProcess(arr, 0, arr.length - 1);
10     }
11 
12     private static void sortProcess(int[] arr, int L, int R) {
13         if (L == R)
14             return;
15         else {
16             int mid = L + ((R - L) >> 1);
17 //            根據Master公式求其時間復雜度:
18             sortProcess(arr, L, mid);//T(N/2)
19             sortProcess(arr, mid + 1, R);//T(N/2)
20             merge(arr, L, mid, R);//O(N)
21 //            根據Master公式,其時間復雜度為T(N) = 2T(N/2)+O(N) = N*logN
22         }
23     }
24 
25     //融合兩個有序數組,使之成為一個更大的有序數組的方法,叫做外排
26     private static void merge(int[] arr, int l, int mid, int r) {
27 //        空間復雜度O(體現在需要一個大小為數據量N的輔助數組help上)
28         int[] help = new int[r - l + 1];
29         int i = 0;
30         int p1 = l;
31         int p2 = mid + 1;
32         while (p1 <= mid && p2 <= r)
33             help[i++] = arr[p1]<=arr[p2]?arr[p1++]:arr[p2++];
34 //        兩個必有且只有一個越界
35         while(p1<=mid)
36             help[i++] = arr[p1++];
37         while(p2<=r)
38             help[i++] = arr[p2++];
39 
40         i = 0;
41         while(l<=r)
42             arr[l++] = help[i++];
43     }
44 
45     public static void main(String[] args) {
46         int[] a = {2, 1, 7, 10, 3, 9, 5, 4, 6, 8};
47         mergeSort(a);
48         for(int i:a)
49             System.out.print(i+",");
50     }
51 }
View Code

快速排序:

技術分享圖片
 1 import java.util.Arrays;
 2 
 3 //快排
 4 //時間復雜度最好為O(NlogN). 數組逆序的時候最差,時間復雜度為O(N^2),可以通過隨機快排的方式使得其長期時間復雜度期望為O(N*logN)
 5 //空間復雜度最好為O(logN),數組逆序的時候最差,空間復雜度為O(N),額外空間主要是每次partition函數返回的二元數組造成的。
 6 //通過隨機快排的方式使得其長期時間復雜度期望為O(logN)
 7 //所有遞歸函數都可以改為非遞歸版本,因為遞歸的本質行為是系統在幫我們壓棧。改為非遞歸就是改成我們自己來壓棧
 8 // 在工程上是不允許遞歸行為存在的,因為遞歸過深可能會導致系統棧爆滿,系統不穩定。因此工程上的快排都是非遞歸版本實現的。
 9 //庫函數都是高度優化過的
10 public class QuickSort {
11 
12     static void quickSort(int[] arr, int L, int R) {
13         if (L < R) {
14 //            隨機快排, 每次將中間隨機一個數和數列最後一個元素交換位置,放置逆序數列產生差的結果
15             swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
16             int[] p = partition(arr, L, R);
17             quickSort(arr, L, p[0] - 1);
18             quickSort(arr, p[1] + 1, R);
19         }
20     }
21 
22     static int[] partition(int[] arr, int L, int R) {
23         int less = L - 1;
24         int more = R;
25         int cur = L;
26 //        以arr[R]作為基準,有了隨機快排,這裏的arr[R]被重新洗牌
27 //        這裏一次性處理了大於基準等於基準和小於基準的三種情況,速度比傳統快排要快
28         while (cur < more) {
29             if (arr[cur] < arr[R]) {
30                 // cur++,因為換到cur位置上的一定是比基準arr[R]小的數,直接將其擴到less範圍去,且cur指向下一位置
31                 swap(arr, ++less, cur++);
32             } else if (arr[cur] > arr[R]) {
33                 //交換到cur位置上的數大小位置,交換過去的數一定大於基準arr[R], 故more--,將其擴到more區域, 但cur位置不變
34                 swap(arr, --more, cur);
35             } else {
36                 //當前位置和基準arr[R]相等,不擴到less區域和more區域,放在相等區域
37                 cur++;
38             }
39         }
40         //最後將基準交換到more區域的下一位置
41         swap(arr, more, R);
42        // 返回相等區域下標,註意此時more位置上是交換過來的基準值,不用加1
43         return new int[]{less + 1, more};
44     }
45 
46     static void swap(int[] arr, int i, int j) {
47         int tmp = arr[i];
48         arr[i] = arr[j];
49         arr[j] = tmp;
50     }
51 
52     public static void main(String[] args) {
53         int a[] = {49, 38, 65, 97, 76, 13, 27, 49};
54         quickSort(a, 0, a.length - 1);
55         System.out.println(Arrays.toString(a));
56     }
57 }
快排

堆排序:

技術分享圖片
 1 import java.util.Arrays;
 2 
 3 //堆排序
 4 //堆是完全二叉樹
 5 //二叉樹的底層可以用線性的結構來儲存,也就是說可以用數組來儲存一個二叉樹,通過數組中下標的關系來表示這個堆。設完全二叉樹的一個節點在數組中的下標為i,
 6 //則其父節點的下標應該為(i-1)/2,其左孩子節點應該是2*i+1, 其右孩子節點應該為2*i+2
 7 public class HeapSort {
 8     static void heapSort(int[] arr) {
 9         if (arr == null || arr.length < 2)
10             return;
11         else
12             for (int i = 0; i < arr.length; i++)
13                 heapInsert(arr, i);
14 
15         int heapSize = arr.length;//堆的大小等於數組的長度
16         //交換堆頂和最後一個元素
17         swap(arr, 0, --heapSize);
18         while (heapSize > 0) {
19             heapify(arr, 0, heapSize);
20             swap(arr, 0, --heapSize);
21         }
22     }
23 
24     static void heapInsert(int[] arr, int index) {
25         while (arr[(index - 1) / 2] < arr[index]) {//如果index=0, -1/2=0是根節點
26             swap(arr, index, (index - 1) / 2);
27             index = (index - 1) / 2;
28         }
29 
30     }
31 
32     //    如果堆中有某個元素變小了,將這個元素下沈以保持大根堆的過程heapify
33     static void heapify(int[] arr, int index, int heapSize) {
34         int left = index * 2 + 1;//在用數組存儲的堆中,節點i的左孩子節點是2*i+1, 右節點是2*i+2;
35         //這裏heapSize是最後一個元素,做堆排的時候,因為是從堆頂交換來的最大值,所以重新heapify要把它排除在外;
36         while (left < heapSize) {
37             int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
38             largest = arr[index] > arr[largest] ? index : largest;
39             if (largest == index) {
40                 break;
41             }
42             swap(arr, largest, index);
43             index = largest;
44             left = index * 2 + 1;
45         }
46     }
47 
48     static void swap(int[] arr, int i, int j) {
49         int tmp = arr[i];
50         arr[i] = arr[j];
51         arr[j] = tmp;
52     }
53 
54     public static void main(String[] args) {
55         int a[] = {49, 38, 65, 97, 76, 13, 27, 49};
56         heapSort(a);
57         System.out.println(Arrays.toString(a));
58     }
59 }
堆排序

希爾排序:

基數排序:

八大經典排序算法的代碼實現