对于快排的优化大概有这样几点:
1、减少 swap 次数 或者 直接不用 swap 操作,从整体上考虑每次 (i, j)元素的交换,让每次元素对的交换变成整体上挪位:
1 // 快排: 选定轴点 2 int parti(int lo, int hi) 3 { 4 swap(num[lo], num[lo + rand() % (hi - lo + 1)]); 5 int pivot = num[lo]; 6 while (lo < hi) 7 { 8 while ((lo < hi) && (pivot <= num[hi])) hi--; 9 num[lo] = num[hi]; 10 while ((lo < hi) && (num[lo] <= pivot)) lo++; 11 num[hi] = num[lo]; 12 } 13 num[lo] = pivot; 14 return lo; 15 }
表现在有下划线的代码上。
2、对于轴点的选取,要使左右集合的规模尽可能相当。
可以采取的方法有:随机选取法、三者取中法。
相比而言,对于最坏情况产生的概率,三者取中法又比随机选取法更能有效避免。
3、对于退化情形的考虑,即重复元素。
可以将上述选取轴点代码优化为:
1 // 快排: 选定轴点 2 int parti(int lo, int hi) 3 { 4 swap(num[lo], num[lo + rand() % (hi - lo + 1)]); 5 int pivot = num[lo]; 6 while (lo < hi) 7 { 8 while (lo < hi) 9 { 10 if (pivot < num[hi]) hi--; 11 else 12 { 13 num[lo++] = num[hi]; 14 break; 15 } 16 } 17 while (lo < hi) 18 { 19 if (num[lo] < pivot)) lo++; 20 else 21 { 22 num[hi--] = num[lo]; 23 break; 24 } 25 } 26 } 27 num[lo] = pivot; 28 return lo; 29 }
这样对于全部都是一样的元素,也能将轴点选取在中点位置而不会退化为最坏情况。代价是实际上的交换变多了。
From:我的知乎回答:http://www.zhihu.com/question/19841543/answer/46760856
时间: 2024-10-12 16:14:23