您的位置:首页 > 产品设计 > UI/UE

improved partition in quick sort

2017-09-29 10:15 375 查看

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 pivot
int 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法