C语言实现冒泡排序和快速排序

2023-10-28

写在前面的话:以排升序为例

目录

冒泡排序

单趟

循环

优化

快速排序

单趟

递归

优化

不足


冒泡排序

通过重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

单趟

单趟会通过两两比较的方式将数组中最大的元素排到末尾

	for(int j=0;j<numsSize-1;j++)
	{
		if(nums[j]>nums[j+1])
		{
			Swap(&nums[j],&nums[j+1]);
		}
	}

循环

初始:第一趟,是将数组下标从0到numsSize-1的范围中的最大元素放在了numsSize-1的位置上

循环:缩小范围,将数组下标从0到numsSize-2的范围中的最大元素放在numsSize-2的位置上

终止:当范围缩小到一个元素

void Bubble(int* nums,int numsSize)
{
	for(int i=0;i<numsSize-1;i++)
	{
		for(int j=0;j<numsSize-1-i;j++)
		{
			if(nums[j]>nums[j+1])
			{
				Swap(&nums[j],&nums[j+1]);
			}
		}
	}
}

优化

优化点在于,当一个升序数组通过冒泡进行排序,时间复杂的是O(N*N),可以在此种情况优化为O(N)

void Bubble(int* nums,int numsSize)
{
	for(int i=0;i<numsSize-1;i++)
	{
		bool exchage=false;
		
		for(int j=0;j<numsSize-1;j++)
		{
			if(nums[j]>nums[j+1])
			{
				Swap(&nums[j],&nums[j+1]);
				exchage=true;
			}
		}
		
		if(bool==false)
		{
			break;
		}
	}
}

快速排序

我的理解:

快速排序使用递归,在每层的的递归中,只做一件事,那就是将当前范围内的某一个关键字元素(通常选取最左侧元素)放到正确的位置上来

回归,有深层次的递归就要有回归,当某一层递归排序的数组范围小到只有一个及以下的元素个数时,就需要回归结束递归了

单趟

.首先实现将关键元素放到正确的位置上,解释:当一个元素在数组中的位置满足两个条件,我们认为它在正确的位置上

1,在它之前的元素小于它

2,在它之后的元素大于等于它

..这里使用前后指针的方法,关于此方法的理解,我们可以这样看:

将数组划分为两部分:

 通过指针cur,prev将蓝色部分调整为蓝色部分中的小于nums[keyi]的元素聚集在前一部分,大于等于nums[keyi]的元素聚集在后一部分:

 此时,交换keyi与prev的元素即可使keyi指向的元素来到正确的位置

void QuickSort(int* nums,int left,int right)
{
	int keyi=left;
	int prev=left;
	int cur=prev+1;
	
	while(cur<=right)
	{
		if(nums[cur]<nums[keyi]&&++prev!=cur)
		{
			Swap(&nums[cur],&nums[prev]);
		}
		
		cur++;
	}
	
	Swap(&nums[prev],&nums[keyi]);
}

递归

递归至回归,即可完成排序(至此快排基本完成,可以完成多数情况下的排序)

void QuickSort(int* nums,int left,int right)
{
	if(left>=right)
	{
		return;
	}
	
	int keyi=left;
	int prev=left;
	int cur=prev+1;
	
	while(cur<=right)
	{
		if(nums[cur]<nums[keyi]&&++prev!=cur)
		{
			Swap(&nums[cur],&nums[prev]);
		}
		
		cur++;
	}
	
	Swap(&nums[prev],&nums[keyi]);
	
	QuickSort(nums,left,prev-1);
	QuickSort(nums,prev+1,right);
}

优化

针对部分特殊情况,可以进行相应的优化

一,针对有序数组,当升序数组进入上述快排时,会出现递归层数过深(栈溢出)的问题,应对方法有

1,随机取keyi

2,三数取中

二,当数组长度较小的时候,使用快排是不合适的,在递归层次较深的时候,目标数组长度较小的时候,可以考虑不再继续递归,而是将这一长度较小的数组直接使用插入排序完成排序

给出快排代码:

void* Swap(int* x,int* y)
{
	int temp=*x;
	*x=*y;
	*y=temp;
}

int MidNum(int* nums,int left,int right)
{
	int mid=(left+right)/2;
	
	if(nums[left]>nums[right])
	{
		if(nums[mid]>nums[right])
		{
			return mid;
		}
		else if(nums[mid]>nums[left])
		{
			return left;
		}
		else
		{
			return mid;
		}
	}
	else
	{
		if(nums[mid]>nums[left])
		{
			return mid;
		}
		else if(nums[mid]>nums[right])
		{
			return right;
		}
		else
		{
			return mid;
		}
	}
}

