算法
快速排序由两部分组成,第一部分是根据所选元素x分割,将待排序部分分成三块,#1:比x小的部分,#2:等于x的部分,#3:大于x的部分。第二部分是递归,将#1和#2重复执行第一部分的操作。
并且元素x的选取位置不同,一定程度上会影响算法的时间复杂度,这里使用随机方法选择一个位置,改善时间复杂度。
note:分割这一步操作可以在时间复杂度O(N)内完成。使用两个指针left和right,分别指向待排序列首元素前一个位置和尾元素后一个位置,使用另一个指针i指向待排序列首元素,比较当前指针的值是否小于x,是则交换left+1和i的元素,这样#1部分扩充一个元素,i++;如果等于x,则i++;如果大于x,则交换right-1和i的元素,这样#3部分扩充一个元素。当i和right重合时,循环结束。
该算法维持了一个不变量,每次进入循环前,left以及左边部分是比x小的部分,right以及右边部分是大于x的部分,而left+1到righ-1t则是处于一种混沌的状态,大于小于等于都有可能,初始化时i指向了left+1位置;循环体中,调整i位置元素,使得其在合适的部分,从而使得循环不变量保持。当循环结束时,i==right,这时所有部分都处理完成。至此说明了算法的正确性。
实现
#include <iostream>
#include <vector>
using namespace std;
ostream& operator << (ostream& os , vector<int> v)
{
for (auto& i : v)
cout << i << " ";
cout << endl;
return os;
}
pair<int,int> split (vector<int>& v , int val , int _left , int _right)
{
int left = _left -1, right = _right+1,i = _left;
while (i < right)
{
if (v[i] < val)
swap(v[i++], v[++left]);
else if (v[i] == val) ++i;
else
{
swap(v[i], v[--right ]);
}
}
//cout << left << " " << right << endl;
return make_pair(left,right);
}
void quicksort(vector<int>& v,int left , int right)
{
if (left < right)
{
int pivot = v[left + rand() % (right - left + 1)];
pair<int, int> p = split(v, pivot,left,right);
quicksort(v, left, p.first);
quicksort(v, p.second, right);
}
}
int main() {
vector<int> a = { 50,62,75,4,152,2,7,56,7,2,2,7,-5,7,96,5 };
cout << "排序前:" << a;
quicksort(a, 0, a.size() - 1);
cout << "排序后:" << a;
}