快速排序:虽然名字中有快速二字,但其在最糟糕的情况下时间复杂度为O(N^2),在平均情况下,快速排序的时间复杂度为O(nlogn).
快速排序也是一种归并算法,我们在待排序序列中选择一个对象作为基准,将小于它和大于它的分别分成两个子序列,然后分别对着两个子序列对排序。
示例:
3 2 0 5 -1 9 1 4
第一次取sign = 3,左指针指向3,右指针从最后一位开始循环,
4 > 3,右指针左移一位,为1,1 < 3, 将1放到3的位置,
左指针右移一位,为2, 2 < 3,继续右移,0 < 3,继续右移,
5 > 3, 将5放到1的位置,右指针继续左移,9 > 3,
继续右移, -1 < 3, 将-1放到5的位置,左指针右移,
这时左右指针重逢,将sign放在重逢的位置,继续下一次递归
第一次递归后,源数据分成了两组
1 2 0 -1 | 3 9 5 4
继续在这两组上做递归
C++实现(递归):
#include <iostream>
using namespace std;
template<typename T>
void quick_sort(T arr[], int left, int right) {
if (right <= left) return;
T var = arr[left];
int _left = left;
int _right = right;
while (_left != _right) {
while ((_right > _left) && (arr[_right] >= var)) {
_right--;
}
arr[_left] = arr[_right];
while ((_left < _right) && (arr[_left] <= var)) {
_left++;
}
arr[_right] = arr[_left];
}
arr[_left] = var;
quick_sort(arr, left, _left - 1);
quick_sort(arr, _left + 1, right);
}
template<typename T>
void print(T arr, int len) {
for (int i = 0; i < len; i++) {
if (i + 1 < len) {
std::cout << arr[i] << ",";
} else {
std::cout << arr[i] << std::endl;
}
}
}
int main() {
double arr[] = {1.3, 4.35, 0, 12.34, 33.5, -1, 3.4, 5.56, 8.67};
std::cout << "before sort:" << std::endl;
int len = sizeof(arr) / sizeof(arr[0]);
print(arr, len);
quick_sort(arr, 0, len - 1);
std::cout << "after sort:" << std::endl;
print(arr, len);
}
Python实现(递归):
1 def quick_sort(lists, left, right):
2 if (right <= left):
3 return
4 val = lists[left]
5 _left = left
6 _right = right
7 while (_left < _right):
8 while ((_right > _left) and (lists[_right] > val)):
9 _right -= 1
10 lists[_left] = lists[_right]
11 while ((_left < _right) and (lists[_left] < val)):
12 _left += 1
13 lists[_right] = lists[_left]
14 lists[_right] = val
15 quick_sort(lists, left, _left - 1)
16 quick_sort(lists, _left + 1, right)
17
18 lists = [3, -1, 4, 0, 34, 35, 2, 100, 56, 7, 8]
19 lens = len(lists)
20 print("before sort:", lists)
21 quick_sort(lists, 0, lens - 1)
22 print("after sort:", lists)
C++实现(非递归):
其实递归转非递归就是用栈保存每一个代排序的集合的首尾元素,下次去除首尾进行partition排序,直到栈为空。
1 #include <iostream> 2 #include <stack> 3 using namespace std; 4 5 template<typename T> 6 int partition(T arr[], int left, int right) { 7 T var = arr[left]; 8 int _left = left; 9 int _right = right; 10 while (_left != _right) { 11 while ((_right > _left) && (arr[_right] >= var)) { 12 _right--; 13 } 14 arr[_left] = arr[_right]; 15 while ((_left < _right) && (arr[_left] <= var)) { 16 _left++; 17 } 18 arr[_right] = arr[_left]; 19 } 20 arr[_left] = var; 21 return _left; 22 } 23 24 template<typename T> 25 void quick_sort(T arr[], int left, int right) { 26 if (right <= left) return; 27 int mid = partition(arr, left, right); 28 std::stack<T> data_stack; 29 data_stack.push(left); 30 data_stack.push(mid - 1); 31 data_stack.push(mid + 1); 32 data_stack.push(right); 33 while (!data_stack.empty()) { 34 int high = data_stack.top(); 35 data_stack.pop(); 36 int low = data_stack.top(); 37 data_stack.pop(); 38 mid = partition(arr, low, high); 39 if (mid - 1 > low) { 40 data_stack.push(low); 41 data_stack.push(mid - 1); 42 } 43 if (mid + 1< high) { 44 data_stack.push(mid + 1); 45 data_stack.push(high); 46 } 47 } 48 } 49 50 template<typename T> 51 void print(T arr, int len) { 52 for (int i = 0; i < len; i++) { 53 std::cout << arr[i] << std::endl; 54 } 55 } 56 57 int main() { 58 double arr[] = {1.3, 4.35, 0, 12.34, 33.5, -1, 3.4, 5.56, 8.67}; 59 std::cout << "before sort:" << std::endl; 60 int len = sizeof(arr) / sizeof(arr[0]); 61 print(arr, len); 62 quick_sort(arr, 0, len - 1); 63 std::cout << "after sort:" << std::endl; 64 print(arr, len); 65 }