void InsetSort(int* nums,int left,int right)
{
	for(int i=left;i<right;i++)
	{
		for(int end=i;end<right;end++)
		{
			if(nums[end]>nums[end+1])
			{
				Swap(&nums[end],&nums[end+1]);
			}
		}
	}
}

void QuickSort(int* nums,int left,int right)
{
	if(left>=right)
	{
		return;
	}
	//三数取中,避免升序数组进入快速排序后栈溢出
	int mid=MidNum(nums,left,right);
	Swap(&nums[left],&nums[mid]);
	
	int keyi=left;
	int prev=left;
	int cur=prev+1;
	
	while(cur<=right)
	{
		if(nums[cur]<nums[keyi]&&++prev!=cur)
		{
			Swap(&nums[cur],&nums[prev]);
		}
		
		cur++;
	}
	
	Swap(&nums[prev],&nums[keyi]);
	//当数组长度小到一定范围后,不再通过递归的方式排序,而是通过插入排序将这个长度较短的数组排序
	if(right-left+1>=13)
	{
		QuickSort(nums,left,prev-1);
		QuickSort(nums,prev+1,right);
	}
	else
	{
		InsetSort(nums,left,right);
	}
}

不足

依然存在可优化的空间,针对待排序数组中存在大量重复的元素的情况,可以使用三路划分(未掌握,挖个坑)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言实现冒泡排序和快速排序 的相关文章

  • 有没有办法分析 WCF 应用程序的性能?

    我们正在尝试测量我们的系统的性能 该系统是一个使用 WCF 调用的 NET 3 5 应用程序 问题是到目前为止 我们无法分析这些调用中的方法 编写了一个 winforms 客户端应用程序来测试我们的系统 我们尝试使用ANTS 4 Profi
  • 类型转换 sockaddr 结构

    我正在尝试学习网络编程 并在这个过程中学习C 我对结构感到困惑sockaddr这是一个通用地址 并且sockaddr in 我的书里是这么说的 因此 我们可以填写 sockaddr in 的字段 然后强制转换 a 指向 它指向 指向 soc
  • 将数据集导出到 EXCEL

    我使用以下代码将数据库表中的字段导出到 Excel 中 我想要做的是能够编写一条 SQL 语句从多个表中检索字段并将其导出到 Excel 中 这段代码只允许我导出一张表 另外 如何显示保存提示对话框 示例代码将不胜感激 非常感谢 prote
  • 如何查找boost运行时版本

    我正在编写一个使用 boost 的 C 库 在这个库中 我想包含有关用于编译我的库的二进制版本的 boost 版本的信息 我可以使用宏BOOST VERSION这很好 我还想确定哪个是 boost 的运行时版本 以便我可以与用于编译我的库的
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • 实体框架 - 循环更新属性

    我正在尝试找到一种方法来循环 EF 对象的属性并更新这些属性的值 更具体地说 我有 50 个字段 其中最多填充 50 个下拉列表 所有 50 个可能都需要填充 也可能不需要填充 为了解决这个问题 我有一个中继器 最多可以创建 50 个 DD
  • Reflection.Emit 中的短格式操作码错误

    我正在制作一种与以下非常相似的小语言hlsl但仅支持像素着色器 该语言使用reflection emit构建实现相同功能的 NET 程序集 我目前正在测试分支指令的实现if在我的一个单元测试中 一个大的if与内if elses 失败并显示以
  • c#Registry to XML无效字符问题

    我在尝试从注册表创建 XML 文件时遇到问题 在我的笔记本电脑 W7 64b 上它工作正常 生成了 xml 文件 但在另一台计算机 Xp 32b 上抛出异常 System ArgumentException 十六进制值 0x00 是无效字符
  • 从空白启动时 VSTO 功能区不显示解决方案

    如果我从 文件 新建项目 菜单创建一个新的 Excel 2013 和 2016 VSTO 加载项 项目 然后单击 项目 添加新项目 gt 功能区 可视化设计器 则一切正常 我启动了应用程序 我的功能区显示在 Excel 中 但是 如果我首先
  • 是否可以用 C# 为 Android 编写应用程序?

    我们都知道Android运行Dalvik VM程序 通常开发人员用 Java 编写程序并将其编译为 Dalvik 字节码 我想知道是否有可能创建一个可以接受 C 代码并将其编译为 Dalvik 字节码的编译器 嗯 这是一种选择 或者您可以在
  • 平衡两轮机器人而不使其向前/向后漂移

    我正在尝试设计一个控制器来平衡 2 轮机器人 约 13 公斤 并使其能够抵抗外力 例如 如果有人踢它 它不应该掉落 也不应该无限期地向前 向后漂移 我对大多数控制技术 LQR 滑模控制 PID 等 都很有经验 但我在网上看到大多数人使用 L
  • 为什么std::string在发布时是标准布局类型,但在调试时不是标准布局类型?

    include
  • 读取所有进程内存以查找字符串变量c#的地址

    我有 2 个用 C 编写的程序 第一个名为 ScanMe 的程序包含一个包含值 FINDMEEEEEEE 的字符串变量 以及一个值为 1546 22915487 的双精度变量 另一个名为 MemoryScan 的程序读取第一个程序的所有内存
  • 在 C# 中加密并在 Flex 中解密

    我需要解密 Flex 中的一些数据 这些数据是用 C 加密并写入文件的 为了简单起见 我选择使用 as3crypto As3 库和 Bruce Schneier C 库 AS3 as3加密链接 http code google com p
  • 修改公共属性的访问修饰符是否是重大更改?

    如果我将公共属性的 setter 的访问修饰符从私有更改为公共 是否会导致引用它的其他程序集发生任何重大更改 UPDATE 这个问题是我 2012 年 1 月博客的主题 https ericlippert com 2012 01 09 ev
  • Yield Return == IEnumerable 和 IEnumerator 吗?

    Is yield return实施的捷径IEnumerable and IEnumerator 是的 您可以在我的书 C in Depth 的第 6 章中找到更多相关信息 幸好第六章是免费提供 http www manning source
  • 如何从标准输入读取一行,阻塞直到找到换行符?

    我试图从命令行的标准输入一次读取任意长度的一行 我不确定是否能够包含 GNU readline 并且更喜欢使用库函数 我读过的文档表明getline应该可以工作 但在我的实验中它不会阻塞 我的示例程序 include
  • 什么是多重重继承?

    我将以下称为 多重重新继承 直接继承一个类一次 并通过继承其一个或多个后代来间接继承一次或多次 通过继承一个类的两个或多个后代来间接继承一个类两次或多次 我想知道它是否存在以及如何明确访问嵌入的子对象 1 Professional C 2n
  • 在 WPF 树视图中获取 FullPath?

    如果我以编程方式创建 WPF TreeView 例如 TreeView treeView lt added in the designer TreeViewItem rootNode new TreeViewItem rootNode He
  • C++20 范围太多 |运营商?

    我在这段代码中使用 g 10 2 有谁知道为什么我最后收到编译器错误std views reverse on results3 include

