九大排序之交换排序

1.前言

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

重点:

冒泡排序和快速排序

2.冒泡排序

思路:冒泡排序是典型的交换排序,每趟排一个值,一直排n-1趟,这样就能把n个值按照一定的顺序排好。

  • end记录冒泡的最终位置;
  • 待排区间中的数据前后两两比较,交换,冒泡到end;
  • 如果在一趟比较中没有发生交换则提前结束循环;
  • –end,准备冒下一个泡。当end > 0时循环继续。

代码如下:

void Bubble(int* arr,int size)
{//1.先确定趟数int end=size-1;while(end>0){bool exchange=false;for(int i=1;i<=end;i++){if(arr[i]<arr[i-1]) {exchange=true;swap(&arr[i],&arr[i-1]);}}end--;if(exchange) break;}
}

动画演示如下:

冒泡排序总结:

时间复杂度:O(n)~O(n^2)

空间复杂度:O(1)

稳定性:稳定

3.快速排序

快排是hore在19世纪提出的一种基于二叉树结构的排序方法,其基本思想是:先选定基准值,然后比基准值的小的放在其左边,比基准值大的放在其右边。然后再进行递归左边的值,然后再进行递归右边的值。一直递归到只有一个值为止。

方法一左右指针法也称hore法:

1. 选择一个关键字key,一般选最左值或最右值。
2. 单趟排序:目的是利用基准值key将序列分成左右两个部分:key左边的值比key要小,右边的值比key要大。即直接将key移动到排序后的最终位置。
3. 递归思想:单趟排完,再使用同样的方法使得左子区间有序,右子区间也有序,整体就有序了。

void QuickSort(int* arr,int left,int right)
{if(left>=right) return;int mid=parition(arr,left,right);QuickSort(arr,left,mid-1);QuickSort(arr,mid+1,right);
}int parition(int* arr,int left,int right)
{int keyi=arr[left];while(left<right){while(left<right&&keyi<=arr[right]) right--;while(left<right&&keyi>=arr[left])  left++;swap(&arr[left],&arr[right]);}swap(&keyi,&arr[left]);return left;
}

 动画演示:

 

规律总结:

  • 选最左值做key,右边先走:左右相遇时比key小
  • 选最右值做key,左边先走: 左右相遇时比key大

为什么?
没有相遇之前谁先走都无所谓,L找大R找小
相遇时(key选最左),无非是 L<–R 或 L–>R

L<-R (R找不到小),由于上次交换后L还未发生移动,此时的L< key (或L == key,其余所有数都比key要大);

例:5 6 3 1 7 4 2 8 9 ---如果是左边先走那么最后一次交换是  5 2 3 1 4 7 6 8 9    left和right同时指向7所在的位置,又因为选择了左边做基准值,所以相遇的位置必须是比基准值小的,那么就只能右边先走,把所有的大的走完了,遇见的第一个比基准值小的就是相遇值。
L->R(L找不到大),由于是每次循环R先走,此时的R<key;(与上述同理)

方法二:前后指针法

1.定义两个指针(下标)cur与prev一前一后:prev指向left,cur指向left+1;
2.选最左端left做keyi;(需提前做三数取中优化:让left,mid,right三个数的中间值于left交换);
3.cur不断向前找小于key的数,找到后与++prev(大于key)交换;如果++prev==cur,则可以不交换。
经4.过这样的交换,prev左边的值 (keyi, prev] 都小于key,prev右边的值 (prev, cur)都大于等于key。(prev是左右区间的交界)
5.最后将prev和key交换,就可以实现快排单趟的分割。

代码如下:

//三数取中
int GetMidIndex(int *arr, int left, int right){int mid = left + (right - left) / 2;int tmp1 = arr[left] > arr[mid] ? left : mid;int tmp2 = arr[mid] > arr[right] ? mid : right;return arr[tmp1] > arr[tmp2] ? tmp2 : tmp1;}int Partion2(int *arr, int left, int right){//三数取中 -- 有序的情况每次二分,将最坏情况变成最好情况int midi = GetMidIndex(arr, left, right);Swap(&arr[midi], &arr[left]);int prev=left,cur=left+1;while(cur<=right){if(arr[cur]<arr[midi]&&prev+1!=cur){prev++;swap(&arr[prev],&arr[cur]);}cur++;}swap(&arr[midi],&arr[prev]);return prev;
}void QuickSort(int *arr,int left,int right)
{if(left>=right) return;int mid=Parition2(arr,left,right);QuickSort(arr,left,mid-1);QuickSort(arr,mid+1,right);
}

 关键点:这里是把三数取中的值,与最左边进行了互换,所以选取的是最左边作为关键值。

当选取左边为关键值时:

1.prev=left,cur=left+1(把基准值排除在外)

2.循环条件是  cur<=right

3.最后把基准值与prev的值进行交换(得到了左边比其小,右边比其大)

