快速排序:(小->大),首先在序列中找出一个数作为基准数,一般第一次会选择序列的首元素,再选择左右两个探针,一般第一次会选择序列的首尾下标作为左右探针,从两端开始探测,起始探测方向随意,但一定得是基准数的对面。为什么呢?(比如,序列(6,1,2,7,9)基准数选则首下标,则探测方向应从右侧开始,这样才能保证左右探针在相遇的时候,右边的都是大于基准数的,因为如果从左测开始探测的话,碍于(左探针<右探针)这个条件,有可能导致右探针没有找到小于基准数时就停了下来,继续的话,可能导致错误的结果。)按照正确的探测规则探测的话,当左右探针相遇的时候,相遇点的左侧都小于当前基准数,右侧都大于当前基准数,然后将相遇点与基准数交换,实现当前基准数归位,反复下去。
快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。
代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
static std::vector<int> vec;
int Partition(int left,int right)
{
int temp = vec[left];
int lv = left;
int rv = right;
while (lv!=rv)
{
while (vec[rv] >= temp && lv < rv)
rv--;
while (vec[lv] <= temp && lv < rv)
lv++;
if (lv < rv)
{
int t = vec[lv];
vec[lv] = vec[rv];
vec[rv] = t;
}
}
//将基数归位
vec[left] = vec[lv];
vec[lv] = temp;
return lv;
}
//快速排序(小->大) 递归实现
void QuickSort(int left, int right)
{
if (left<right)
{
int pivot = Partition(left,right);
//继续递归处理
QuickSort(left, pivot - 1); //处理左边
QuickSort(pivot + 1, right); //处理右边
}
}
//快速排序,非递归实现
//用栈实现,用栈保存每一个待排序子串的首尾元素下标
//下一次while循环时取出这个范围,进行划分操作
void QuickSort2(int left,int right)
{
std::stack<int> sta;
int mid;
if (left<right)
{
mid = Partition(left,right);
if (left<mid-1)
{
sta.push(left);
sta.push(mid-1);
}
if (right>mid+1)
{
sta.push(mid+1);
sta.push(right);
}
}
while (!sta.empty())
{
int q = sta.top();
sta.pop();
int p = sta.top();
sta.pop();
mid = Partition(p,q);
if (p < mid - 1)
{
sta.push(p);
sta.push(mid-1);
}
if (q > mid + 1)
{
sta.push(mid+1);
sta.push(q);
}
}
}
//函数指针作为形参
void Test(void(*Quick)(int,int ))
{
Quick(0,9); //递归
//QuickSort2(0,9); //非递归
}
int main()
{
int n = 0;
std::cin >> n;
::fill_n(::back_inserter(vec),n,0);
for (int i=0;i<n;i++)
{
std::cin >> vec[i];
}
//auto * qS = &QuickSort;
//qS(0,n-1);
Test(&QuickSort);
for (int i=0;i<n;i++)
{
std::cout << vec[i] << std::endl;
}
::getchar(); ::getchar();
return 0;
}