iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >详解C语言快速排序三种方法的单趟实现
  • 495
分享到

详解C语言快速排序三种方法的单趟实现

2024-04-02 19:04:59 495人浏览 八月长安
摘要

目录交换排序的思想冒泡排序的思想快速排序的整体框架快速排序单趟实现逻辑1. hoare版本单趟实现(左右指针法)2.挖坑法单趟排序实现3.前后指针法交换排序的思想 基本思想:所谓交换

交换排序的思想

基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排 序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

冒泡排序的思想

冒泡排序比较简单,我们之前使用也很多,简单讲解,就是比较两个数,如果比他大就交换,没有他大就接着向后比,一直到数组结束,这是单趟排序,多趟就是控制好下标,进行循环即可。

冒泡代码实现

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
 
 
void BubbleSort(int* a, int n)
{
	assert(a);
 
	for (int j = 0; j < n - 1; ++j)
	{
		int exchange = 0;//定义变量,用于判断是否交换过
		for (int i = 1; i < n - j; ++i)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				exchange = 1;
			}
		}
 
		if (exchange == 0)//没有交换过表示有序,直接跳出
		{
			break;
		}
	}
}

冒泡排序的特性

1. 冒泡排序是一种非常容易理解的排序

2. 时间复杂度:O(N^2)

3. 空间复杂度:O(1)

4. 稳定性:稳定

快速排序的整体框架

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

// 假设按照升序对array数组中[left, right)区间中的元素进行排序
void QuickSort(int array[], int left, int right)
{
 if(right - left <= 1)
 return;
 
 // 按照基准值对array数组的 [left, right)区间中的元素进行划分
 int div = partion(array, left, right);
 
 // 划分成功后以div为边界形成了左右两部分 [left, div) 和 [div+1, right)
 // 递归排[left, div)
 QuickSort(array, left, div);
 
 // 递归排[div+1, right)
 QuickSort(array, div+1, right);
}

述为快速排序递归实现的主框架,发现与二叉树前序遍历规则非常像,同学们在写递归框架时可想想二叉 树前序遍历规则即可快速写出来,后序只需分析如何按照基准值来对区间中数据进行划分的方式即可。

简单理解:

我们先选出一个数,然后把所有数据分为三部分,第一部分是大于这个数的部分,第二个部分是这个数,第三个部分是大于这个数的。

然后,进行递归求解,对于小于的部分,选一个数,分为三部分。对于大于的部分,选一个数,分为三部分进行求解。

递归返回条件:首先是区间不存在返回,区间只有一个数返回。

快速排序单趟实现逻辑

1. hoare版本单趟实现(左右指针法)

首先我们先学习下最经典的左右指针法:

首先我们一般都会这两个疑问?(后续挖坑法和前后指针法同理)

1.为什么要选左边的数作为初识位置比较位置。

2.为什么要让右边先走?

我们之所以选取左边,只是因为方便,容易控制,你也可以选择右边,或者任意位置,都可以,只不过在代码逻辑上稍微复杂点,不容易控制。

我们让右边先走,是因为最后我们要把 key位置的数据移动到相遇位置,也就是key位置数据的正确位置,所以我们应该保证让左边来遇到右边,就是让右边的位置先到等着左边。因为我们选取的是左边的key,所以左边的下标就是少了 1 ,我们让右边先走就可以刚好弥补过来。反之,如果我们选取左边为key,还让左边先走,那么我们最后就会发现,这个位置的下标就错了,不能保证左边都是大于key的数了。

综上:我们如果选择了左边为key,那么就让右边先走,选择右边为key,就让左边先走。

我们看着示意图实现下单趟排序代码:

//前后指针法单趟排序
int PartSort(int *a,int left,int right)
{
	int keyi = left;//先保存最左侧下标,作为keyi
 
	while (left < right)
	{
		//先让右走,找小,并且不能越界
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}
 
		//再让左走,找大,不越界。
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}
 
		//交换左边大的,和右边小的
		Swap(&a[left], &a[right]);
	}
 
	//循环完成,我们在最后交换下,相遇位置的和原来keyi位置的值
	Swap(&a[keyi], &a[left]);
 
	//返回相遇位置的下标是为进行下一步递归。
	return left;
}

2.挖坑法单趟排序实现

我们看下有点意思的挖坑法。

我们观察发现,还是先选取一个位置作为我们比较的数同时也是坑位,然后还是先让右边走,然后把数据放到坑中,形成一个新的坑,接着左边走,再把数据放入坑中,形成新坑,最后,把我们选取位置的数据放到最后一个坑位上,就满了。

其实在我们调试发现,"挖坑" 只不过是形象描述了,其实乜有坑位,只是数据重复,然后替换掉了。

图示比较简单,我们尝试实现下单趟排序:

 //挖坑法
int PartSort2(int* a, int left, int right)
{
	int key = a[left];//保存最左边初始位置的值
 
	while (left < right)
	{
		while (left < right && a[right] >= key)
		{
			--right;
		}
 
		a[left] = a[right];//产生一个坑位
 
		while (left < right && a[left] <= key)
		{
			++left;
		}
 
		a[right] = a[left];//上一个坑位填上,产生新的坑位
	}
 
	a[left] = key;//把最后的坑位填上了。
 
	return left;//返回最后相遇的下标,以便后序递归
}

3.前后指针法

前后指针法和左右指针类似但是不完全一样哦。

前后指针法,其实就是定义两个指针,一个是prev为初始位置,一个是cur为初始位置+1,cur是遇见大于初始位置的值停下,交换(prev+1)下标的值,直到 cur 指针走到结尾,此时就交换prev指针和初始位置即可。

简单理解:

前后指针,就是不停的把大于初始位置的数据向后移动,最后一个指针走到末尾了,另一个指针此时的指向,刚好就是我们初始位置在整个数据中要排的位置。

需要注意的是:我们每次交换的都是prev+1的下标值,如果 prev = cur 时,此时我们不用交换,prev也不用++,只需要 cur++ 即可。

前后指针的单趟代码实现:

//前后指针法
int PartSort3(int *a, int left, int right)
{
	int prev = left;//后指针
	int cur = left + 1;//前指针
	int keyi = left;//初始位置
 
	while(cur <= right)//当cur小于等于最右边时进入循环
	{
		//当cur找到比初始位置大的数,如果此时cur不等于prev,
		//那么就交换cur和++prev,一定是前置++。
		if (a[cur] < a[keyi] && prev != cur)
		{
			Swap(&a[cur], &a[++prev]);
		}
		cur++;
	}
	Swap(&a[prev], &a[keyi]);//最后交换prev和初始位置即可
 
	return prev;//返回prev为了后续递归做铺垫
}

以上就是详解C语言快速排序三种方法的单趟实现的详细内容,更多关于C语言快速排序单趟实现的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详解C语言快速排序三种方法的单趟实现

本文链接: https://www.lsjlt.com/news/151268.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 详解C语言快速排序三种方法的单趟实现
    目录交换排序的思想冒泡排序的思想快速排序的整体框架快速排序单趟实现逻辑1. hoare版本单趟实现(左右指针法)2.挖坑法单趟排序实现3.前后指针法交换排序的思想 基本思想:所谓交换...
    99+
    2022-11-13
  • C语言实现单链表的快速排序算法
    目录背景设计思路算法主要步骤快速排序算法实现整个程序源代码测试案例总结背景 传统QuickSort算法最大不足之处在于,由于其基于可索引存储结构设计(一般为数组或索引表),因而无法用...
    99+
    2022-11-13
  • C语言下快速排序(挖坑法)详解
    目录全部代码如下挖坑法-->代码讲解-->总结全部代码如下 #include <stdio.h> void evaluation(int *x,int...
    99+
    2022-11-12
  • C/C++实现快速排序(两种方式)图文详解
    目录介绍实现方式一方式二总结介绍 快速排序是对冒泡排序算法的一种改进,快速排序算法通过多次比较和交换来实现排序。 流程如下:   实现 以下有两种实现方式,说是两种,其...
    99+
    2022-11-12
  • C语言实现快速排序算法实例
    首先我们要对一组数据进行排序: 在数组中选一个基准数(通常为数组第一个,黄圈圈标记了); 将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边,怎么移动,后面说; 对于基准数...
    99+
    2022-11-13
  • C语言如何实现快速排序算法
    这篇文章将为大家详细讲解有关C语言如何实现快速排序算法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。代码#define  _CRT_SECURE_NO_WARNINGS 1/...
    99+
    2023-06-22
  • C/C++实现快速排序算法的两种方式实例
    目录介绍流程如下实现方式一方式二总结介绍 快速排序是对冒泡排序算法的一种改进,快速排序算法通过多次比较和交换来实现排序。 流程如下 (图片来自百度) 实现 以下有两种实现方式,说是...
    99+
    2022-11-12
  • 超详细解析C++实现快速排序算法的方法
    目录一、前言1.分治算法2.分治算法解题方法二、快速排序1.问题分析2.算法设计3.算法分析三、AC代码一、前言 1.分治算法 快速排序,其实是一种分治算法,那么在了解快速排序之前,...
    99+
    2022-11-13
  • C语言实现数组元素排序方法详解
    目录前言算法总结及实现优化算法前言 在实际开发中,有很多场景需要我们将数组元素按照从大到小(或者从小到大)的顺序排列,这样在查阅数据时会更加直观,例如: 一个保存了班级学号的数组,排...
    99+
    2023-02-11
    C语言数组元素排序 C语言数组元素 C语言数组排序
  • C++归并法+快速排序实现链表排序的方法
    本文主要介绍了C++归并法+快速排序实现链表排序的方法,分享给大家,具体如下: 我们可以试用归并排序解决: 对链表归并排序的过程如下。 找到链表的中点,以中点为分界,将链表拆分成...
    99+
    2022-11-12
  • C语言实现交换排序算法(冒泡,快速排序)的示例代码
    目录前言一、冒泡排序1.基本思想2.优化3.扩展二、快速排序1.基本思想2.优化3.代码前言 查找和排序是数据结构与算法中不可或缺的一环,是前辈们在算法道路上留下的重要且方便的一些技...
    99+
    2022-11-13
  • C语言实现打印杨辉三角的方法详细(三种方法)
    目录题目描述问题分析1. 使用数组法(打印直角三角)2. 使用数组法(打印等腰三角)3. 使用公式法(打印等腰三角)网上参考题目描述 打印杨辉三角(前N行) 问题分析 杨辉三角是中国...
    99+
    2022-11-12
  • C语言实现短字符串压缩的三种方法详解
    目录前言一、通用算法的短字符压缩二、短字符串压缩(1)Smaz(2)Shoco(3)Unisox2三、总结前言 上一篇探索了LZ4的压缩和解压性能,以及对LZ4和ZSTD的压缩、解压...
    99+
    2022-11-13
    C语言短字符串压缩 C语言 字符串压缩
  • C语言魔方阵的三种实现方法
    目录魔方阵:1.奇数阶魔方阵 2.偶数阶魔方阵 (n=4K)3.偶数阶魔方阵 (n=4K+2)魔方阵: 把1到n*n排成n行n列方阵,使方阵中的每一行、每一列以及对角线上的数之和都相...
    99+
    2022-11-12
  • c语言实现的几种常用排序算法
    概述 最近重新回顾了一下数据结构和算法的一些基本知识,对几种排序算法有了更多的理解,也趁此机会通过博客做一个总结。 1.选择排序-简单选择排序 选择排序是最简单的一种基于O(n2)时...
    99+
    2022-11-12
  • JS实现数组随机排序的三种方法详解
    目录1.利用数组方法sort实现随机排序2.洗牌算法实现随机排序3.洗牌算法深入分析全部代码1.利用数组方法sort实现随机排序 实现随机排序方法还是很多的,用for循环是可以写的,...
    99+
    2022-11-13
  • C语言中栈的两种实现方法详解
    目录一、顺序栈二、链式栈总结一、顺序栈 #include<stdio.h> #include<stdlib.h> #define maxsize 64 ...
    99+
    2022-11-12
  • C语言实现冒泡排序算法的示例详解
    目录1. 问题描述2. 问题分析3. 算法设计动图演示4. 程序设计设计一设计二结论5. 流程框架6. 代码实现7. 问题拓展1. 问题描述 对N个整数(数据由键盘输入)进行升序排列...
    99+
    2022-11-13
  • C语言非递归算法解决快速排序与归并排序产生的栈溢出
    目录1、栈溢出原因和递归的基本认识2、快速排序(非递归实现)3、归并排序(非递归实现)建议还不理解快速排序和归并排序的小伙伴们可以先去看我上一篇博客​​​​​​哦!C语言超详细讲解排...
    99+
    2022-11-13
  • C语言函数调用的三种实现方法实例
    目录C语言函数第一种方法第二种方法第三种方法总结C语言函数 1.概念:函数是一组一起执行一个任务的语句,每个c程序都必须有一个main函数,程序员可以把代码划分到不同的函数当中去,在...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作