看了这个你就会快排了!

看了这个你就会快速排序了!

快速排序:(C++版)

完整代码在后文!!!

挖坑法:(递归)

思想:
1、先设定一个基准数,一般取数组的第一个数做为基准数。
2、设置两个变量,left和right,让left指向数组第一个数,right指向数组的最后一个数。即left = 0;right = n - 1;
3、right一直向前走,直到找到一个比基准数小的数,将right目前指向的数赋值给left目前指向的数。
4、然后left一直朝后走,直到找到一个比基准数大的数,然后将left目前指向的数赋值给right目前指向的数。
5、重复3、4步骤,当left和right相遇了,就可以将基准数放入left和right指向的坑位了。

我这里做的是从小到大的排序,所以left将比自己大的数王后放,right将比自己小的数往前放,如果是从大到小,则相反。

思想读起来太繁琐,直接上图!
在这里插入图片描述
在这里插入图片描述

如上图,left对应的是数组中的4,right对应的是数组中的5,将4做为基准数存放在tmp中。
第一步:right前移了一位,发现了比基准数小的数3,所以将3放在了left的位置,即基准数的位置,自己的位置形成一个坑位。
第二步:left后移两位,发现了比基准数大的数字7,所以将7放在了right的位置,填了上一步的坑,自己形成了一个坑。
第三步:right前移一位,发现了比基准数小的数字0,将0放在left位置,填了上一步的坑,自己变成了一个坑。
第四步:left后移一位,发现了比基准数大的数字6,将6放在right位置,填了right的坑,自己形成一个坑。
第五步:right左移两位才发现了比自己小的数字2,将2放在left位置。
第六步:left后移一位,发现比自己小的9,将9放在right位置。
第七步:left和right经过千辛万苦终于如愿以偿的见面了,所以第一次快排也随之结束了。

随着第一步快排的结束,可以发现基准数走到了中间位置,左边都是比基准数小的数字,右边都是比基准数大的数字。但这写数字还不是完全有序的。
哪么我们该怎么办呢?
从当前left和right的位置开始,我们将这些数字分为左右两边,再次调用上面步骤所实现的函数。反复调用,直到他们完全有序。
递归法完整代码:

#include<iostream>
#include<vector>

using namespace std;

vector<int> partation(vector<int>& arr,int l,int r)
{
	int less = l - 1;
	int more = r;
	while (l < more)
	{
		if (arr[l] < arr[r])
		{
			swap(arr[++less], arr[l++]);
		}
		else if (arr[l] > arr[r])
		{
			swap(arr[--more], arr[l]);
		}
		else
		{
			l++;
		}
	}
	swap(arr[more], arr[r]);
	return vector<int> {less + 1, more};
}

void QuickPass(vector<int>& arr, int left, int right)
{
	if (left < right)
	{
		swap(arr[left + (int)(rand() % (right - left + 1))], arr[right]);
		vector<int> pos = partation(arr, left, right);
		QuickPass(arr, left, pos[0] - 1);
		QuickPass(arr, pos[1] + 1, right);
	}
}

void QuickSort(vector<int>& arr, int n)
{
	if (arr.empty() || arr.size() < 2) return;

	QuickPass(arr, 0, n - 1);
}

int main()
{
	vector<int> arr = { 56,123,89,23,56,34,10,56,45,78,56 };
	int n = arr.size() - 1;
	for (int i = 0; i < n; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;

	QuickSort(arr, n);
	for (int i = 0; i < n; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;

	return 0;
}

快排非递归法:
非递归法我是用队列实现的,先将left和right依次放入队列中,left指向数组的第一个元素,下标为0,right指向数组的最后一个元素,下标为9。将每一次快排完之后,所有部分的数组的首下标和尾下标依次放入队列中。例如,第一次执行完之后左半边的下标为0和3,右半边的下标为5和9。每一部分下标出队列之后调用Parition,循环往复。
在这里插入图片描述
非递归代码:

#include<iostream>
#include<assert.h>
using namespace std;

//第一次快排
int Parition(int* ar,int left,int rigth)
{
	assert(ar != NULL);
	int tmp = ar[left];
	while(left < right)
	{
		while(left < right && ar[right] > tmp) right--;
		ar[left] = ar[right];
		
		while(left < right && ar[left] <= tmp) left--;
		ar[right] = ar[left];
	}
	ar[left] = tmp;
	return left;
}
//非递归
void NiceQuickPass(int *ar,int left,int right)
{
	std::queue<int> qu;
	qu.push(left);
	qu.push(right);
	while(!qu.empty())
	{
		left = qu.front();
		qu.pop();
		right = qu.front();
		qu.pop();
		int pos = Parintion(ar,left,right);
		
		if(left < pos -1)
		{
			qu.push(left);
			qu.push(pos - 1);
		}
		if(right > pos +1)
		{
			qu.push(pos + 1);
			qu.push(right);
		}
	}
}
void QuickSort(int *ar,int n)
{
	NiceQuickPass(ar,0,n-1);
}

int main()
{
	int ar[] = { 56,123,89,23,56,34,10,56,45,78,56 };
	int n = sizeof(ar) / sizeof(ar[0]);
	for (auto& x : ar)
	{
		cout << x << " ";
	}
	cout << endl;
	QuickSort(ar, n);
	for (auto& x : ar) {
		cout << x << " ";
	}
	cout << endl;

	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值