Data Structure
  • 資料結構自學筆記
  • 1 - Stack & Queue
    • 1.1 - Stack
    • 1.2 - Queue
    • 1.3 - Stack and Queue
  • 2 - Tree & Binary Tree
    • 2.1 - Tree
    • 2.2 - Binary Tree
    • 2.3 - Binary Tree Traversal
    • 2.4 - Binary Search Tree
    • 2.5 - Heap
    • 2.6 - Thread Binary Tree
    • 2.7 - Tree and Binary Tree Conversion
    • 2.8 Advanced Trees
      • 2.8.1 - Min-Max Heap
      • 2.8.2 - Deap
      • 2.8.3 - Symmetric Min-Max Heap
      • 2.8.4 - Extended Binary Tree
      • 2.8.5 - AVL Tree
      • 2.8.6 - M-Way Search Tree
      • 2.8.7 - B Tree
      • 2.8.8 - Red-Black Tree
      • 2.8.9 - Optimal Binary Search Tree
      • 2.8.10 - Splay Tree
      • 2.8.11 - Leftest Heap
      • 2.8.12 - Binomial Heap
  • 3 - Search & Sort
    • 3.1 - Searching
    • 3.2 - Elementary Sorting
      • 3.2.1 - Insertion Sort
      • 3.2.2 - Selection Sort
      • 3.2.3 - Bubble Sort
      • 3.2.4 - Shell Sort
    • 3.3 - Sophisticated Sorting
      • 3.3.1 - Quick Sort
      • 3.3.2 - Merge Sort
      • 3.3.3 - Heap Sort
      • 3.3.4 - Radix Sort
      • 3.3.5 - Bucket Sort
      • 3.3.6 - Counting Sort
    • 3.4 - Summary
  • 4 - Graph
    • 4.1 - Intro
    • 4.2 - Graph Traversal
    • 4.3 - Spanning Tree
      • 4.3.1 - Kruskal's algorithm
      • 4.3.2 - Prim's algorithm
      • 4.3.3 - Sollin's algorithm
    • 4.4 - Shortest Path Length
      • 4.4.1 - Dijkstra's algorithm
      • 4.4.2 - Bellman-Ford algorithm
      • 4.4.3 - Floyd-Warshall algorithm
    • 4.5 - AOV Network
    • 4.6 - AOE Network
    • 4.7 - Others
Powered by GitBook
On this page
  • 1. 演算法
  • 2. 性質
  1. 3 - Search & Sort
  2. 3.3 - Sophisticated Sorting

3.3.1 - Quick Sort

Previous3.3 - Sophisticated SortingNext3.3.2 - Merge Sort

Last updated 6 years ago

1. 演算法

採用Divide and Conquer策略。選定一個pivot key使得:

  1. A[1]~A[q-1] ≤ p.k

  2. A[q+1]~A[n] ≥ p.k

此時資料被分成左右兩個sublist,再各自排列,當左右sublist排完,整個資料也就排序完成。

排序步驟範例:

A[8]={5,9,8,2,3,6,4,7}⇒p.k=5A[8]=\{5,9,8,2,3,6,4,7\} \Rightarrow p.k=5A[8]={5,9,8,2,3,6,4,7}⇒p.k=5

iii 找到大於p.k的位置, jjj找到小於p.k的位置 ⇒A[1]=9, A[6]=4\Rightarrow A[1]=9,\ A[6]=4⇒A[1]=9, A[6]=4

swap⇒{5,4‾,8,2,3,6,9‾,7}swap \Rightarrow \{5,\underline{4},8,2,3,6,\underline{9},7\}swap⇒{5,4​,8,2,3,6,9​,7}

iii 找到大於p.k的位置, jjj找到小於p.k的位置 ⇒A[2]=8, A[4]=3\Rightarrow A[2]=8,\ A[4]=3⇒A[2]=8, A[4]=3

swap⇒{5,4,3‾,2,8‾,6,9,7}swap \Rightarrow \{5,4,\underline{3},2,\underline{8},6,9,7\}swap⇒{5,4,3​,2,8​,6,9,7}

