快速排序的思想是二分, 理想情况是每次二分都能把数据序列平均的二分, 这样 递归层级就是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的元素放在右边, 那对于这种规则, 都可以用一个相反的方法, 人为制造出数据, 使这个排序方法栈溢出.


xxxxxsssss
1 声望0 粉丝