快速排序的思想是二分, 理想情况是每次二分都能把数据序列平均的二分, 这样 递归层级就是logN. 最坏的情况是,每次二分 都分成了0 和 n, 这种情况会无限递归,最后栈溢出. 或者每次都分成了 1 和 n-1, 这种情况会递归n次, 如果n比较大, 会导致栈溢出.
所以快速排序的二分的方法, 并不能简单的写.
比如下面这种快速排序方法能解决几乎所有数据序列, 但是如果人为制造一段数据, 是可以让它栈溢出的
#include <stdio.h>
#include <vector>
using namespace std;
static inline void swap(int *p, int *q)
{
int t = *p;
*p = *q;
*q = t;
}
void quick_sort1(int *A, int head, int end)
{
if(head >= end)
{
return;
}
int x = A[(head + end) / 2];
int left = head;
int right = end;
while(left <= right)
{
while(left < end)
{
if(A[left] >= x) // when >= -> break
{
break;
}
left++;
}
while(right > head)
{
if(A[right] <= x) // when <= -> break
{
break;
}
right--;
}
if(left <= right) // when <=, go on swap and ++ --, until left > right,
{
swap(&ar[left], &ar[right]);
left++;
right--;
}
}
quick_sort1(A, head, right);
quick_sort1(A, left, end);
}
int main()
{
vector <int> v = {2, 3};
int min = 1;
int n = 40000;
for(int i = 0; i < n; i++)
{
v.insert(v.begin(), min);
int middle_index= (0 + (v.size() - 1)) / 2;
int t = v[middle_index];
v[middle_index] = v[0];
v[0] = t;
min--;
}
n += 2;
int ar[n];
for(int i = 0; i < n; i++)
{
ar[i] = v[i];
}
quick_sort1(ar, 0, n - 1);
for(int i = 0; i < n; i++)
{
printf("%d \n", ar[i]);
}
return 0;
}
制造数据序列的方法如下(实际上 就是以上的二分方法的逆):
第一步: 随意构造一个数组ar{2,3}, 然后在数组头部添加一个"小于数组所有元素"的数1, 得到{1,2,3}, 然后将ar的第一个元素ar[0]和ar中间的元素ar[1]的值互换,得到 {2, 1, 3}
第二步: 在数组头部添加一个小于数组所有元素的值 0, 得到{0, 2, 1, 3}, 然后将ar的第一个元素ar[0]和ar中间的元素ar[1]的值互换,得到 {2, 0, 1, 3}
重复做第二步, 如果做40000次的话, 就会得到一个有40002个元素的数组, 这个数组会让前面的快速排序方法递归深度过大, 最后栈溢出.
所以快速排序的二分法, 如果只是指定一个数a, 用某种规则, 把<=a的元素放在左边, >=a的元素放在右边, 那对于这种规则, 都可以用一个相反的方法, 人为制造出数据, 使这个排序方法栈溢出.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。