當 i≥ji≥ji≥j時,p.k和 A[j]A[j]A[j]交換位置,此時 j=3j=3j=3

⇒{[2,4,3],5,[8,6,9,7]}\Rightarrow \{[2,4,3],5,[8,6,9,7]\}⇒{[2,4,3],5,[8,6,9,7]}

採用同樣方法sort({2,3,4})、sort({8,6,9,7})

void Sort(char *arr, int l, int u){
    if (l >= u) return; //判斷sorting結束
    int pk = arr[l];    //選pk
    int i = l;
    int j = u ;
    int temp;
    while (i<j){        //直到i>j
        while (arr[i]<pk) i++;
        while (arr[j]>pk) j--;
        if (i<j){     //swap
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    temp = arr[l];    //j與pk交換位置
    arr[l] = arr[j];
    arr[l] = temp;
    Sort(arr, l, j-1);  //左邊sublist
    Sort(arr, j+1, u);  //右邊sublist
}

2. 性質

  • Time Complexity:

Quick sorting is a unstable sorting method.

Best Case: O(nlogn)O(nlogn)O(nlogn)

⇒\Rightarrow⇒ p.k的位置恰將資料分割成兩等份

T(n)=C×n+T(n2)+T(n2)T(n)=C\times n+T(\frac{n}{2})+T(\frac{n}{2})T(n)=C×n+T(2n​)+T(2n​) C*n為分割所花時間

T(n)=2T(n2)+C×nT(n)=2T(\frac{n}{2})+C\times nT(n)=2T(2n​)+C×n

T(n2)=2T(n4)+C×n2T(\frac{n}{2})=2T(\frac{n}{4})+C\times\frac{n}{2}T(2n​)=2T(4n​)+C×2n​

T(n)=2[2T(n4)+C×n2]+C×n=4T(n4)+2(C×n)T(n)=2[2T(\frac{n}{4})+C\times\frac{n}{2}]+C\times n=4T(\frac{n}{4})+2(C\times n)T(n)=2[2T(4n​)+C×2n​]+C×n=4T(4n​)+2(C×n)

T(n)=nT(1)+log⁡2n(C×n)T(n)=nT(1)+\log_2n(C\times n)T(n)=nT(1)+log2​n(C×n)

Worst Case: O(n2)O(n^2)O(n2)

⇒\Rightarrow ⇒ p.k恰好是最大值或是最小值,使得分割無效果

T(n)=C×n+T(n−1)T(n)=C\times n+T(n-1)T(n)=C×n+T(n−1) C*n為分割所花時間

T(n)=C(n+(n−1))+T(n−2)T(n)=C(n+(n-1))+T(n-2)T(n)=C(n+(n−1))+T(n−2)

T(n)=C(n+...+2)+T(1)=C(n+2)(n−1)2T(n)=C(n+...+2)+T(1)=\frac{C(n+2)(n-1)}{2}T(n)=C(n+...+2)+T(1)=2C(n+2)(n−1)​

Space Complexity: O(logn)O(logn)O(logn)~ O(n)O(n)O(n)

⇒\Rightarrow⇒ 額外空間需求來自於recursion所需的stack,stack size取決於recursion call的次數。

Best Case: O(logn)O(logn)O(logn)

⇒\Rightarrow⇒ 每次p.k的位置恰將資料分割成兩等份,經過k次呼叫後只剩一筆Data, n2k=1, k=log2n\frac{n}{2^k}=1,\ k=log_2n2kn​=1, k=log2​n

Worst Case: O(n)O(n)O(n)

⇒\Rightarrow⇒ p.k恰好是最大值或是最小值,使得分割無效果,資料大小為n, n-1, n-2,...,共需n次呼叫

{3p.k, 5, 5∗, 1, 2}⇒[1, 2], 3, [5∗, 5]\{3_{p.k},\ 5,\ 5^*,\ 1,\ 2 \} \Rightarrow [1,\ 2],\ 3,\ [5^*,\ 5]{3p.k​, 5, 5∗, 1, 2}⇒[1, 2], 3, [5∗, 5]