57.md 10.0 KB
Newer Older
W
wizardforcel 已提交
1 2 3 4
# 快速排序算法

> 原文: [https://www.programiz.com/dsa/quick-sort](https://www.programiz.com/dsa/quick-sort)

W
wizardforcel 已提交
5
#### 在本教程中,您将学习快速排序的工作原理。 此外,您还将找到 C,C++  Python 和 Java 中快速排序的工作示例。
W
wizardforcel 已提交
6

W
wizardforcel 已提交
7
快速排序是一种基于分治方法的算法,其中将数组拆分为子数组,然后递归调用这些子数组以对元素进行排序。
W
wizardforcel 已提交
8 9 10

* * *

W
wizardforcel 已提交
11
## 快速排序如何工作?
W
wizardforcel 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

1.  从数组中选择枢轴元素。 您可以从数组中选择任何元素作为枢轴元素。
    在这里,我们将数组的最右边(即最后一个元素)作为枢轴元素。

    ![Quick Sort Steps](img/b32e09ddb0be0b5a2dfaf5b6f8844cf4.png "Selection of rightmost element")

    选择枢轴元素

    

2.  小于枢轴元素的元素放在左侧,大于枢轴元素的元素放在右侧。

    ![Quick Sort Steps](img/c49c33dfcb5bbf5262a2da96f34fadef.png "pivoting")

    将所有较小的元素放在枢轴元素

    

    的左侧,将较大的元素放在右侧。
    1.  指针固定在枢轴元件上。 将枢轴元素与从第一个索引开始的元素进行比较。 如果达到大于枢轴元素的元素,则为该元素设置第二个指针。
    2.  现在,将枢轴元素与其他元素(第三个指针)进行比较。 如果到达的元素小于枢轴元素,则将较小的元素替换为较早找到的较大的元素。

        ![Quick Sort Steps](img/4079763eb43119ba57d70efb790b0f4c.png "comparison")

        枢轴元素与其他元素的比较

        

    3.  该过程一直进行到到达倒数第二个元素为止。
        最后,将枢轴元素与第二个指针交换。

        ![Quick Sort Steps](img/4824ca4c010875951d98c61370ecc47a.png "swapping")

        与第二个指针

        

        交换枢轴元素
3.  再次分别为左子部分和右子部分选择了枢轴元素。 在这些子部件中,枢轴元件放置在正确的位置。 然后,重复步骤 2。

    ![Quick Sort Steps](img/5387573ae3499df532f56740aa08de6f.png "Quick Sort Steps")

    在每一半中选择枢轴元素,然后使用递归

    

    将其放置在正确的位置
4.  将子部分再次划分为较小的子部分,直到每个子部分由单个元素形成。
5.  至此,该数组已经排序。

* * *

W
wizardforcel 已提交
64
**快速排序使用递归对子部分进行排序。**
W
wizardforcel 已提交
65 66 67 68 69

[分治法](/dsa/divide-and-conquer)的基础上,快速排序算法可以解释为:

*   **划分**
    将数组划分为以枢轴为分割点的子部分。 小于枢轴的元素放置在枢轴的左侧,大于枢轴的元素放置在右侧。
W
wizardforcel 已提交
70
*   **解决**
W
wizardforcel 已提交
71 72
    左子部分和右子部分再次通过选择枢轴元素进行划分。 这可以通过将子部分递归传递到算法中来实现。
*   **合并**
W
wizardforcel 已提交
73
    此步骤在快速排序中不起作用。 该数组已在解决步骤的末尾排序。
W
wizardforcel 已提交
74 75 76 77 78

您可以在以下插图的帮助下了解快速排序的工作方式。

![Quick Sort Steps](img/f22e800cc6e33667304b08b82f725430.png "Quick Sort first half")

W
wizardforcel 已提交
79
使用递归对枢轴左侧的元素进行排序
W
wizardforcel 已提交
80 81 82 83 84



![Quick Sort Steps](img/78b8af5cbc89bddf72c6913bd6623b60.png "Quick Sort second half")

W
wizardforcel 已提交
85
使用递归对枢轴右侧的元素进行排序
W
wizardforcel 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112



* * *

## 快速排序算法

```
quickSort(array, leftmostIndex, rightmostIndex)
  if (leftmostIndex < rightmostIndex)
    pivotIndex <- partition(array,leftmostIndex, rightmostIndex)
    quickSort(array, leftmostIndex, pivotIndex)
    quickSort(array, pivotIndex + 1, rightmostIndex)

partition(array, leftmostIndex, rightmostIndex)
  set rightmostIndex as pivotIndex
  storeIndex <- leftmostIndex - 1
  for i <- leftmostIndex + 1 to rightmostIndex
  if element[i] < pivotElement
    swap element[i] and element[storeIndex]
    storeIndex++
  swap pivotElement and element[storeIndex+1]
return storeIndex + 1
```

* * *

W
wizardforcel 已提交
113
## Python,Java 和 C/C++ 示例
W
wizardforcel 已提交
114

W
wizardforcel 已提交
115

W
wizardforcel 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346

```
# Quick sort in Python

# Function to partition the array on the basis of pivot element
def partition(array, low, high):

    # Select the pivot element
    pivot = array[high]
    i = low - 1

    # Put the elements smaller than pivot on the left and greater 
    #than pivot on the right of pivot
    for j in range(low, high):
        if array[j] <= pivot:
            i = i + 1
            (array[i], array[j]) = (array[j], array[i])

    (array[i + 1], array[high]) = (array[high], array[i + 1])

    return i + 1

def quickSort(array, low, high):
    if low < high:

        # Select pivot position and put all the elements smaller 
        # than pivot on left and greater than pivot on right
        pi = partition(array, low, high)

        # Sort the elements on the left of pivot
        quickSort(array, low, pi - 1)

        # Sort the elements on the right of pivot
        quickSort(array, pi + 1, high)

data = [8, 7, 2, 1, 0, 9, 6]
size = len(data)
quickSort(data, 0, size - 1)
print('Sorted Array in Ascending Order:')
print(data)
```

```
// Quick sort in Java

import java.util.Arrays;

class QuickSort {

  // Function to partition the array on the basis of pivot element
  int partition(int array[], int low, int high) {

    // Select the pivot element
    int pivot = array[high];
    int i = (low - 1);

    // Put the elements smaller than pivot on the left and 
    // greater than pivot on the right of pivot
    for (int j = low; j < high; j++) {
      if (array[j] <= pivot) {
        i++;
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
      }
    }
    int temp = array[i + 1];
    array[i + 1] = array[high];
    array[high] = temp;
    return (i + 1);
  }

  void quickSort(int array[], int low, int high) {
    if (low < high) {

      // Select pivot position and put all the elements smaller 
      // than pivot on left and greater than pivot on right
      int pi = partition(array, low, high);

      // Sort the elements on the left of pivot
      quickSort(array, low, pi - 1);

      // Sort the elements on the right of pivot
      quickSort(array, pi + 1, high);
    }
  }

  // Driver code
  public static void main(String args[]) {
    int[] data = { 8, 7, 2, 1, 0, 9, 6 };
    int size = data.length;
    QuickSort qs = new QuickSort();
    qs.quickSort(data, 0, size - 1);
    System.out.println("Sorted Array in Ascending Order: ");
    System.out.println(Arrays.toString(data));
  }
}
```

```
// Quick sort in C

#include <stdio.h>

// Function to swap position of elements
void swap(int *a, int *b) {
  int t = *a;
  *a = *b;
  *b = t;
}

// Function to partition the array on the basis of pivot element
int partition(int array[], int low, int high) {

  // Select the pivot element
  int pivot = array[high];
  int i = (low - 1);

  // Put the elements smaller than pivot on the left 
  // and greater than pivot on the right of pivot
  for (int j = low; j < high; j++) {
    if (array[j] <= pivot) {
      i++;
      swap(&array[i], &array[j]);
    }
  }

  swap(&array[i + 1], &array[high]);
  return (i + 1);
}

void quickSort(int array[], int low, int high) {
  if (low < high) {

    // Select pivot position and put all the elements smaller 
    // than pivot on left and greater than pivot on right
    int pi = partition(array, low, high);

    // Sort the elements on the left of pivot
    quickSort(array, low, pi - 1);

    // Sort the elements on the right of pivot
    quickSort(array, pi + 1, high);
  }
}

// Function to print eklements of an array
void printArray(int array[], int size) {
  for (int i = 0; i < size; ++i) {
    printf("%d  ", array[i]);
  }
  printf("\n");
}

// Driver code
int main() {
  int data[] = {8, 7, 2, 1, 0, 9, 6};
  int n = sizeof(data) / sizeof(data[0]);
  quickSort(data, 0, n - 1);
  printf("Sorted array in ascending order: \n");
  printArray(data, n);
}
```

```
// Quick sort in C++

#include <iostream>
using namespace std;

// Function to swap position of elements
void swap(int *a, int *b) {
  int t = *a;
  *a = *b;
  *b = t;
}

// Function to print eklements of an array
void printArray(int array[], int size) {
  int i;
  for (i = 0; i < size; i++)
    cout << array[i] << " ";
  cout << endl;
}

// Function to partition the array on the basis of pivot element
int partition(int array[], int low, int high) {
  // Select the pivot element
  int pivot = array[high];
  int i = (low - 1);

  // Put the elements smaller than pivot on the left 
  // and greater than pivot on the right of pivot
  for (int j = low; j < high; j++) {
    if (array[j] <= pivot) {
      i++;
      swap(&array[i], &array[j]);
    }
  }
  printArray(array, 7);
  cout << "........\n";
  swap(&array[i + 1], &array[high]);
  return (i + 1);
}

void quickSort(int array[], int low, int high) {
  if (low < high) {
    // Select pivot position and put all the elements smaller 
    // than pivot on left and greater than pivot on right
    int pi = partition(array, low, high);

    // Sort the elements on the left of pivot
    quickSort(array, low, pi - 1);

    // Sort the elements on the right of pivot
    quickSort(array, pi + 1, high);
  }
}

// Driver code
int main() {
  int data[] = {8, 7, 6, 1, 0, 9, 2};
  int n = sizeof(data) / sizeof(data[0]);
  quickSort(data, 0, n - 1);
  cout << "Sorted array in ascending order: \n";
  printArray(data, n);
}
```

* * *

W
wizardforcel 已提交
347
## 快速排序的复杂度
W
wizardforcel 已提交
348 349 350

**时间复杂度**

W
wizardforcel 已提交
351
*   **最坏情况的复杂度【大 O】**`O(n^2)`
W
wizardforcel 已提交
352
    当拾取的枢轴元素为最大或最小元素时,会发生这种情况。
W
wizardforcel 已提交
353
    这种情况导致枢轴元素位于已排序数组的最末端的情况。 一个子数组始终为空,而另一个子数组包含`n - 1`元素。 因此,仅在此子数组上调用快速排序。
W
wizardforcel 已提交
354 355
    但是,快速排序算法对于分散的数据透视表具有更好的性能。

W
wizardforcel 已提交
356
*   **最佳情况复杂度【大 Ω】**`O(n*log n)`
W
wizardforcel 已提交
357
    当枢轴元素始终是中间元素或靠近中间元素时,会发生这种情况。
W
wizardforcel 已提交
358
*   **平均病例复杂度【大 θ】**`O(n*log n)`
W
wizardforcel 已提交
359 360 361 362
    当不出现上述条件时发生。

**空间复杂度**

W
wizardforcel 已提交
363
快速排序的空间复杂度为`O(log n)`
W
wizardforcel 已提交
364 365 366

* * *

W
wizardforcel 已提交
367
## 快速排序应用
W
wizardforcel 已提交
368

W
wizardforcel 已提交
369
快速排序在以下情况下实现
W
wizardforcel 已提交
370 371 372

*   编程语言适合递归
*   时间复杂度很重要
W
wizardforcel 已提交
373
*   空间复杂度很重要