【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)

2024-02-27 1072阅读

温馨提示:这篇文章已超过396天没有更新,请注意相关的内容是否还可用!

 🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343
🔥 系列专栏:《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm=1001.2014.3001.5482

【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)​​​​

目录

 交换排序

快速排序

 hoare版代码呈现

快排优化

三数取中法

 小区间优化

 挖坑法

 前后指针版本

非递归版本快排


前言

    💬 hello! 各位铁子们大家好哇。

             今日更新了快速排序的内容

    🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)

 交换排序

快速排序

快排的过程图如下: 

【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)

 hoare版代码呈现

void QuickSort(int* a, int begin,int end)
{
	if (begin >= end)
	{
		return;
	}
	int left = begin, right =end;
	int keyi = begin;
	while (left = a[keyi])
		{
			right--;
		}
		//左边找大
		while (left 
  • L遇R->R先走,找到小的停下来了,L找大,没有找到,遇到R停下来了,相遇位置是R,比key小。
  • 如果左边做key,R先走。

    如果右边做key,L先走。

    快排优化

    1. 三数取中法选key
    2. 递归到小的子区间时,可以考虑使用插入排序

    三数取中法

    快排对于有序的数据,效率不是很高。

    【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)

    如上图,我们前面的快排是固定选key的,也就是左边第一幅图,效率很低。理想情况下,每一次都二分,这样效率就能提高。这时就用到三数取中法。

    三数取中法指三个数里面取中间大小的数,然后将他与key交换位置,让这个中间大小的数作key。

    完整代码如下: 

    int GetMidi(int* a, int begin, int end)
    {
    	int midi = (begin + end) / 2;
    	//begin end midi三个数中选中位数
    	if (a[begin]  a[end])
    			return begin;
    		else
    			return end;
    	}
    	else
    	{
    		if (a[midi] > a[end])
    			return midi;
    		else if (a[begin] = end)
    		return;
    	int midi = GetMidi(a, begin, end);
    	Swap(&a[midi], &a[begin]);
    	int left = begin, right = end;
    	int keyi = begin;
    	while (left = a[keyi])
    		{
    			right--;
    		}
    		//左边找大
    		while (left  
     
     

     分析:挖坑法其实跟hoare版本比没啥提升,只不过更易理解,本质上没变。但不同的版本,单趟排序后的结果可能会不同。

     前后指针版本

    【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)

    分析:

    1. cur遇到比key大的值,cur++
    2. cur遇到比key小的值,++prev,交换prev和cur位置的值,++cur

    代码实现

    //前后指针法
    int PartSort3(int* a, int begin, int end)
    {
    	int midi = GetMidi(a, begin, end);
    	Swap(&a[midi], &a[begin]);
    	int keyi = begin;
    	int prev = begin;
    	int cur = prev + 1;
    	while (cur a = NULL;
    	pst->capacity = 0;
    	pst->top = 0;
    	//pst->top = -1;
    }
    void STDestroy(ST* pst)
    {
    	free(pst->a);
    	pst->a = NULL;
    	pst->capacity = pst->top = 0;
    }
    //栈顶插入删除
    void STPush(ST* pst, STDataType x)
    {
    	assert(pst);
    	if (pst->top == pst->capacity)
    	{
    		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
    		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
    		if (tmp == NULL)
    		{
    			perror("realloc fail");
    			return;
    		}
    		pst->a = tmp;
    		pst->capacity = newcapacity;
    	}
    	pst->a[pst->top] = x;
    	pst->top++;
    }
    void STPop(ST* pst)
    {
    	assert(pst);
    	assert(pst->top > 0);
    	pst->top--;
    }
    STDataType STTop(ST* pst)
    {
    	assert(pst);
    	assert(pst->top > 0);
    	return	pst->a[pst->top - 1];
    }
    bool STEmpty(ST* pst)
    {
    	assert(pst);
    	//if (pst->top == 0)
    	//{
    	//	return true;
    	//}
    	//else
    	//{
    	//	return	false;
    	//}
    	return pst->top == 0;
    }
    

     非递归代码实现:

    void QuickSortNonR(int* a, int begin, int end)
    {
    	ST s;
    	STInit(&s);
    	STPush(&s, end);
    	STPush(&s, begin);
    	while (!STEmpty(&s))
    	{
    		int left = STTop(&s);
    		STPop(&s);
    		int right = STTop(&s);
    		STPop(&s);
    		int keyi = PartSort3(a, left, right);
    		// [left,keyi-1] keyi [keyi+1,right]
    		
    		if (keyi+1  
    

    【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)

    分析:栈是后进先出,这里用栈是模拟递归的过程。先模拟递归左边,像二叉树递归那样,先入右边的数,再入左边,这样出的时候就先出左边的,然后就可以模拟先往左边递归了。

    VPS购买请点击我

    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]