improved partition in quick sort

来源:互联网 发布:规划算法 pdf 编辑:程序博客网 时间:2024/06/01 22:07

original solution

参考算法导论实现的分组算法

int partition(vector<int>& nums, int p, int r) {    int x = nums[r];    int s = p - 1;  // the last smaller    for (int k = p; k < r; ++k) {        if (nums[k] <= x){            ++s;            swap(nums[s], nums[k]);        }    }    ++s;    swap(nums[r], nums[s]);    return s;}

输入
5 2 4 7 5 1 5 9 5 10 5
分组结果
7
5 2 4 5 1 5 5 5 7 10 9

输入
5 5 5 5 5
分组结果
4
5 5 5 5 5

可以看到,第二组输入的分组结果很不均衡,这在会影响快排算法的性能。


improved solution1

在做分组的时候,同时区分大于和小于pivot值的元素。小于pivot值的元素就往左边放,大于pivot值的元素就往右边放,等于pivot的元素放中间。partition结束之后,返回等于pivot值的元素的中间位置。

int partition(vector<int>& nums, int p, int r) {    int x = nums[r];    int s = p - 1;  // the last smaller    int cnt = 0;  // count # number equals to pivot    for (int k = p; k < r; ++k) {        if (nums[k] < x){            swap(nums[s+cnt+1], nums[k]);            swap(nums[s+cnt+1], nums[s+1]);            ++s;        } else if (nums[k] == x) {            swap(nums[s+cnt+1], nums[k]);            swap(nums[s+cnt+1], nums[s+1]);            ++cnt;        }    }    swap(nums[r], nums[s+cnt+1]);    return s+1+cnt/2;}

输入
5 2 4 7 5 1 5 9 5 10 5
分组结果
5
2 4 1 5 5 5 5 5 7 10 9

输入
5 5 5 5 5
分组结果
2
5 5 5 5 5

改进的代码的均衡性就好多了。


improved solution2

把较小的数往左边放,较大的数放右边。

// partition array, return the index of pivotint partition(vector<int>& nums, int p, int r) {    int x = nums[r];    int s = p - 1;  // the last smaller    int l = r;  // the first larger    for (int k = p; k < l; ++k) {        if (nums[k] > x) {            --l;            swap(nums[l], nums[k]);            --k;  // nums[k] is new, should do again        } else if (nums[k] < x){            ++s;            swap(nums[s], nums[k]);        }    }    swap(nums[r], nums[l]);    return (s+1+l)/2;}

测试输入
5 2 4 7 5 1 5 9 5 10 5
分组结果
5
2 4 1 5 5 5 5 5 10 7 9

测试输入
5 5 5 5 5
分组结果
2
5 5 5 5 5