快速排序的实现及其优化以及非递归方法的实现

基本思想:

任取待排序元素中的某个序列为基准,以该元素值为基准,将序列分成两个子序列。左子序列的元素都小于基准值,右子序列的元素都大于基准值,然后左右序列重复上面的过程,直到所有元素都排列到相应的位置为止。

图解:

在这里插入图片描述

代码实现:

主题框架代码:

//快排,我们需要依次递归
void QuickSort(int*a, int begin,int end)
{
	if (begin > end)
		return;
	int key = PartSort(a, begin, end);// PartSort函数实现单次排序
	QuickSort(a, begin, key - 1);
	QuickSort(a, key + 1, end);
	
}

单次排序函数代码:

1. 方法一

//Swap函数功能为交换两个数

int PartSort(int* a, int begin, int end)
{
	int key = begin;
	while (begin < end)
	{
		while (begin<end&&a[end]>=a[key])
		{
			--end;

		}
		while (begin < end&&a[begin] <= a[key])
		{
			++begin;
		}
		Swap(&a[begin], &a[end]);
	}
	Swap(&a[begin], &a[key]);
	return begin;
}

2.方法二:坑位法

int PartSort(int* a, int begin, int end)
{
	int key = a[begin];
	while (begin<end)
	{
		while (begin < end&&a[end] >= key)
		{
			--end;
		}
		a[begin] = a[end];
		while (begin < end&&a[begin] <= key)
		{
			++begin;
		}
		a[end] = a[begin];
	}
	a[begin] = key;
	return begin;
}

3.方法三:前后指针

在这里插入图片描述

int  PartSort3(int *a, int begin, int end)
{
	int prev = begin - 1;
	int cur = begin;
	while (cur<end)
	{    //以end处元素为key
		if (a[cur] < a[end])
		{
			++prev;
			Swap(&a[prev], &a[cur]);
			++cur;
		}
		else
			++cur;
	}
	++prev;
	Swap(&a[prev], &a[end]);
	return prev;

}

方法三的简洁代码:

int  PartSort3(int *a, int begin, int end)
{
	int prev = begin - 1;
	int cur = begin;
	while (cur<end)
	{
		if (a[cur] < a[end]&&++prev!=cur)
		{
	
			Swap(&a[prev], &a[cur]);
		}
			++cur;
	}
	
	Swap(&a[++prev], &a[end]);
	return prev;

}

通过刚才的图解的过程,我们发现待排序列为逆序的时候快排效率最低,时间复杂度为O(N^2),然而这种情况是由于我们选择的key值引起的。为了解决这种情况,我们可以采用三数取中的方法。

快排的优化

三数取中+小区间优化(当数据较少的时候,我们可以采用直接插入排序,效率较高)
三数取中代码实现:

int GetMinIndex(int* a, int begin, int end)
{
	int min = begin + ((end - begin) >> 1);
	if (a[begin] < a[min])
	{
		if (a[min] < a[end])
		{
			return min;
		}
		else
		{
			if (a[begin] < a[end])
				return end;
			else
				return begin;
		}
	}
	else//a[begin]>a[min]
	{
		if (a[min]>a[end])
			return min;
		else
		{
			if (a[begin] < a[end])
				return end;
			else
				return begin;
		}
	}
}

快排优化之后的代码实现

int  PartSort(int *a, int begin, int end)
{
	int min = GetMinIndex(a, begin, end);
	Swap(&a[min], &a[begin]);
	int key = a[begin];
	while (begin<end)
	{
		while (begin < end&&a[end] >= key)
		{
			--end;
		}
		a[begin] = a[end];
		while (begin < end&&a[begin] <= key)
		{
			++begin;
		}
		a[end] = a[begin];
	}
	//begin和end一定相遇于坑的位置
	a[begin] = key;
	return begin;

}
void QuickSort(int*a, int begin, int end)
{
	if (begin > end)
		return;
	if (end - begin + 1 <3)
	{
		Insertsort(a, end - begin + 1);
	}
	int key = PartSort3(a, begin, end);
	
	//[begin,key-1] key [key+1,end]

	QuickSort(a, begin, key - 1);
	QuickSort(a, key + 1, end);
}

非递归方法的代码实现:

非递归的实现借助于栈,将要排序的部分开始,结尾的下标入进栈,表示一段区域。
此处的栈接口代码的具体实现,可参考https://blog.csdn.net/weixin_43519514/article/details/104783366

void QuickSortNonr(int* a, int left, int right)
{
	assert(a);
	Stack s;
	StackInit(&s);
	StackPush(&s, left);
	StackPush(&s, right);
	while (!StackEmpty(&s))
	{
		int end = StackTop(&s);
		StackPop(&s);
		int begin = StackTop(&s);
		StackPop(&s);
		int key = PartSort(a, begin, end);
		
		if (begin < key - 1)
		{
			StackPush(&s, begin);
			StackPush(&s, key - 1);
		}
		if (key + 1 < end)
		{
			StackPush(&s, key+1);
			StackPush(&s, end);

		}
	}
	StackDestroy(&s);
}

用到的函数代码实现

void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

插入排序的实现可参考下面的网址
https://editor.csdn.net/md/?articleId=104770087

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值