当选取右边为关键值时:

1.那么cur应该为cur=left,prev=left-1;

2.cur<right(把基准值排除在外)

3.最后把基准值与prev的值进行交换

方法三:挖洞法

挖洞法的中心思想就是,把基准值挖掉,用一个数记录下来,然后左边找比他大的,右边找比他小的,填到洞里面,然后找到的那个就是一个新的洞

int Partion3(int *arr, int left, int right){//三数取中 -- 将有序的最坏情况变成最好情况int midi = GetMidIndex(arr, left, right);Swap(&arr[midi], &arr[left]);int tmp = arr[left];int hole = left;while (left < right){//右边找小,放到左边的坑while (arr[right] >= key && left < right){right--;}arr[hole] = arr[right];hole = right;//左边找大,放到右边的坑while (arr[left] <= key && left < right){left++;}arr[hole] = arr[left];hole = left;}arr[hole] =tmp;return hole;
}

动画如下:

快速排序的特性总结:
1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
2. 时间复杂度:O(N*logN)~O(N^2)
3. 空间复杂度:O(logN)~O(N)(栈结构消耗)
4. 稳定性:不稳定---排序主要依靠的是选基准值。如果每次选的基准值都是最大的,那就是O(n^2)
5. 数据敏感性:敏感,越无序效率越高

快排的复杂度和优化分析

复杂度:

如果每次选取的基准值都是中间值的话,那么就会形成一棵二叉树

那么时间复杂度就是O(N*logN),空间复杂度就是O(logN)

如果每次排序的话选取的基准值都是最大值的话,那么就无法形成两端区间。

那么时间复杂度就是0(N*2),空间复杂度也是O(N)

如果数据太多,会因此调用堆栈空间太多,而导致栈溢出。

优化:

1.发现时间和空间复杂度都与基准值的选取有关,那么就可以利用三数取中的方式,来尽量找到一个中间值,使其成为一棵二叉树

2.当快排分割区间分割到一定的程序的时候,试试用直接插入排序来对这段区间排序,减少递归的次数

快排的缺陷

无法解决值相等或者重复序列排序的问题

例如: 3,4,4,3,3,4,3,4,3,4

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

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

相关文章

【电子通识】TINA-TI 安装

TINA-TI是一个SPICE的模拟仿真程序&#xff0c;提供了 SPICE 所有的传统直流、瞬态和频域分析以及更多功能。 TINA 具有允许您按照希望的方式设置结果的格式。虚拟仪器允许选择输入波形、探针电路节点电压和波形。 下载链接&#xff1a;TINA-TI 模拟工具 | 德州仪器 TI.com.cn …

MAC备忘录空白解决方案

打开icloud->备忘录 取消勾选同步此MAC后再次勾选&#xff0c;然后点击完成即可。

【投稿优惠|稳定检索】2024 年信息学、网络与电子工程国际会议(INEE 2024)

2024 年信息学、网络与电子工程国际会议 2024 International Conference on Informatics, Networks, and Electronic Engineering 【1】大会信息 会议名称&#xff1a;2024 年信息学、网络与电子工程国际会议 会议简称&#xff1a;INEE 2024 大会时间&#xff1a;请查看官网 …

qt 3D编程

Qt 3D是一个用于构建交互式3D图形应用的库&#xff0c;它是Qt库的一 部分。Qt 3D提供了一组C和QMLAPI&#xff0c;帮助开发者快速构 建3D应用程序。 一、核心模块 Qt3DCore 功能&#xff1a;提供3D场景中的基本概念&#xff0c;如实体&#xff08;Entity&#xff09;、组件&…

Oracle 表空间异构传输

已经有了表空间的数据文件&#xff0c;和元数据dump文件&#xff0c;如何把这个表空间传输到异构表空间中&#xff1f; 查询异构传输平台信息&#xff1a; COLUMN PLATFORM_NAME FORMAT A40 SELECT PLATFORM_ID, PLATFORM_NAME, ENDIAN_FORMAT FROM V$TRANSPORTABLE_PLATFORM O…

数据分析Power BI设置万为单位的数据

玩过Power BI的同学都知道&#xff0c;power BI在度量值设置单位里&#xff0c;唯独没有万这个单位&#xff0c;但是我们可以自定义&#xff0c;操作过程如下&#xff1a; 1.用DAX新建单位表 单位 SELECTCOLUMNS( { ( "元", 1), ("万",10000), ("千…

初识Mysql/备份,基础指令

1&#xff0c;MySQL登录指令&#xff1a; mysql -h 127.0.0.1 -P3306 -u -p 其中&#xff0c;-h指明登录部署了mysql服务的主机 -P指明要访问的端口号&#xff0c; -u指明登录用户 -p输入密码 2&#xff0c;数据库基础 mysql&#xff1a;表示的是客户端 mysqld&…

