快速排序

快速排序:(小->大),首先在序列中找出一个数作为基准数,一般第一次会选择序列的首元素,再选择左右两个探针,一般第一次会选择序列的首尾下标作为左右探针,从两端开始探测,起始探测方向随意,但一定得是基准数的对面。为什么呢?(比如,序列(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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值