[程式設計題] 單鏈錶快排與陣列快排
阿新 • • 發佈:2020-07-23
單鏈錶快排與陣列快排
時間:2020.07.23
一、傳統快排思想
思想簡介:
-
傳統的快速排序演算法使用到遞迴
-
快排是對氣泡排序演算法的一種改進。基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料小,然後再按照此方法對兩部分資料使用
遞迴
進行如上操作。使得整個資料達到有序序列。
特點:在單項鍊表中無法應用。
圖解
流程
Java程式碼
package demo08; import java.text.BreakIterator; import java.util.Arrays; /** * @author jiyongjia * @create 2020/7/23 - 10:27 * @descp: */ public class Demo01_kuaipai { public static void main(String[] args) { int[] arr = new int[]{-9,78,0,23,-2,70,-32,323,-222,421}; quickSort1(arr,0,arr.length-1); System.out.println(Arrays.toString(arr)); } public static void quickSort(int[] arr,int left,int right){ int l = left; int r = right; int mid = (l+r)/2; int midValue = arr[mid]; while (l<r){ //左找 while(arr[l]<midValue){ l++; } //右找 while(arr[r]>midValue){ r--; } //判斷退出條件 if(l>=r){ break; } //不然的話就交換 int temp = arr[l]; arr[l] = arr[r]; arr[r] = temp; //處理邊界條件 if(arr[l] == midValue){ r--; } if(arr[r] == midValue){ l++; } } //處理死鎖 if(l==r){ l++; r--; } //左遞迴 if(left<r){ quickSort(arr,left,r); } //右遞迴 if(right>l){ quickSort(arr,l,right); } } public static void quickSort1(int[] arr,int left,int right){ int l = left; int r = right; int mid = (l+r)/2; int midValue = arr[mid]; while (l<r){ //左邊找 while(arr[l]<midValue){ l++; } //右邊找 while (arr[r]>midValue){ r--; } //判斷退出條件 if (l>=r){ break; } //找到交換的兩個數字就交換 int temp = arr[l]; arr[l] = arr[r]; arr[r] = temp; //防止死鎖 if(arr[l]==midValue){ r--; } if(arr[r]==midValue){ l++; } } if(l==r){ l++; r--; } //左遞迴 if(r>left){ quickSort1(arr,left,r); } if(l<right){ quickSort1(arr,l,right); } } }
二、快排新思想
思想:
案例
特點:
可以應用在陣列,也可以應用在單向連結串列
實現對陣列的快排
Java程式碼:
package demo08; import java.util.Arrays; /** * @author jiyongjia * @create 2020/7/23 - 16:33 * @descp: 快排陣列 */ public class Demo06_quickSort2 { public static void main(String[] args) { int[] ints = {-2, 3, 5, 3, 88, 8, 1}; quickSort(ints,0,ints.length-1); System.out.println(Arrays.toString(ints)); } public static void quickSort(int[] arr, int left, int right) { //遞迴的結束條件 if(left<right){ int base = arr[left]; //選擇一個基本的比較的節點,每次預設是該組元素的第一個 int i = left+1; // i和j指標都是指向了base後的那個元素 int j = left+1; //j指標一直在後移比較,如果發現小於base的數就和base交換,並且i++;j++; //如果j的值不大於base,就j指標一直後移,直到結束 while (j<=right){ if(arr[j]<base){ swep(arr,i,j); i++; } j++; } //當j走到頭的時候,那麼此時就找新的base的位置(老base位置和i指標前的那個數交換) swep(arr,left,i-1); //左遞迴 quickSort(arr,left,i-2); //右遞迴 quickSort(arr,i,right); } } //負責交換的函式 public static void swep(int[] arr,int i,int j){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } }
輸出:
實現對連結串列的快排
Java程式碼:
package demo08; import com.sun.jndi.toolkit.ctx.StringHeadTail; /** * @author jiyongjia * @create 2020/7/23 - 20:37 * @descp: 快排單鏈表 */ public class Demo07_quickSortLinkedList { //測試用例 public static void main(String[] args) { Node head = new Node(2); Node node1 = new Node(1); Node node2 = new Node(65); Node node3 = new Node(3); Node node4 = new Node(8); head.next=node1; node1.next=node2; node2.next=node3; node3.next=node4; //排序前的連結串列 System.out.println("排序前的連結串列情況:"); Node dummy = head; while (dummy!=null){ System.out.print(dummy+"==>>"); dummy = dummy.next; } //呼叫 entrance(head); } //主要入口方法 public static void entrance(Node head){ //如果題目只給了頭節點,我們需要遍歷出尾節點 Node cur = head; while (cur.next!=null){ cur = cur.next; } //呼叫連結串列快排 quickSortLinkedList(head,cur); //打印出最終的連結串列情況 System.out.println("\n排序後的連結串列情況:"); while (head!=null){ System.out.print(head+"==>>"); head = head.next; } } //連結串列快排演算法 public static void quickSortLinkedList(Node head,Node tail){ if(head==null || head.next==null || head==tail) { return;//結束 } Node base = head; //基準比較的值,預設是本組的頭節點 Node i = head.next; //i指標是頭節點後 Node i_pre = head; //記錄i的前一個節點 Node j = head.next; //j指標是頭節點後 while (j!=tail.next){ //j走完了整個連結串列,走到tail if(j.val < base.val){ swep(i,j); //執行交換i 和 j的值 i_pre = i; //先記錄i的前一個值 i = i.next;//再讓i指標後移 } j = j.next; //j指標後移 } //退出while即走到連結串列尾部,重新找base節 swep(head,i_pre); //左遞迴 quickSortLinkedList(head,i_pre); //右遞迴 quickSortLinkedList(i,tail); } //交換兩節點中的值 private static void swep(Node i,Node j) { int temp = i.val; i.val = j.val; j.val = temp; } } //節點定義 class Node{ int val; Node next; public Node(int val){ this.val = val; } @Override public String toString() { return "Node{" + "val=" + val + '}'; } }
輸出測試結果: