首页 > 其他分享 >快速排序(动图详解)(C语言数据结构)

快速排序(动图详解)(C语言数据结构)

时间:2024-09-05 18:22:14浏览次数:7  
标签:begin end 递归 int mid C语言 key 动图 数据结构

快速排序:

        快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:

        任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
        快速排序有三个版本,将一一实现。

Hoare版本:

        直接上动图理解:

当前为一遍快排。

再分别以key左右两边进行相同的排序

直到key = right = left。

综上得用递归思想。

代码如下:

void QuickSort(int* a, int begin,int end)
{
	if (begin >= end)//递归返回条件
	{
		return;
	}
	int right = end;
	int left = begin;
	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[key], &a[begin]);
    k = begin;
	QuickSort(a,left,key-1);//key左边递归
	QuickSort(a,key+1,right);//key右边递归
}

递归展开图:

 优化代码:

        通过画递归展开图后,发现如果这个k的取值一直等于left,有缺点,递归的次数较多。

如果能改进就能让效率提高。

        改进思路:

        如果这个递归能像二叉树一样,总共只需要N*log(N)次,就只需要每次这个k取值去一个中间值,不需要去最大也不需要取最小。

        这样的改进方案,称之为三数取中。 

像刚刚,如果要递归的话一次需要递归9次,如果每次取中间的值当k,每次只需要递归3次 。

等左边递归结束式左边空间还是可以继续利用的。                 

 代码如下:

int GetMid(int* a, int begin, int end)
{
	int mid = (begin+end) / 2;
	if (a[mid] > a[end])
	{
		if (a[mid] < a[begin])
		{
			return mid;
		}
		else if (a[end] > a[begin])
		{
			return end;
		}
		else
			return begin;
	}
	else
	{
		if (a[mid] > a[begin])
		{
			return mid;
		}
		else if (a[end] < a[begin])
		{
			return end;
		}
		else
			return begin;
	}
}
void QuickSort(int* a, int begin,int end)
{
	if (begin >= end)//递归返回条件
	{
		return;
	}
	//三数取中
	int mid = GetMid(a, begin, end);
	swap(&a[mid], &a[begin]);
	int right = end;
	int left = begin;
	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[key], &a[begin]);
	key = begin;
	QuickSort(a,left,key-1);//key左边递归
	QuickSort(a,key+1,right);//key右边递归
}

挖坑法版本:

        

代码如下:

void QuickSort2(int* a, int begin, int end)
{
	if (begin >= end)//递归返回条件
	{
		return;
	}
	//三数取中
	int mid = GetMid(a, begin, end);
	swap(&a[mid], &a[begin]);
	int left = begin;
	int right = end;
	int key = a[left];
	int hole = left;//第一个为坑
	while (begin < end)
	{
		//找小
		while (begin < end && a[end] >= key)
		{
			end--;
		}
		//找到小的后将数据移到刚刚坑位,并将当前位置作为坑
		a[hole] = a[end];
		hole = end;
		//找大
		while (begin < end && a[begin] <= key)
		{
			begin++;
		}
		//找到大的后将数据移到刚刚坑位,并将当前位置作为坑
		a[hole] = a[begin];
		hole = begin;
	}
	a[hole] = key;
	QuickSort(a, left, hole - 1);//key左边递归
	QuickSort(a, hole + 1, right);//key右边递归
}

前后指针法:

cur找小,找到以后prev+1后交换cur和prev。

等cur == n-1之后,将a[key]和a[prev]交换,并且将key = prev。 

这个过程保证了prev和cur之间的值是大于key的。

代码如下:

void QuickSort3(int* a, int begin,int end)
{
	if (begin>=end)//递归返回条件
	{
		return;
	}
	//三数取中
	int mid = GetMid(a, begin, end);
	swap(&a[mid], &a[begin]);
	int prev = begin;
	int cur = prev + 1;
	int key = prev;
	while (cur<=end-begin)
	{
		if (a[cur] < a[key])
		{
			prev++;
			if (prev < cur)
			{
				swap(&a[prev],&a[cur]);
			}
		}
		cur++;
	}
	swap(&a[key], &a[prev]);
	key = prev;
	QuickSort(a, begin, key - 1);//key左边递归
	QuickSort(a, key + 1, end);//key右边递归
}

标签:begin,end,递归,int,mid,C语言,key,动图,数据结构
From: https://blog.csdn.net/m0_75235246/article/details/141825816

相关文章

  • 新手c语言讲解及题目分享(十七)--运算符与表达式专项练习
    本文主要讲解c语言的基础部分,运算符与表达式的学习,在这一部分中,往往有许多细节的东西需要去记住。当各种运算符一起用时,就会存在优先级的关系,本文末尾有各种运算符的优先级顺序表。参考书目和推荐学习书目:通过网盘分享的文件:C语言程序设计电子教材(1).pdf链接:https://pa......
  • 新手c语言讲解及题目分享(十六)--文件系统专项练习
    在我刚开始学习c语言的时候就跳过了这一章节,但在后面慢慢发现这一章节还是比较重要的,如果你报考了计算机二级c语言的话,你应该可以看到后面的三个大题有时会涉及到这章。所以说这章还是非常重要的。目录前言一.打开文件1.Fopen()函数返回值2.文件打开方式二.关闭文件......
  • 新手c语言讲解及题目分享(十五)--结构体专项练习
    目录前言一.结构体1.结构体一般形式:2.定义结构体变量:Ⅰ.先声明结构体类型,再定义变量:Ⅱ.在声明结构体类型的同时定义变量:Ⅲ.不包含结构体类型名,直接定义结构体类型变量:3.引用结构体变量:4.定义结构体数组:Ⅰ.先定义结构体类型,后定义结构体数组:Ⅱ.在定义结构体类型的同......
  • 【数据结构】排序算法系列——插入排序(附源码+图解)
    插入排序算法思想插入排序的算法思想其实很容易理解,它秉持着一个不变的循环:比较->交换->比较->交换…因为我们排序最终的目的是要得到递增或者递减的数据,那么在原有的数据中,我们可以将数据依次两两进行比较:如果是升序,那么就将较小的放在较大的前面如果是降序,那么就将较大......
  • 【时时三省】(C语言基础)指针进阶 例题
    山不在高,有仙则名。水不在深,有龙则灵。            ----CSDN时时三省字符数组例题: arr后面放了六个字符所以这个数组的元素个数就是6第一个arr因为他计算的是一整个数组的大小就是打印6第二个arr+0arr没有单独放在它的内部所以它计算的就......
  • 【时时三省】(C语言基础)指针进阶6
    山不在高,有仙则名。水不在深,有龙则灵。             ----CSDN时时三省例题1: sizeof(数组名)-数组名表示整个数组的-计算的是整个数组的大小&数组名-数组名表示整个数组,取出的是整个数组的地址除此之外,所有的数组名都是数组首元素的地址第一个a......
  • 【时时三省】c语言例题----华为机试题<截取字符串>
    山不在高,有仙则名。水不在深,有龙则灵。                                    ----CSDN时时三省1,题目HJ46截取字符串描述输入一个字符串和一个整数k,截取字符串的前k个字符并输出数据范......
  • Java-数据结构-链表-习题(三)(๑´ㅂ`๑)
    文本目录:​❄️一、习题一:  ▶ 思路: ▶ 代码:​❄️二、习题二: ▶ 思路: ▶ 代码:​❄️三、习题三: ▶ 思路: ▶ 代码:​❄️四、习题四:    ▶ 思路:   ▶ 代码:​❄️五、习题五: ▶ 思路:    ▶ 代码:  ​❄️六、习题六:   ......
  • 数据结构总结心得
    1.在数据结构数据的概念中,数据的最小单位是数据项2.数据结构中的存储结构分为顺序存储结构和链式存储结构  从逻辑上可分为线性结构和非线性结构3.带头结点的单链表head为空的条件是head->next=NULL4.在具有n各个元素的循环队列中,队满时具有n-1个元素5.栈的入栈操......
  • 基于C语言的堆排序算法
    一、堆排序概述        堆排序是一种基于二叉堆数据结构的高效排序算法。它具有稳定的时间复杂度为O(nlogn),适用于大规模数据的排序。堆排序具有原地排序的特点,即不需要额外的存储空间,几个指针变量使用O(1)空间,元素交换和堆化操作都是在原数组上进行的。然而,堆排序的......