快排面面观(1)-递归和非递归

快排的思想

(1)递归的版本
快排体现的就是分治的思想,传统的快排思想首先将原数组分成两个部分,再通过递归分别对两个子数组进行快排。定义两个变量left,right指向首尾,递归结束的条件就是left > right。完整的代码如下,代码的重点是Position函数,即找到分隔数组的位置。注意函数中的边界判断。判断完位置pos之后,利用分治和递归的思想,将数组分成两个部分进行递归。

#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <assert.h>
using namespace std;
void Print(int arr[], int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}
int Position(int arr[], int left, int right)
{
	assert(arr != NULL);
	int tmp = arr[left];
	while (left < right)
	{
		while (left < right && arr[right] > tmp)
		{
			right--;
		}
		if (left < right)
		{
			arr[left] = arr[right];
		}
		while (left < right && arr[left] <= tmp)
		{
			left++;
		}
		if (left < right)
		{
			arr[right] = arr[left];
		}
	}
	arr[left] = tmp;
	return left;
}
void QuickSort(int arr[], int left, int right)
{
	if (left < right)
	{
		int pos = Position(arr, left, right);
		QuickSort(arr, left, pos - 1);
		QuickSort(arr, pos + 1, right);
	}
}
void Quick(int arr[], int n)
{
	assert(arr != NULL);
	QuickSort(arr, 0, n - 1);
}
int main()
{
	int arr[] = { 4,3,2,5,6,1,9,7 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Print(arr, len);
	Quick(arr, len);
	Print(arr, len);
	return 0;
}

(2)非递归版本
非递归版本就是在递归的版本的改进。可以使用栈和队列来实现Position函数分隔位置的保存。首先将首尾位置保存在栈或者队列中,用的时候从中取值,并将分隔后的首尾节点在存放在栈或者队列中。代码部分只写排序的核心部分,用来替换原来的Quick函数。

void QuickStack(int arr[], int n)
{
	assert(arr != NULL);
	stack<int> st;
	st.push(n - 1);
	st.push(0);
	while (!st.empty())
	{
		int left = st.top();
		st.pop();
		int right = st.top();
		st.pop();
		int pos = Position(arr, left, right);
		if (left < pos - 1)
		{
			st.push(pos - 1);
			st.push(left);
		}
		if (pos + 1 < right)
		{
			st.push(right);
			st.push(pos + 1);
		}
	}
}

快排的特点

最优的时间复杂度是O(nlogn),最差的空间O(n^2),额外空间是O(nlogn)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值