【数据结构】八大排序(二)

目录

前言:

冒泡排序

冒泡排序代码实现

冒泡排序特性总结

快速排序

单趟排序hoare版本

单趟排序挖坑法

单趟排序快慢指针法

 快速排序整体概览

快排的优化

三数取中法选key

小区间优化


前言:

上文介绍了直接插入排序,希尔排序,选择排序,堆排序并对四种排序进行了详尽的探讨,本文将以排序的基本思想,代码实现和各种排序的特性总结三个角度继续分析冒泡排序,快速排序

冒泡排序

冒泡排序的基本思想:

将待排序的序列从前向后依次比较相邻元素的值,如果逆序则交换

升序:将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来后最大元素就在数组的末尾;

降序:将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素小,则交换,一趟下来后最小元素就在数组的末尾;

具体步骤如下

  1. 比较待排序序列中相邻的两个元素,如果发现左边的元素比右边的元素大,则交换这两个元素
  2. 每一对相邻的两个元素重复第一步的动作,从左至右依次执行,最后的元素一定是最大的元素
  3. 由于最大的元素位于数组尾元素的位置,下一趟两两比较的范围为待排序序列的首元素倒数第二个元素所处的位置,这段范围成为新的待排序序列,重复步骤1,步骤2;
  4. 持续以上步骤 1, 步骤 2, 步骤 3 的工作,每重复一次需要排序的序列中少一个最右边的元素,直到没有任何一对数字需要比较排序;

......

冒泡排序代码实现

