Quicksort


original website:http://www.algolist.net/Algorithms/Sorting/Quicksort

Quicksort is a fast sorting algorithm, which is used not only for educational purposes, but widely applied in practice. On the average, it has O(n log n) complexity, making quicksort suitable for sorting big data volumes. The idea of the algorithm is quite simple and once you realize it, you can write quicksort as fast as bubble sort.

Algorithm

The divide-and-conquer strategy is used in quicksort. Below the recursion step is described:
  1. Choose a pivot value. We take the value of the middle element as pivot value, but it can be any value, which is in range of sorted values, even if it doesn't present in the array.
  2. Partition. Rearrange elements in such a way, that all elements which are lesser than the pivot go to the left part of the array and all elements greater than the pivot, go to the right part of the array. Values equal to the pivot can stay in any part of the array. Notice, that array may be divided in non-equal parts.
  3. Sort both parts. Apply quicksort algorithm recursively to the left and the right parts.

Partition algorithm in detail

There are two indices i and j and at the very beginning of the partition algorithm i points to the first element in the array and j points to the last one. Then algorithm moves i forward, until an element with value greater or equal to the pivot is found. Index j is moved backward, until an element with value lesser or equal to the pivot is found. If i ≤ j then they are swapped and i steps to the next position (i + 1), j steps to the previous one (j - 1). Algorithm stops, when i becomes greater than j.

After partition, all values before i-th element are less or equal than the pivot and all values after j-th element are greater or equal to the pivot.

Example. Sort {1, 12, 5, 26, 7, 14, 3, 7, 2} using quicksort.

Quicksort example

Notice, that we show here only the first recursion step, in order not to make example too long. But, in fact, {1, 2, 5, 7, 3} and {14, 7, 26, 12} are sorted then recursively.

Why does it work?

On the partition step algorithm divides the array into two parts and every element  a from the left part is less or equal than every element  b from the right part. Also  a and  bsatisfy  a ≤ pivot ≤ b inequality. After completion of the recursion calls both of the parts become sorted and, taking into account arguments stated above,  the whole array is sorted.

Complexity analysis

On the average quicksort has O(n log n) complexity, but strong proof of this fact is not trivial and not presented here. Still, you can find the proof in [1]. In worst case, quicksort runs O(n2) time, but on the most "practical" data it works just fine and outperforms other O(n log n) sorting algorithms.

Code snippets

Partition algorithm is important per se, therefore it may be carried out as a separate function. The code for C++ contains solid function for quicksort, but Java code contains two separate functions for partition and sort, accordingly.

Java

int partition(int arr[], int left, int right)

{

      int i = left, j = right;

      int tmp;

      int pivot = arr[(left + right) / 2];

     

      while (i <= j) {

            while (arr[i] < pivot)

                  i++;

            while (arr[j] > pivot)

                  j--;

            if (i <= j) {

                  tmp = arr[i];

                  arr[i] = arr[j];

                  arr[j] = tmp;

                  i++;

                  j--;

            }

      };

     

      return i;

}

 

void quickSort(int arr[], int left, int right) {

      int index = partition(arr, left, right);

      if (left < index - 1)

            quickSort(arr, left, index - 1);

      if (index < right)

            quickSort(arr, index, right);

}

C++

void quickSort(int arr[], int leftint right) {

      int i = leftj = right;

      int tmp;

      int pivot = arr[(left + right) / 2];

 

      /* partition */

      while (i <= j) {

            while (arr[i] < pivot)

                  i++;

            while (arr[j] > pivot)

                  j--;

            if (i <= j) {

                  tmp = arr[i];

                  arr[i] = arr[j];

                  arr[j] = tmp;

                  i++;

                  j--;

            }

      };

 

      /* recursion */

      if (left < j)

            quickSort(arrleftj);

      if (i < right)

            quickSort(arriright);

}

Full quicksort package

Full quicksort package includes:
  • Ready-to-print PDF version of quicksort tutorial.
  • Full, thoroughly commented quicksort source code (Java & C++).
  • Generic quicksort source code in Java (Advanced).
  • Generic quicksort source code using templates in C++ (Advanced).
Download link:  full quicksort package.

Recommended books

  1. Cormen, Leiserson, Rivest. Introduction to algorithms. (Theory)
  2. Aho, Ullman, Hopcroft. Data Structures and Algorithms. (Theory)
  3. Robert Lafore. Data Structures and Algorithms in Java. (Practice)
  4. Mark Allen Weiss. Data Structures and Problem Solving Using C++. (Practice)

Visualizers

  1. Quicksort Animation (with source code line by line visualization)
  2. Quicksort in Java Applets Centre
  3. Animated Sorting Algorithms: Quicksort

