/** * 快速排序 * 分治、遞歸思想 * 如果要排序數組中下標從 p 到 r 之間的一組數據,我們選擇 p 到 r 之間的任意一個數據作爲 pivot (分區點)。 我們遍歷 p 到 r 之間的數據,將小於 pivot 的放到左邊,將大於 pivot 的放右邊,pivot 放到中間。經過這一步驟之後,數組 p 到 r 之間的數據就被分成了三個部分,前面 p 到 q-1 之間都是小於pivot的,中間是pivot,後面的q+1到r之間是大於pivot的,根據分治、遞歸思想,我們可以用遞歸排序下標從p到q-1之間的數據和下標q+1到r之間的數據,直到區間縮小爲1,就說明所有的都是有序了 * 最好和平均複雜度爲 O(nlogn),最壞時間複雜度爲O(n²),不穩定的原地排序算法 * * @param data */ public static void quickSort(int[] data){ quickSortInternally(data,0,data.length - 1); } private static void quickSortInternally(int[] data,int p,int r){ if(p>=r) return; int midden = getMidden(data,p,r); quickSortInternally(data,p,midden - 1); quickSortInternally(data,midden + 1,r); } private static int getMidden(int[] data,int p,int r){ int i = p; int pivot = data[r]; for (int j=p;j<r ;j++){ if(data[j]<pivot){ int temp = data[i]; data[i] = data[j]; data[j] = temp; i++; } } int temp = data[i]; data[i]= data[r]; data[r] = temp; System.out.println("i="+i); return i; } /** * 歸併排序 * 分治、遞歸思想 * 要排序一個數組,我們先把數組從中間分成前後兩部分,然後對前後兩部分進行排序,然後將排序好的兩部分合並 * 最好、最壞、平均時間複雜度都爲 O(nlogn),需要空間複雜度爲O(n),是穩定的非原地算法 * @param data * @param p * @param r */ public static void mergeSort(int[] data,int p,int r){ //終止條件 if(p>=r) return; //防止 p和r過大,(p+r)溢出 int q = p +(r- p)/2; //分治遞歸 mergeSort(data,p,q); mergeSort(data,q + 1,r); // 將A[p...q]和A[q+1...r]合併爲A[p...r] merge(data,p,q,r); } private static void merge(int[] data,int p,int q,int r){ int i= p; int j = q +1; int k = 0; int[] temp = new int[r-p + 1]; while (i<=q && j<=r){ if(data[i]<=data[j]){ temp[k++] = data[i++]; }else { temp[k++] = data[j++]; } } // 判斷哪個子數組中有剩餘的數據 int start = i; int end = q; if(j<=r){ start = j; end = r; } // 將剩餘的數據拷貝到臨時數組tmp while (start <= end){ temp[k++]=data[start ++]; } //將臨時變量拷貝回a[p..r] for (i=0;i<=r-p;i++){ data[p+i] = temp[i]; } } /** * 冒泡排序,只會操作相鄰的兩個數據。每次冒泡操作都會對相鄰的兩個元素進行比較,看是否滿足大小關係要求,如果不滿足就讓他互換。一次冒泡會讓至少一個元素移動到它應該在的位置,重複n次,就完成了n個數據的排序工作 * 爲原地穩定算法,時間複雜度爲n²,最好時間複雜度爲n,平均和最壞情況爲n² * @param data */ public static void bubbleSort(int[] data){ if(data ==null || data.length <= 1) return; int n = data.length; for (int i=0;i<n;i++){ //提前退出標識 boolean flag =false; for(int j=0;j<n-i-1;j++){ if(data[j]>data[j+1]){ int temp = data[j]; data[j] = data[j+1]; data[j+1] = temp; flag = true; } } if(!flag) break; } } /** * 插入排序 * 首先我們將數組中數據分爲兩個區間,已排序和未排序區間。初始化時已排序區間只有一個元素,就是數組的第一個元素。插入算法的核心思想是取未排序算法中的元素,在已排序算法中找到合適的插入位置將其插入 * 原地穩定算法,時間複雜度爲O(n2),但它賦值次數比冒泡的少(插入賦值一次,冒泡3次),所以效率比冒泡的高 * @param data */ public static void insertSort(int[] data){ if(data == null || data.length <= 1) return; for (int i=1;i<data.length;i++){ int val = data[i]; int j = i - 1; //查找插入的位置 for(; j>=0 ;j--){ if(data[j]>val){ //數據移動 data[j+1] = data[j]; }else { break; } } //找到位置插入 data [j + 1] = val; } } public static void main(String[] args) { int[] data ={6,11,3,9,8}; quickSort(data); System.out.println("快排結果爲"+ Arrays.toString(data)); data =new int[]{6,11,3,9,8}; mergeSort(data,0,data.length-1); System.out.println("歸併排序結果爲"+ Arrays.toString(data)); data =new int[]{6,11,3,9,8}; bubbleSort(data); System.out.println("冒泡排序結果爲"+ Arrays.toString(data)); data =new int[]{6,11,3,9,8}; insertSort(data); System.out.println("插入排序結果爲"+ Arrays.toString(data)); }
java 基本排序
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.