随机推荐

  • 日撸leetCode三道题---Day1---二分查找

    二分查找时间复杂度为O log n 针对有序数组 定义查找区间 var low 0 var high n 循环查找 while low
  • 深入剖析HTTP和HTTPS代理在爬虫中的应用价值

    在当今信息时代 数据是无处不在且极其宝贵的资源 对于从互联网上获取大量结构化或非结构化数据的需求而言 网络爬虫成为一种强有力的工具 然而 在实际操作过程中 我们常常会面临许多挑战和限制 其中一个主要问题就是目标网站可能会设置反扒机制来阻止自
  • 电话悬浮代码

    代码
  • 小娜老师的讲义-搭建私人镜像

    前言 之前我们讲docker的基本命令的时候 提到过docker pull 每次也是让大家直接从官方的registry 仓库 里面把需要用到的基础镜像pull下来 那我现在不想用官方的了 我就像用我自己已经做好的 而且其他同网段的同事们都可
  • 网络安全第1章课后题 网络安全概论

    1 选择题 1 计算机网络安全是指利用计算机网络管理控制和技术措施 保证在网络环境中数据的 完整性 网络服务可用性和可审查性受到保护 A 机密性 B 抗攻击性 C 网络服务管理性 D 控制安全性 2 网络安全的实质和关键是保护网络的 安全
  • 【ACWing 每日一练之接龙数列】

    题目 对于一个长度为 K的整数数列 A1 A2 AK 我们称之为接龙数列当且仅当 Ai的首位数字恰好等于 Ai 1的末位数字 2 i K 例如 12 23 35 56 61 11 是接龙数列 12 23 34 56不是接龙数列 因为 56的
  • Macbook pro如何设置触控栏touch bar?

    打开 系统偏好设置 点击打开 键盘 点击 自定功能栏 打开 自定功能栏 此时鼠标在屏幕下方继续下移就可以到触控栏 也可以将自己喜欢的功能按住拖到触控栏 如我就加上了锁屏 并将Siri移出触控栏Touch bar 因为总误触到它
  • mysql递归查询

    本文转载 文章底部有我实践过程中遇到的问题总结博客 希望能够帮到大家 2021SC SDUSC 我是以山东济南的行政区划作为示例的 数据库是MySQL 话不多说 直接上示例代码 目录 1 建表脚本 1 1 建表 1 2 插入数据 2 递归查
  • 小程序推广:微信公众平台可自由挂载小程序

    公众号可挂载任意小程序 在公众号挂载小程序的时候 会出现小程序搜索的页面 这里可以搜索所有微信上可被搜索的小程序 这意味着 公众号无需绑定小程序 可实现自由挂载 挂载的形式支持4种 其中小程序码是全新的挂载形式 选择后会释放该小程序码到公众
  • 【Unity Optimize】Unity中的优化工具和优化方法介绍

    目录 1 Unity项目优化的必要性 2 Unity自带的优化工具 2 1 Profiler窗口 Profile Analyzer 2 2 Stats窗口 2 3 Frame Debugger窗口 3 其他优化方法 3 1 批处理 Batc
  • MinGW下载和安装详细步骤 及 环境配置

    一 下载 点击 这里 进入官网下载最新版本的MinGW 这里下载的是Windows32位 但MinGW的所有软件都将在64位Windows平台上执行 所以32位和64位都是一样的 二 安装 1 下载完成后 双击程序进行安装 2 点击 Ins
  • Oracle学习总结09——表的操作

    1 创建数据表 createtable 代码手敲 且增加注释 问题 字段为系统默认日期怎么定义 创建students表 create table students stuno number 10 not null stuname varch
  • ExtJs4.0环境搭建及spket安装 .

    这些天在边学边用ExtJs 避免不了要写相关的代码来加深对这个框架的理解 那么首先就得搭建一个ExtJs的环境 1 开发环境 Microsoft Windows XP Version 2002 Service Pack 3 Eclipse
  • 华为OD机试 - 整型数组按个位值排序(Java)

    题目描述 给定一个非空数组 列表 其元素数据类型为整型 请按照数组元素十进制最低位从小到大进行排序 十进制最低位相同的元素 相对位置保持不变 当数组元素为负值时 十进制最低位等同于去除符号位后对应十进制值最低位 输入描述 给定一个非空数组
  • 深入 Spring 系列之静态资源处理

    深入 Spring 系列之静态资源处理 1 背景 前一段时间 WebIDE 开源的过程中 无意间接触到 webjars 觉得比较有趣 于是研究并整理了一下 webjars 是将前端的库 比如 jQuery 打包成 Jar 文件 然后使用基于
  • 什么是IQ信号, IQ调制又是怎么回事?

    在现代无线通信中 IQ调制属于标准配置 经常应用于通信系统的信号调制和解调环节 IQ调制的应用简化了通信设备的硬件结构 同时提高了频谱资源的利用效率 提高了信号传输的稳定性 让我们先来看看什么是IQ信号 IQ信号又称同向正交信号 I为in
  • linux grep 多个文件,Linux多文件查找工具之grep

    1 简介 grep全称Global Regular Expression Print 全局正则表达式打印 在这里面提到了三个关键词 我们逐个进行分析 这样有助于我们理解 grep这个命令的作用 1 global说明该命令可以用于所有用户 交
  • VHDL——含异步清零和同步使能的加法计数器源程序

    library ieee use ieee std logic 1164 all use ieee std logic arith all use ieee std logic unsigned all entity counter is
  • Kubernetes YAML 文件 详细解释

    To deploy Dashboard execute following command kubectl apply f https raw githubusercontent com kubernetes dashboard v1 10
  • C语言实现冒泡排序和快速排序

    写在前面的话 以排升序为例 目录 冒泡排序 单趟 循环 优化 快速排序 单趟 递归 优化 不足 冒泡排序 通过重复地走访过要排序的元素列 依次比较两个相邻的元素 如果顺序错误就把他们交换过来 走访元素的工作是重复地进行 直到没有相邻元素需要