常見的內部排序算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸並排序、快速排序、堆排序、基數排序等。用一張圖概括:
冒泡排序
算法步驟
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對。這步做完后,最后的元素會是最大的數。
針對所有的元素重復以上的步驟,除了最后一個。
持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。
Java 代碼實現
import java.util.Arrays; public class MaoPao { public static void main(String[] args){ int[] arr = {1,45,43,12,91,4,66,82,19,213}; arr = sort(arr); System.out.println(Arrays.toString(arr)); } public static int[] sort(int[] sourceArray) { // 對 arr 進行拷貝,不改變參數內容 int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); for (int i = 1; i < arr.length; i++) { // 設定一個標記,若為true,則表示此次循環沒有進行交換,也就是待排序列已經有序,排序已經完成。 boolean flag = true; for (int j = 0; j < arr.length - i; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; flag = false; } } if (flag) { break; } } return arr; } }
選擇排序
算法步驟
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再從剩余未排序元素中繼續尋找最小(大)元素,然后放到已排序序列的末尾。
重復第二步,直到所有元素均排序完畢。
Java 代碼實現
import java.util.Arrays; public class XuanZe { public static void main(String[] args) { int[] arr = {1,45,43,12,91,4,66,82,19,213}; arr = sort(arr); System.out.println(Arrays.toString(arr)); } public static int[] sort(int[] sourceArray){ int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); // 總共要經過 N-1 輪比較 for (int i = 0; i < arr.length - 1; i++) { int min = i; // 每輪需要比較的次數 N-i for (int j = i + 1; j < arr.length; j++) { if (arr[j] < arr[min]) { // 記錄目前能找到的最小值元素的下標 min = j; } } // 將找到的最小值和i位置所在的值進行交換 if (i != min) { int tmp = arr[i]; arr[i] = arr[min]; arr[min] = tmp; } } return arr; } }
插入排序
算法步驟
將第一待排序序列第一個元素看做一個有序序列,把第二個元素到最后一個元素當成是未排序序列。
從頭到尾依次掃描未排序序列,將掃描到的每個元素插入有序序列的適當位置。(如果待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的后面。)
Java 代碼實現
import java.util.Arrays; public class ChaRu { public static void main(String[] args) { int[] arr = {1,45,43,12,91,4,66,82,19,213}; arr = sort(arr); System.out.println(Arrays.toString(arr)); } public static int[] sort(int[] sourceArray){ // 對 arr 進行拷貝,不改變參數內容 int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); // 從下標為1的元素開始選擇合適的位置插入,因為下標為0的只有一個元素,默認是有序的 for (int i = 1; i < arr.length; i++) { // 記錄要插入的數據 int tmp = arr[i]; // 從已經排序的序列最右邊的開始比較,找到比其小的數 int j = i; while (j > 0 && tmp < arr[j - 1]) { arr[j] = arr[j - 1]; j--; } // 存在比其小的數,插入 if (j != i) { arr[j] = tmp; } } return arr; } }
快速排序
算法步驟
-
從數列中挑出一個元素,稱為 "基准"(pivot);
-
重新排序數列,所有元素比基准值小的擺放在基准前面,所有元素比基准值大的擺在基准的后面(相同的數可以到任一邊)。在這個分區退出之后,該基准就處於數列的中間位置。這個稱為分區(partition)操作;
-
遞歸地(recursive)把小於基准值元素的子數列和大於基准值元素的子數列排序;
Java 代碼實現
import java.util.Arrays; public class KuaiSu { public static void main(String[] args) { int[] arr = {1,45,43,12,91,4,66,82,19,213}; arr = sort(arr); System.out.println(Arrays.toString(arr)); } public static int[] sort(int[] sourceArray){ // 對 arr 進行拷貝,不改變參數內容 int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); return quickSort(arr, 0, arr.length - 1); } private static int[] quickSort(int[] arr, int left, int right) { if (left < right) { int partitionIndex = partition(arr, left, right); quickSort(arr, left, partitionIndex - 1); quickSort(arr, partitionIndex + 1, right); } return arr; } private static int partition(int[] arr, int left, int right) { // 設定基准值(pivot) int pivot = left; int index = pivot + 1; for (int i = index; i <= right; i++) { if (arr[i] < arr[pivot]) { swap(arr, i, index); index++; } } swap(arr, pivot, index - 1); return index - 1; } private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } }