快速排序

快速排序


快速排序接近二分查找;时间效率为O(NlogN)-O(N^2);
快速排序的效率依赖于key值


快速排序算法:

快速排序是冒泡排序的一种改进,那可以先选定一个值,然后扫描待排序序列,把小于该值的记录和大于该值的记录分成两个单独的序列,然后分别对这两个序列进行上述操作。我们把选定的那个值称为枢纽值(key),如果枢纽值为序列中的最大值,那么一趟快速排序就变成了一趟冒泡排序。


快速排序使用分治法来把一个区间分为两个区间。

递归地把小于基准值元素key的子数列和大于基准值元素的子数列排序。

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代中,它至少会把一个元素摆到它最后的位置去。


函数简介:

函数PartionSort()版本一:递归;

函数PartionSort1()版本二:挖坑法;

函数PartionSort2()版本三:指针prev/cur;

快速排序的优化:

函数GetMidIndex()优化一:三树取中法(三平均分区),优化了函数函数PartionSort();

函数InsertSort()优化二:根据分区大小调整算法;当递归到接近有序时,用插入排序,提高效率;优化了函数QuickSort();

函数QuickSort_Non():处理桟溢出的问题,当有许多数时将左右区间下标压桟;用桟实现非递归。


函数QuickSort():实现递归,单趟排序,分为三部分;去调用函数PartionSort(),或者函数PartionSort1(),或者函数PartionSort2();


代码如下:


<span style="font-size:18px;">#include<iostream>
#include<assert.h>
using namespace std;
void Print(int* arr, int len)
{
	if (arr == NULL && len <= 0)
		return;

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

#include<stack>
//处理桟溢出的问题
//函数声明,实现在下方
int PartionSort(int* array, int left, int right);

void QuickSort_Non(int* arr,int left,int right)
{
	//assert(arr);

	stack<int> s;
	s.push(right);
	s.push(left);

	while (!s.empty())
	{
		int left = s.top();
		s.pop();
		int right = s.top();
		s.pop();

		int index = PartionSort(arr, left, right);

		if (index == -1)
			continue;

		if (left < index - 1)
		{
			s.push(index - 1);
			s.push(left);
		}

		if (index + 1 < right)
		{
			s.push(right);
			s.push(index + 1);
		}
	}
}

//快速排序的优化:三树取中法
int GetMidIndex(int* arr, int left, int right)
{
	assert(arr);

	int mid = left + (right - left) / 2;
	if (arr[left] < arr[mid])
	{
		if (arr[mid] < arr[right])
			return mid;
		else if (arr[left] < arr[right])
			return right;
		else
			return left;
	}
	else
	{
		if (arr[left] < arr[right])
			return left;
		else if (arr[mid] < arr[right])
			return right;
		else
			return mid;
	}
}

//指针prev/cur
int PartionSort2(int* arr, int left, int right)
{
	assert(arr);

	int prev = left - 1;
	int cur = left;
	int key = arr[right];
	while (cur < right)
	{
		//cur找小,停下来与++prev交换数据,否则cur一直走
		if (arr[cur] < key && ++prev != cur)
			swap(arr[prev], arr[cur]);
		++cur;
	}
	swap(arr[++prev], arr[right]);

	//返回正确位置上的值
	return prev;
}

//快速排序挖坑法
int PartionSort1(int* arr, int left, int right)
{
	assert(arr);

	int begin = left;
	int end = right;
	int key = arr[begin];
	while (begin < end)
	{
		while (begin < end && arr[end] >= key)
			--end;
		if (begin < end)
			arr[begin++] = arr[end];

		while (begin < end && arr[begin] <= key)
			++begin;
		if (begin < end)
			arr[end--] = arr[begin];
	}

	arr[begin] = key;
	return begin;
}

//函数声明,实现在下方
void InsertSort(int* arr, int len);
//key,递归
int PartionSort(int* arr, int left, int right)
{
	assert(arr);

	int begin = left;
	int end = right - 1;

	快速排序的优化1:三树取中法
	int midIndex = GetMidIndex(arr, left, right);
	if (midIndex != right)
		swap(arr[midIndex], arr[right]);


	//关键字key的值
	int key = arr[right];

	while (begin < end)
	{
		// 找大  =为了判断多个5的情况
		while (begin < end && arr[begin] <= key)
			++begin;

		// 找小   =为了判断多个5的情况
		while (begin < end && arr[end] >= key)
			--end;

		//小的数换到前面,大的数换在后面
		if (begin < end)
			swap(arr[begin], arr[end]);
	}

	//begin与end相遇,用key去交换相遇处的值

	//一般情况,If是解决俩个数时的情况,eg:3,4
	if (arr[begin] > key)
		swap(arr[begin], arr[right]);
	//逆序时的情况
	else
		begin = right;
	//返回正确位置上的值
	return begin;
}

//快速排序依赖于key的值,当key为最大或者最小时,快排的时间效率为O(N^2);
void QuickSort(int* arr,int left,int right)
{
	assert(arr);

	//递归返回条件
	if (left >= right)
		return;

	//优化快速排序2:当递归到接近有序时,用插入排序,提高效率
	if (right - left < 16)
	{
		InsertSort(arr + left, right - left + 1);
		return;
	}

	//1.递归
	int div = PartionSort(arr, left, right);
	//2.挖坑填坑法
	//int div = PartionSort1(arr, left, right);
	//3.快慢指针prev/cur
	//int div = PartionSort2(arr, left, right);

	//递归左区间
	if (left < div)
		QuickSort(arr, left, div - 1);

	//递归右区间
	if (div < right)
		QuickSort(arr, div + 1, right);
}

//直接插入排序
void InsertSort(int* arr,int len)
{
	if (arr == NULL && len <= 0)
		return;

	for (int i = 0; i < len - 1; ++i)
	{
		int end = i;
		int cur = arr[end + 1];				//待插入的数据
		
		// 挪动数据
		while (end >= 0 && arr[end] > cur)
		{
			arr[end + 1] = arr[end];
			--end;
		}
		arr[end + 1] = cur;
	}
}

//测试用例
//递归测试
void TestQuickSort()
{
	int array[] = { 2, 9, 5, 8, 3, 6, 1, 7, 4, 0 };
	QuickSort(array, 0, 9);
	Print(array, 10);

	int array1[] = { 3, 4 };
	QuickSort(array1, 0, 1);
	Print(array1, 2);

	int array2[] = { 5, 9, 5, 8, 3, 6, 1, 5, 4, 5 };
	QuickSort(array2, 0, 9);
	Print(array2, 10);

	int array3[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	QuickSort(array3, 0, 9);
	Print(array3, 10);

	int array4[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
	QuickSort(array4, 0, 9);
	Print(array4, 10);
}

//非递归测试
void TestQuickSort_Non()
{
	int array[] = { 2, 9, 5, 8, 3, 6, 1, 7, 4, 0 };
	QuickSort_Non(array, 0, 9);
	Print(array, 10);

	int array1[] = { 3, 4 };
	QuickSort_Non(array1, 0, 1);
	Print(array1, 2);

	int array2[] = { 5, 9, 5, 8, 3, 6, 1, 5, 4, 5 };
	QuickSort_Non(array2, 0, 9);
	Print(array2, 10);

	int array3[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	QuickSort_Non(array3, 0, 9);
	Print(array3, 10);

	int array4[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
	QuickSort_Non(array4, 0, 9);
	Print(array4, 10);
}
</span>







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值