資料結構-排序-快速排序之固定位置選取基準法(遞迴/非遞迴)
阿新 • • 發佈:2018-12-18
快速排序: 資料量小的時候,使用插入排序;聚焦相同基準元素法
- 固定位置選取排序:資料越有序,複雜度越高
- 隨機選取基準排序
- 三分取中法
思想:均勻的分割待排序序列 :選取一個基準par,定義兩個指標 low high 一般基準選取low下標的值;如果high下標的值比par大,high–;反之將high的值放到low 下標; low的操作和high 一樣 ;當high和low 相遇時,將par放到low角標,此時,左邊全是比par小的,右邊全是比par 大的;
快速排序:遞迴實現 ,一趟排序結束後如果基準左右兩邊的元素數量大於等於2,那麼說明左右還沒有有序,那麼在確定新的low 和high的值 繼續呼叫此方法;
public static int partion(int []array ,int low,int high){ //一趟快速排序; int tmp=array[low]; while(low<high){ while(low<high&& array[high]>tmp){ //如果high對應的元素大於tmp; high--; } if(low >= high) { break; } else { array[low] = array[high]; } while(low < high && array[low] <= tmp) { low++; } if(low >= high) { break; } else { array[high] = array[low]; } } array[low] = tmp; return low; } /** * 時間複雜度:O(nlog2n) * 空間複雜度:O(log2n) * 穩定性:不穩定 * @param array * @param low * @param high */ public static void quick(int [] array ,int low,int high ){ int par=partion(array,low,high); 返回下一趟排序的基準; if(par>low+1){ //新的基準與邊界之間的元素大於等於兩個就可以確定新的par quick(array,low,par-1); //log 2 N; 基準左邊遞迴 } if(par<high-1){ quick(array ,par+1,high); //右邊遞迴。 } } public static void quickSort(int array){ quick(array,0,array.length-1); } public static void main(String[] args) { int[] array = new int[10000];//n log2n Random random = new Random(); for (int i = 0; i < array.length; i++) { array[i] = random.nextInt(10000)+1; } System.out.println(System.currentTimeMillis()); quickSort(array); System.out.println(System.currentTimeMillis()); System.out.println(Arrays.toString(array)); }
快速排序: 非遞迴解法 :思想和遞迴解法差不多,只不過左右兩邊沒有序,將新的low和high壓入模擬棧中;在呼叫確定基準並排序的方法;只要棧不為空,那麼就需要進行排序
public class TestQuickSort { //一趟快速排序函式 public static int partion(int[] array,int low,int high) { int tmp = array[low]; while(low < high) { while(low < high && array[high] >= tmp) { high--; } if(low >= high) { break; } else { array[low] = array[high]; } while(low < high && array[low] <= tmp) { low++; } if(low >= high) { break; } else { array[high] = array[low]; } } array[low] = tmp; return low; } public static void quickSort(int [] array){ int high=array.length-1; int low=0; int par=partion(array,low,high); int size=(int)(Math.log(double)array.length/Math.log2d+1); //這裡如果閒麻煩可以直接將長度確定為array 的長度; int [] stack=new int [size*3] //log2n //按理應該是*2 但是溢位,所以*3 。 可以直接放array的長度; int top=0; if(par>low+1){ //先壓第一次迴圈後符合條件的,在進迴圈 stack[top++]=low; 先入後出 stack[top++]=par-1; } if(par<high-1){ stack[top++]=par+1; stack[top++]=high; } while(top>0){ //每次出一對low high 排序 high=stack[--top]; //後進先出 low=stack[--top]; par=partion(array,low,high);//呼叫一次快排確定新的基準 if(par>low+1){ stack[top++]=low; 先入後出 stack[top++]=par-1; } if(par<high-1){ stack[top++]=par+1; stack[top++]=high; } } } public static void main(String[] args) { int[] array = new int[10000];//n log2n Random random = new Random(); for (int i = 0; i < array.length; i++) { array[i] = random.nextInt(10000)+1; } System.out.println(System.currentTimeMillis()); quickSort(array); System.out.println(System.currentTimeMillis()); System.out.println(Arrays.toString(array)); } }