交互排序思想:在待排序的序列中選擇兩個記錄,將他們的關鍵碼進行比較。若是反序則交互它們的位置。 java
基本思想:將序列分爲有序區,無序區。每次從無序區冒泡一個最小的記錄。 算法
冒泡過程:從無序區從後往前掃描,兩個相鄰記錄比較,若是後面比前面的小,則交互。 ui
算法分析 指針
/** * 將序列分爲兩部分:有序區:無序區 <br> * 每趟從無序區 冒泡一個最小的,有序區+1. * 穩定的排序 * * @param arr */ public static void bubble_normal(int[] arr) { int size = arr.length; for (int i = 0; i < size - 2; i++) { //n-1輪冒泡 for (int j = size - 1; j > i; j--) { if (arr[j] < arr[j - 1]) // 從後往前,小的記錄往前冒泡 MathUtil.swap(arr, j, j - 1); } System.out.println("第 " + (i + 1) + "輪 :" + Arrays.toString(arr)); } }
冒泡排序的變體orm
/** * 非冒泡排序,也非選擇排序,姑且叫他假冒泡<br> * 將序列分爲兩部分:有序區:無序區<br> * 每輪排序從無序區找到一個最小記錄,無序區長度-1<br> * * 找到一個最小記錄的過程:<br> * 用無序區的第一個元素存儲最小記錄。<br> * 對比交換:最小記錄>無序區記錄就交換<br> * 紀錄在排序過程當中的移動不是冒泡,而是跳躍的交換。不穩定的排序<br> * * 缺點:原本位於前面的較小數被交換到後面 * * @param arr */ public static void bubble_fake(int[] arr) { int size = arr.length; for (int i = 0; i < size - 2; i++) {//n-1輪 for (int j = i + 1; j < size; j++) { if (arr[j] < arr[i]) //確保arr[i]爲無序區最小的 MathUtil.swap(arr, i, j); } System.out.println("第 " + (i+1) + "輪 :" + Arrays.toString(arr)); } } /** * 冒泡算法的改進,增長isSwaped標誌<br> * 在一輪循環中記錄沒有交互,也就代表序列已經有序的。<br> * 當記錄交換(冒泡)則isSwaped=true;說明無序。<br> * @param arr */ public static void bubble_optimize(int[] arr) { int size = arr.length; boolean isSwaped = true; for (int i = 0; i < size - 2 && isSwaped; i++) {//n-1輪 isSwaped = false; // 重置狀態 for (int j = size - 1; j > i; j--) { if (arr[j] < arr[j - 1]) { // 從後往前,小的記錄往前冒泡 MathUtil.swap(arr, j, j - 1); isSwaped = true; // 改變則賦值true } System.out.println("\t" + Arrays.toString(arr)); } System.out.println("isChanged:" + isSwaped); System.out.println("第 " + (i + 1) + "輪 :" + Arrays.toString(arr)); } }
基本思想:選擇一個軸值,將待排序列分爲兩個部分,左側記錄均小於軸值,右側記錄均大於軸值。 blog
劃分過程:頭尾兩根指針分別指向劃分區間的頭尾,分別向中間靠攏。 排序
過程當中,若是尾針所指的記錄<軸值,交互,頭指針所指記錄>軸值,交互。這樣就保證了軸值前的全部記錄都小於軸值,軸值以後的記錄都大於軸值。 遞歸
直到兩根指針相遇的位置,即軸值的最終位置。完成劃分。 ip
排序過程:將序列一次劃分後,分別對兩個子序列進行劃分(遞歸處理),直到劃分區間<1 。 get
一次劃分圖示:
算法分析
/** * 劃分區間:arr[first]~arr[end]<br> * 右側掃描:直到 尾指針 指向的記錄 小於 軸值,交互,頭指針+1。<br> * 左側掃描:直到 頭指針 指向的記錄 大於 軸值,交互,尾指針-1。<br> * 頭尾兩根指針相遇,完成劃分。<br> * * @param arr * @param first 劃分區間的頭指針 * @param end 劃分區間的頭指針 * @return */ public static int partition(int[] arr, int first, int end) { while (first < end) {//頭尾指針相遇,退出循環,即爲最終的軸值記錄的位置 while (first < end && arr[first] < arr[end])// 右側掃描 end--; if (first < end) { MathUtil.swap(arr, first, end);// 較小記錄交互到前面 first++; } //具備操做的對稱性 while (first < end && arr[first] < arr[end])// 左側掃描 first++; if (first < end) { MathUtil.swap(arr, first, end);// 較大記錄交互到後面 end--; } } return first; } /** * 將序列一次劃分後,分別對兩個子序列進行劃分(遞歸處理),直到劃分區間<1 <br> * @param arr * @param first * @param end */ public static void quickSort(int[] arr,int first, int end){ if(first<end){//區間長度<1,遞歸結束 int pivot=partition(arr, first, end); quickSort(arr, first, pivot - 1);//遞歸對左側子序列進行快排 quickSort(arr, pivot + 1, end); //遞歸對右側子序列進行快排 } } public static void qsort(int[] arr){ quickSort(arr, 0, arr.length-1); }