void bubblesort(int arr[], int n)
{// 外层循环控制冒泡排序的趟数int i = 0;for (i = 0; i < n - 1; i++){//内层循环控制要比较元素的个数int j = 0;for (j = 0; j < n - i - 1; j++){int temp = 0;if (arr[j]>arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}

冒泡排序特性总结

1.时间复杂度

冒泡排序的平均 时间复杂度是O(n^2),最好时间复杂度是O(n),最坏时间复杂度是O(n^2);

2. 空间复杂度

额外开辟的空间为常数个,所以空间复杂度为O(1)

3.算法稳定性

冒泡排序是一种稳定的排序算法,即相等元素的相对位置在排序前后不会发生改变;

快速排序

快速排序的基本思想

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值右子序列中所有元素均大于基准值,然后对左右子序列分别递归地进行快速排序,直到所有元素都排列在相应位置上为止;

单趟排序hoare版本

思路如下:

1. 选取待排序序列最左边元素作为基准值key,定义两个指针left和right分别指向待排序序列的最左侧和最右侧,right从右向左走,left 从左向右走;

2.right先走,right指针找比基准值key小的数;left后走, left找比基准值key大的数;找到后将两个数交换位置;

3. 当left指针与right指针相遇时,将相遇位置的值与基准值key进行交换;

void swap(int* p, int* q)
{int tmp = *p;*p = *q;*q = tmp;
}
//单趟排序hoare版本
int PartSort(int* a, int left, int right)
{int keyi = left;//选取左边作为基准值,则右边先走while (left < right)//left与right相遇,左边找大,右边找小的循环终止{//右边找小while (left<right && a[right] >= a[keyi]){right--;}//左边找大while (left<right && a[left] <= a[keyi]){left++;}//交换swap(&a[left], &a[right]);}swap(&a[keyi], &a[left]);return left;
}

思考: 为什么left与right相遇位置处的数值比key要小

left与right相遇有如下俩种情形:

相遇的第一种情形:right动left不动,相遇位置为left位置,left位置与前一个right位置进行了交换,交换之后left位置比key小;

相遇的第二种情形:right不动left动,相遇位置为right位置,此时left找大没有找到与right相遇,而right位置一定比key小;

思考:为什么左边取基准值key,右边先走?

保证当left与right相遇时,相遇位置小于基准值

  1. right 停下时,left 与 right 相遇,由于right 找比 key小的值,所以此时 right 的位置一定比key小;
  2. left 停下时,right 与 left 进行交换,交换后 left 指向的值比 key 小,此时 right 遇到 left 的位置一定比key小;

单趟排序挖坑法

思路如下:

1. 选择数组第一个数作为基准数,基准数的位置形成一个坑位
2. 定义两个指针left与right分别指向待排序序列的第一个数和最后一个数;
3. 从right开始向前遍历,找到第一个小于基准数的数a[right],将其赋值给a[left],a[right]成为一个新的坑位;
4. 从left开始向后遍历,找到第一个大于基准数的数a[left],将其赋值给a[right],a[left]成为一个新的坑位;
5. 重复步骤3和4,直到left > right
6. 将基准数填入最后一个坑中,a[left]=key;

//单趟排序挖坑法
int PartSort(int* a, int left, int right)
{int key = a[left];int hole = left;while (left < right){//右边先走while (left < right && a[right] >= key){right--;}a[hole]=a[right];hole = right;//左边再走while (left < right&&a[left] <= key){left++;}a[hole] = a[left];hole = left;}a[hole] = key;return hole;
}

单趟排序快慢指针法

思路如下:

1. 选取待排序序列的第一个元素作为基准值key;
2. 定义两个指针prev和cur,prev指针指向序列开头,cur指针指向prev指针的后一个位置
3. 从cur开始向前遍历,如果遇到比key小的元素,就将prev指针向后移动一位,并交换prev和cur指向的元素;
4. 遍历结束后,将key与prev指向的元素交换位置,此时prev指向的位置就是key的最终位置;

//单趟排序前后指针法
int PartSort(int* a, int left, int right)
{int keyi = left;int prev = left;int cur = prev + 1;while (cur <= right){//(++prev)!=cur为了防止++prev与cur指向相同数值,此时交换毫无意义;if (a[cur] < a[keyi]&&(++prev)!=cur){swap(&a[cur], &a[prev]);}cur++;}swap(&a[keyi], &a[prev]);return prev;
}

 快速排序整体概览

快速排序首先选取基准值key,将待排序序列分为两个子序列,左子序列放比基准值小的数,右子序列放比基准值大的数,然后再将子序列以以上方式同样分割,直到数组有序,下图单趟排序采取hoare版本

  • 经过一趟hoare排序,区间被划分为[begin, keyi-1] U keyi U [keyi+1, end] ,单趟排序一次就会唯一确定一个元素来到最终排序所确定的位置

  • 先递归排序左子序列[begin, keyi-1] , 再递归排序右子序列[keyi+1, end],类似二叉树前序遍历

  • 根据上图可得出递归终止条件为区间不存在(begin>end)或者只有一个元素(begin=end)
void QuickSort(int*a, int begin, int end)
{//递归终止的条件//1.区间不存在(begin>end)或者只有一个元素(begin=end)if (begin >= end)return;int keyi = PartSort3(a, begin, end);// 一趟排序原排序区间划分为如下三部分//[begin keyi-1]U[keyi]U[keyi+1,end]QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}

快排的优化

三数取中法选key

若选取的基准值key是序列中最大或最小的数值,则快速排序的递归深度会非常深,排序效率会很低;若是一个有序数组使用快速排序,则递归深度为n,单趟排序也为n,时间复杂度为O(n^2);

假定待排序序列的左下标left , 右下标right,左右下标所对应的中间下标 midi=(left+right)/2,取三个下标所对应的值的中间值为基准值key,可以防止快排出现最差情形;

//三数取中法选keyi keyi为中间值的下标
int GetMidi(int* a, int left, int right)
{int mid = (left + right) / 2;if (a[left] > a[mid]){if (a[mid] > a[right]){return mid;}//mid为最小值else if (a[left] > a[right]){return right;}else{return left;}}else{if (a[mid] < a[right]){return mid;}//mid为最大值else if (a[left]>a[right]){return left;}else{return right;}}
}

小区间优化

由于快速排序是递归实现的,而每一次函数调用,均需要开辟函数栈帧,当递归到最后几层时,此时数组中的值其实已经接近有序,最后几层的函数调用会极大占用函数栈帧所开辟的空间;

假设数组大小N=10,即二叉树节点个数N=10;

10个数值,递归了3~4层,而最后三层占据比例为87.5%,调用函数的次数就越多,开辟函数栈帧的消耗越大,导致效率下降,代价太大,在递归分割过程中,当区间较小时,不再递归分割排序,序列在递归分割过程中,子序列已经接近有序插入排序每一次单趟排序都只向前遍历到最大值之后,一共执行n次,若数组有序,则总共只执行n次,最差情况下每次都只是从i遍历到0下标,综合考虑是执行次数最优,故选择直接插入排序进行优化

void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;// 小区间优化,小区间不再递归分割排序,降低递归次数if ((end - begin + 1) > 10){int keyi = PartSort(a, begin, end);// [begin, keyi-1] keyi [keyi+1, end]QuickSort1(a, begin, keyi - 1);QuickSort1(a, keyi + 1, end);}else{InsertSort(a + begin, end - begin + 1);}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/178839.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3怎么提升效率的?为什么vue3比vue2快?效率提升主要在哪些方面?

官方文档中说vue3在 客户端渲染效率比vue2提升了1.3~2倍&#xff0c; SSR渲染效率比vue2提升了2~3倍&#xff0c;那么究竟是怎么提升的呢&#xff1f; 一、静态提升 在 vue3项目中的package.json文件中&#xff0c;可以看到这个 vue/compiler-sfc&#xff0c;它是用来解析(.v…

【Java Spring】SpringBoot常用插件

文章目录 1、Lombok1.1 IDEA社区版安装Lombok1.2 IDEA专业版安装Lombok1.3 Lombok的基本使用 2、EditStarters2.1 IDEA安装EditStarters2.2 EditStarters基本使用方法 1、Lombok 是简化Java开发的一个必要工具&#xff0c;lombok的原理是编译过程中将lombok的注解给去掉并翻译…

电力感知边缘计算技术网关产品设计方案-硬件方案

网关硬件架构设计图: 1.配置方案 配置差异 A类网关 B类网关 CPU

写一个宏,交换整数二进制位的奇数位和偶数位,并打印这个新的数

我们已经学过了C语言的宏&#xff0c;我们今天应用宏来交换一个整数的二进制的奇数位和偶数位&#xff0c;并得到这个被交换过的数&#xff0c;我们开始吧&#xff01; 1.问题分析 解题方法&#xff1a;& 和<< 和>>操作符 问题解析&#xff1a;我们这里假设一个…

这才是BI大数据分析工具的正确打开方式!

这两年经济下行给各行各业造成不小的发展困扰&#xff0c;为此企业积极自救&#xff0c;希望通过数字化降本增效&#xff0c;提高业绩水平。BI大数据分析工具就是企业数字化转型中常用到的一种商业智能BI工具&#xff0c;主要作用是缩短数据分析时间&#xff0c;提升企业数据分…

解析直播第三方美颜SDK:技术原理与应用

时下&#xff0c;直播平台和主播们纷纷引入美颜技术&#xff0c;以提升视觉效果和用户体验。而在众多美颜技术中&#xff0c;直播第三方美颜SDK成为许多开发者和平台的首选&#xff0c;因其灵活性和高效性而备受推崇。 一、技术原理&#xff1a;美颜算法的精髓 第三方美颜SDK…

2023年【A特种设备相关管理(锅炉压力容器压力管道)】新版试题及A特种设备相关管理(锅炉压力容器压力管道)模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【A特种设备相关管理&#xff08;锅炉压力容器压力管道&#xff09;】新版试题及A特种设备相关管理&#xff08;锅炉压力容器压力管道&#xff09;模拟考试题库&#xff0c;包含A特种设备相关管理&#xff08;锅…

基于Python+OpenCV+dlib+Tensorflow深度学习的人脸表情识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 人脸表情识别是一种重要的计算机视觉任务&#xff0c;它涉及到对人脸图像中的表情进行分类和理解。在这个系统中&am…

vue使用echarts中国地图

需求&#xff1a;Vue3 vite TS 项目内使用 Echarts 5 绘制中国地图。鼠标悬浮省份上面显示指定的数据&#xff0c;地图支持缩放和拖拽的功能&#xff0c;页面放大缩小支持自适应&#xff0c;window.addEventListener(‘resize’, resize); 添加防抖动函数debounce。 一、安装…

零基础学Python第三天||写一个简单的程序

通过对四则运算的学习&#xff0c;已经初步接触了Python中内容&#xff0c;如果看官是零基础的学习者&#xff0c;可能有点迷惑了。难道敲几个命令&#xff0c;然后看到结果&#xff0c;就算编程了&#xff1f;这也不是那些能够自动运行的程序呀&#xff1f; 的确。到目前为止…

算法基础二

回文数 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 示例 1&#xff1a; 输入&#xff1…

【FGPA】Verilog:JK 触发器 | D 触发器 | T 触发器 | D 触发器的实现

0x00 JK 触发器 JK 触发器是 RS 触发器和 T 触发器的组合&#xff0c;有两个输入端 J 和 K&#xff0c;如果两个输入端都等于 1&#xff0c;则将当前值反转。 行为表 状态图 Timing Diagram Circuit JK 触发器的设计目的是防止 RS 触发器在输入 S 和 R 均等于 …

使用Java给钉钉群发消息

目录 目录 1.安装依赖 2.编写工具类 3.测试 安全设置 Webhook 代码编写 运行测试 4.艾特全部功能 1.安装依赖 <dependency><groupId>com.taobao.dingding</groupId><artifactId>taobao-sdk</artifactId><version>1.0.0</versio…

E云管家开发个人微信号批量修改好友备注

简要描述&#xff1a; 修改好友备注 请求URL&#xff1a; http://域名地址/modifyRemark 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说…

扫地机器人市场持续火爆,景联文科技数据采集标注方案助力扫地机器人智能化升级

随着消费者对智能家居和清洁卫生的需求增加&#xff0c;扫地机器人市场规模不断扩大。市场竞争也日益激烈&#xff0c;各品牌都在努力提升产品性能和服务质量&#xff0c;以获取更大的市场份额。 IDC的统计数据显示&#xff0c;今年双十一前两周&#xff08;2023年10月23日至20…

Python入门05 print函数

目录 1 Python中的内置函数2 print函数介绍3 print函数的用途总结 1 Python中的内置函数 Python中内置了很多函数&#xff0c;我们可以直接调用&#xff0c;以下是一些常见的函数&#xff1a; abs()&#xff1a;返回一个数的绝对值。all()&#xff1a;判断一个可迭代对象中的…

Jmeter和Testlink自动化测试框架研究与实施

摘 要 目前基于Jmeter的接口自动化测试框架&#xff0c;大多只实现脚本维护和自动调度&#xff0c;无法与Testlink进行互通&#xff0c;实现测试方案与自动化实施流程连接&#xff0c;本文基于Testlink、Jmeter、Jenkins实现&#xff1a;通过Testlink统一维护接口自动化测试用…

基于python的IOS自动化测试小技巧

文章目录 一、Xpath 的使用1.1 使用Xpath读取固定位置的元素的内容一、Xpath 的使用 在执行IOS APP UI自动化测试时,需要使用到元素定位,我们使用WEditor进行元素的定位,操作流程可以查看基于Python的IOS自动化测试环境搭建 ,但是在一些特殊的场景需要灵活使用元素定位。 …

大数据平台/大数据技术与原理-实验报告--部署全分布模式HBase集群和实战HBase

实验名称 部署全分布模式HBase集群和实战HBase 实验性质 &#xff08;必修、选修&#xff09; 必修 实验类型&#xff08;验证、设计、创新、综合&#xff09; 综合 实验课时 2 实验日期 2023.11.07-2023.11.10 实验仪器设备以及实验软硬件要求 专业实验室&#xff…

diffusion model (九) EmuEdit技术小结

文章目录 背景1 核心思想2 方法2.1 方法建模2.2 数据工程2.2.1 image-edit任务类别定义2.2.2 指令集生成2.2.3 图片对的生成 3 结果 Paper: https://emu-edit.metademolab.com/assets/emu_edit.pdf Project web: https://emu-edit.metademolab.com/ Code: have not opensourc…