Eleven responses to "Quicksort tutorial"

  1. Mark on Oct 22, 2009 said:

    wow this is the BEST explanation i have found yet for quick sort. Thanks!

  2. chathikagunaratne on June 19, 2009 said:

    very clear and informative. Thanks a lot this was very helpful.

  3. satinder on April 20, 2009 said:

    very good algo for quick sort.............. this helps the student so much

  4. Lords_Of_waR on Mar 23, 2009 said:

    thanks for the tip..it really helps..simple and brief!!^.^..do you have a example flowchart of it?

    No, we haven't at the moment. Thought, flowcharts for algorithms is in our to-do-list.

  5. Samin on Mar 16, 2009 said:

    thank you , your codes are really simple to be understood and used

  6. ann on Mar 5, 2009 said:

    one of the best explanation of quick sort on net. great work. keep it coming!!!!

  7. Dipto on Feb 27, 2009 said:

    Thanks for the great program.
    it is shorter and simpler than any other quicksort that i have come across.

  8. Bubli Sagar on Feb 12, 2009 said:

    it is really simple and much better than any of the examples i came across..

  9. Rand on Jan 6, 2009 said:

    Thank u i am really happy because the code is simple and can be understood

  10. Jon Archer on Jan 3, 2009 said:

    Really showed exactly what I wanted to know. Now if you could also include something on tail-recursion elimination, it would indeed be very helpful.

    We are going to develop "Quick sort in-depth" article, which will examine advanced quick sort problems, such as choosing the pivot value, quick sort optimization on small data volumes, etc.

  11. Hassan on Nov 12, 2008 said:

    Thx You :)

### C++ 中 QuickSort 排序算法的实现与用法 #### 1. 快速排序算法简介 快速排序是一种分治策略的高效排序算法,它通过选取一个基准值(pivot),将数据划分为两部分:一部分小于等于基准值,另一部分大于基准值。随后递归地对这两部分分别进行排序[^2]。 #### 2. 快速排序的核心函数 `partition` `partition` 函数用于重新排列数组元素并返回基准值的位置。以下是其实现逻辑: - 基准值通常选为子数组的最后一个元素。 - 使用两个指针变量 `i` 和 `j` 遍历子数组: - 当前元素小于基准值时,交换该元素到左侧区域。 - 否则继续遍历直到完成整个子数组。 - 最终将基准值放置在其最终位置上,并返回此索引。 ```cpp int partition(int arr[], int low, int high) { int pivot = arr[high]; int i = low - 1; for (int j = low; j <= high - 1; ++j) { if (arr[j] < pivot) { ++i; swap(arr[i], arr[j]); } } swap(arr[i + 1], arr[high]); return i + 1; } ``` 上述代码展示了如何划分数组并找到基准值的正确位置[^3]。 #### 3. 主要递归函数 `quickSort` `quickSort` 是核心递归函数,负责调用 `partition` 来分割数组并对左右两侧分别执行相同操作。 ```cpp void quickSort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } ``` 这段代码定义了一个递归过程,其中每次调用都会缩小待处理范围直至完全有序。 #### 4. 完整示例程序 下面提供完整的 C++ 程序演示如何使用自定义的 `quickSort` 方法对数组进行升序排序。 ```cpp #include <iostream> using namespace std; // Partition function as described earlier. int partition(int arr[], int low, int high); // Recursive quick sort implementation. void quickSort(int arr[], int low, int high); // Utility to print array elements. void printArray(int arr[], int size) { for (int i = 0; i < size; i++) cout << arr[i] << " "; cout << endl; } int main() { int data[] = {8, 7, 6, 1, 0, 9, 2}; int n = sizeof(data)/sizeof(data[0]); cout << "Unsorted Array:\n"; printArray(data, n); quickSort(data, 0, n - 1); cout << "\nSorted Array in Ascending Order:\n"; printArray(data, n); return 0; } // Implementation of the functions defined above. int partition(int arr[], int low, int high){ int pivot = arr[high]; int i = low - 1; for (int j = low; j <= high - 1; ++j){ if (arr[j] < pivot){ ++i; swap(arr[i], arr[j]); } } swap(arr[i+1], arr[high]); return i + 1; } void quickSort(int arr[], int low, int high){ if(low < high){ int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } ``` 以上是一个典型的例子,说明了如何利用手动编写的 `quickSort` 对一组随机数列实施排序。 #### 5. STL 提供的标准模板库版本 除了自己编写外,在实际开发过程中更推荐直接采用 `<algorithm>` 头文件里的 `std::sort()` 或者稳定版 `std::stable_sort()` 进行排序工作,它们内部采用了优化后的混合排序方法(通常是 IntroSort)。这些内置功能不仅性能优越而且经过严格测试更加可靠[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值