快速排序排與堆排序
阿新 • • 發佈:2020-07-24
引子
最近練習時,覺得有些生疏,所以加強鍛鍊。
具體實現
快速排序(從小到大排序,升序)
public class QuickSort{ public static void swap(int[] arr, int i, int j){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void sort(int[] arr, int startIndex, int endIndex){ if(arr != null && arr.length > 0){ int start = startIndex, end = endIndex; // 預設以第一個作為基準 int target = arr[startIndex]; // 外迴圈,兩頭往中間迴圈,兩邊相遇時結束 while(start < end){ // 第一個內迴圈,先從右側開始遍歷,直到遇到比target小的數,進行交換 while(start < end){ if(arr[end] < target){ swap(arr, start, end); break; }else{ end --; } } //第二個內迴圈,在前一個內迴圈的基礎上,從左側開始遍歷,找到比target小的數字,進行交換 while(start < end){ if(arr[start] > target){ swap(arr,start, end); break; }else{ start++; } } } //經過前面兩個迴圈,start和end相遇,如果start到startIndex還有元素,對這部分進行排序 if((start-1) > startIndex){ sort(arr,startIndex,start-1); } //同理,如果end到endIndex中還有元素,對這部分進行排序 if((end+1) < endIndex){ sort(arr,end+1,endIndex); } } } public static void main(String[] args){ int[] arr = new int[]{4,3,1,6,9,5,8}; sort(arr,0,arr.length-1); for(int i:arr){ System.out.print(i+" "); } System.out.println(""); } }
堆排序(大頂堆,從大到小排序,降序)
class HeapSort { public static void main(String[] args) { // int[] arr = {5, 1, 7, 3, 1, 6, 9, 4}; int[] arr = {16, 7, 3, 20, 17, 8}; heapSort(arr); for (int i : arr) { System.out.print(i + " "); } } /** * 建立堆, * @param arr 待排序列 */ private static void heapSort(int[] arr) { //建立堆 for (int i = (arr.length - 1) / 2; i >= 0; i--) { //從第一個非葉子結點從下至上,從右至左調整結構 adjustHeap(arr, i, arr.length); } //調整堆結構+交換堆頂元素與末尾元素 for (int i = arr.length - 1; i > 0; i--) { //將堆頂元素與末尾元素進行交換 int temp = arr[i]; arr[i] = arr[0]; arr[0] = temp; //重新對堆進行調整 adjustHeap(arr, 0, i); } } /** * 調整堆 * @param arr 待排序列 * @param parent 父節點 * @param length 待排序列尾元素索引 */ private static void adjustHeap(int[] arr, int parent, int length) { //將temp作為父節點 int temp = arr[parent]; //左孩子 int lChild = 2 * parent + 1; while (lChild < length) { //右孩子 int rChild = lChild + 1; // 如果有右孩子結點,並且右孩子結點的值大於左孩子結點,則選取右孩子結點 if (rChild < length && arr[lChild] > arr[rChild]) { lChild++; } // 如果父結點的值已經大於孩子結點的值,則直接結束 if (temp < arr[lChild]) { break; } // 把孩子結點的值賦給父結點 arr[parent] = arr[lChild]; //選取孩子結點的左孩子結點,繼續向下篩選 parent = lChild; lChild = 2 * lChild + 1; } arr[parent] = temp; } }