posix接口与system V接口及其异同

POSIX接口和System V接口是用于多线程和进程间通信的两种主要编程接口。它们各自有不同的特点、功能和适用场景。以下是对这两种接口的详细介绍及其异同点。 POSIX接口 特点 标准化: POSIX&#xff08;可移植操作系统接口&#xff09;是由IEEE制定的标准&#xff0c;旨在提供统…

大数据新视界 --大数据大厂之 GraphQL 在大数据查询中的创新应用:优化数据获取效率

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【Linux】man手册安装使用

目录 man(manual,手册) 手册安装: 章节区分&#xff1a; 指令参数: 使用场景&#xff1a; 手册内容列表: 手册查看快捷键: 实例: 仍致谢:Linux常用命令大全(手册) – 真正好用的Linux命令在线查询网站 提供的命令查询 在开头先提醒一下:在 man 手册中退出的方法很简单…

给Windows系统设置代理的操作方法

一、什么是代理 网络代理是一种特殊的网络服务&#xff0c;允许一个网络终端通过这个服务与另一个网络终端进行非直接的连接&#xff0c;而提供代理服务的电脑系统或其它类型的网络终端被称为代理服务器。 代理服务器是网络信息的中转站&#xff0c;代理服务器就像是一个很大的…

map和set(c++)

前言 在前面我们在介绍二叉搜索树时我们分别实现了一个key结构和key-val结构&#xff0c;如果我们再进一步完善这棵树&#xff0c;将二叉搜索树升级为红黑树去存储key和key-val那么我们就可以得到我们今天要介绍的主角map和set。当然了标准库的实现还是有很多需要注意的地方&a…

玩机搞机基本常识-----如何在 Android 中实现默认开启某个功能 修改方法列举

我们有时候需要对安卓系统进行修改。实现其中的某些功能。让用户使用得心应手。节约时间。那么如果要实现系统中的有些功能选项开启或者关闭。就需要对系统有一定的了解。那么在 Android 中实现默认开启某个功能可以通过以下几种方式&#xff1a; 一、在应用的设置中添加选项 …

C语言练习

题目: 1.如果在int型变量的声明中为变量赋一个实数值(如3.12或4.6)的初始值会怎样呢&#xff1f;请打一段代码来看看 分析&#xff1a;……不用分析&#xff0c;开个玩笑&#xff0c;虽然很简单但是还是按照惯例水上一波数字 1.首先按照题目要求用函数类型int整型给变量赋值…

鸿蒙网络管理模块05——数据流量统计

如果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧&#xff01;扫描下方名片&#xff0c;关注公众号&#xff0c;公众号更新更快&#xff0c;同时也有更多学习资料和技术讨论群。 1、概述 HarmonyOS供了基于物理网络的数据流量统计能力&#xff0c;支持基于网卡/U…

【PS2020】Adobe Photoshop 2020 中文免费版

photoshop 2020是全球最大的图像处理软件&#xff0c;为用户提供了广泛的专业级润饰工具套件&#xff0c;集成了专为激发灵感而设计的强大编辑功能&#xff0c;帮助用户制作出满意的图片效果&#xff0c;是很多摄影师、广告师等专业人员必备的一款图像及照片后期处理大型专业软…

网络受限情况下安装openpyxl模块提示缺少Jdcal,et_xmlfile

1.工作需要处理关于Excel文件内容的东西 2.用公司提供的openpyxl模块总是提示缺少jdcal文件,因为网络管控,又没办法直接使用命令下载&#xff0c;所以网上找了资源&#xff0c;下载好后上传到个人资源里了 资源路径 openpyxl jdcal et_xmlfile 以上模块来源于&#xff1a;Py…

Java-进阶二

单列集合&#xff1a; ----------List ArrayList的源代码分析&#xff08;扩容原理&#xff09; 1 使用空参构造的集合&#xff0c;在底层创建一个容量为0的数组。2 添加第一个元素时&#xff0c;底层会扩容创建一个容量为10的数组。3 存满时会扩容1.5倍。4 如果一次添加多个…

大模型基础:基本概念、Prompt、RAG、Agent及多模态

随着大模型的迅猛发展&#xff0c;LLM 作为人工智能的核心力量&#xff0c;正以前所未有的方式重塑着我们的生活、学习和工作。无论是智能语音助手、自动驾驶汽车&#xff0c;还是智能决策系统&#xff0c;大模型都是幕后英雄&#xff0c;让这些看似不可思议的事情变为可能。本…

Redis SpringBoot项目学习

Redis 是一个高性能的key-value内存数据库。它支持常用的5种数据结构&#xff1a;String字符串、Hash哈希表、List列表、Set集合、Zset有序集合 等数据类型。 Redis它解决了2个问题&#xff1a; 第一个是&#xff1a;性能 通常数据库的读操作&#xff0c;一般都要几十毫秒&…