浅谈数据结构-选择排序(简单、堆排序)

选择排序:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止。

选择排序正如定义所讲,在数组查询出最小值,然后放在此次循环开始位置(前一次循环已经获取比它更小的值放在前面)。

简单选择排序就是单纯的从数组中一次一次循环获取到最小值,放到循环位置。而堆排序正如名字,是从一个堆中选择,然后放在堆的循环开始位置,所以重点就是如何争取获取堆(分组)。

一、简单选择排序

1、算法思想

正如图上所示,每次选择最小值,然后放在本次循环的开始位置。

2、代码

//选择排序
void SortAlgorithm::SelectSort(pSqlList pList)
{int i,j,min;printf("开始验证选择排序");//选择排序和低级冒泡排序很像,关键就是在比较时,低级冒泡进行数据交换,而选择排序进行记录,最后只交换一次for (i =0;i<pList->length;i++){min = i;for(j = pList->length-1;j>=i;j--){//注意数组坐标,千万别溢出if (pList->SqlArray[min] > pList->SqlArray[j]){min = j;}}//最后进行交换,先选择最小的,最后一次交换
        swap(pList,i,min);PrintSqlList(pList);}}

简单选择排序算法海华丝比较简单,关键点就是遍历寻找最小记录,然后入循环开始位置进行交换。

二、堆排序

1、堆排序概念

堆排序是首先引入完全二叉树的概念,就是构建完全二叉树,前提是完全二叉树是有特点的,也就是大根堆和小根堆。

上图是完全二叉树,在完全二叉树中有几个性质:

设当前元素在数组中以R[i]表示,那么,
(1) 它的左孩子结点是:R[2*i+1];
(2) 它的右孩子结点是:R[2*i+2];
(3) 它的父结点是:R[(i-1)/2];

(4) R[i] <= R[2*i+1] 且 R[i] <= R[2i+2]。

大根堆:每个结点的关键字都不小于其孩子结点的关键字。

小根堆:每个结点的关键字都不大于其孩子结点的关键字。

2、算法思想

(1)根据初始数组去构造初始堆,默认是大根堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大)。

(2)每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆。

上述算法是个循环操作,先构建,然后交换输出,最后调整余下的为大根堆,其实就是寻找最大值,其实只需要左右两个结点,那个比较大,就获取那个,所以调整堆排序也是比较简单,就是比较左右结点,获取最大值

第一步:构建大根堆

第二步、输出、调整

3、代码

////堆排序
void SortAlgorithm::HeapSort(pSqlList pList)
{//循环构建堆for (int i = pList->length/2;i>0;i--){AdjustHeap(pList,i,pList->length-1);}PrintSqlList(pList);for (int i = pList->length-1;i>1;i--){//循环输出根节点,同时再次调整为大根堆swap(pList,1,i);     //根节点位于最前面,也就是1,这样就将1最大值,放在数组后面了AdjustHeap(pList,1,i-1);PrintSqlList(pList);}
}
inline void SortAlgorithm::AdjustHeap(pSqlList pList,int start,int length)
{int temp  = pList->SqlArray[start];  //这是分支节点,然后比较它的分支节点,也就是2ifor (int i = 2*start;i<length;i = i*2){//获取左右结点中比较大的值的坐标if (i<length && pList->SqlArray[i] < pList->SqlArray[i+1]){i++;}//如果根节点本来就大,无序调整if (temp > pList->SqlArray[i]){break;}//交换值,将左右结点大值放在根节点pList->SqlArray[start] = pList->SqlArray[i];start = i;}//将开始需要比较的值,放在最后交换出的位置上pList->SqlArray[start] = temp;}

4、代码分析

程序中一开始构建,调整大根堆,最大值是length/2,因为从完全二叉树的概念上分析:

image

在上图中大根堆的建立,就是调整前四个元素的位置,就是放再分支节点上还是叶子结点上,所以只要输入4即可。

image

一开始大根堆,发现是90在最前面。

首先,将位于第一位(根节点树最大),然后和最后一位交换,然后调整前8位(第九位已经是最大了)。

然后,再讲获取到的80,和最后一位(第九位,第十已经不需交换),然后调整前7位,当然都是从1开始了。

最后经过一次次循环调整,完成算法的排序。

其中关键的思想是获取调整堆排序,比如一开始90和20交换后,20位于第一位置;此时20和左右结点中的较大值80交换,关键是后续继续拿20和后面左右结点比较,直到break,也就是找到比它小的,跳出,然后赋值。

三、性能分析

1、简单选择排序

从简单选择排序的过程来看,它最大的特点就是交换移动数据次数相当少,这样也就节约了相应的时间。分析它的时间复杂度,无论最好最差的情况,其比较次数都是一样多,第i趟排序需要进行n-i次关键字的比较,此时需要n-1 +...+1 = n(n - 1)/2次。而对于交换次数而言,当最好的时候,交换次数为0,最差的时候,也就初始降序时,交换次数为n-1次。总的时间复杂度依然为O(n2)。

    尽管简单选择排序与冒泡排序同为O(n2),但简单选择排序的性能上还是要优于冒泡排序的。

2、堆排序

堆排序是一种不稳定的排序方法。

因为在堆的调整过程中,关键字进行比较和交换所走的是该结点到叶子结点的一条路径。

在程序运行时主要消耗在初始化构建堆和重建堆的反复刷选上。在初始化构建堆时,是从非终结点开始,其实比较两次,本来时n/2,这样最多对n/2进行两次比较工作,所以初始化构建大根堆是O(n)。

在调整构建堆时,第i次构建树logI(根据完全二叉树性质),需要遍历N-1记录,所以时间复杂度是O(nlogn)

转载于:https://www.cnblogs.com/polly333/p/4816828.html

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

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

相关文章

php 去掉多维数组的键名,去除多维数组的最外层key 保留值

如果你是要将JSON转成PHP数组&#xff0c;方法如下首先&#xff0c;你这个数据格式是JSON的&#xff0c;要先转成PHP数组。$a json_decode($a, TRUE);json_decode第二个参数为TRUE表示保留键名&#xff0c;否则JSON转PHP数组之后&#xff0c;PHP数组的键名会重新排序。然后将你…

安装php7的mysql扩展,php7安装mysql扩展的方法是什么

php7安装mysql扩展的方法&#xff1a;1、下载mysql扩展并解压&#xff1b;2、使用phpize工具初始化并进行configure&#xff1b;3、执行【make && make install】命令&#xff1b;4、编辑php.ini文件&#xff1b;5、重启服务。本文环境&#xff1a;windows10系统、php7…

什么是简单的分析SQL注入漏洞

如今非常多人在入侵的过程中基本都是通过SQL注入来完毕的&#xff0c;可是有多少人知道为什么会有这种注入漏洞呢&#xff1f;有的会随口说着对于字符的过滤不严造成的。可是事实是这样吗&#xff1f;我们学这些。不仅要知其然。更要知其所以然&#xff01;理论联系实际&#x…

python发布服务,Python服务发现:在本地n上发布服务

在本地网络上执行服务通告/发现的一个简单方法是广播UDP包。常数&#xff1a;PORT 50000MAGIC "fna349fn" #to make sure we dont confuse or get confused by other programs公告&#xff1a;from time import sleepfrom socket import socket, AF_INET, SOCK_DGR…

[codevs1262] 不要把球传我 数论+组合数学

没什么好说的&#xff0c;很容易分析出递推公式f[n](n-2)*(n-1)*(n-3) div 6; 代码 beginreadln(n);     writeln((n-2)*(n-1)*(n-3) div 6);end. 巨短&#xff0c;就是这样233&#xff08;&#xff09; 我不会告诉你这一张是…

php可以用水晶报表吗,什么是水晶报表与水晶报表功能分析

水晶报表水晶报表(Crystal Report)是业内最专业、功能最强的报表系统&#xff0c;它除了强大的报表功能外&#xff0c;最大的优势是实现了与绝大多数流行开发工具的集成和接口。在VS.Net平台做过报表开发的程序员&#xff0c;一定都对水晶报表强大、高效、集成等特性留下了深刻…

大数据笔记11:MapReduce的运行流程

1.基本概念 &#xff08;1&#xff09;Job & Task &#xff08;2&#xff09;JobTracker &#xff08;3&#xff09;TaskTracker转载于:https://www.cnblogs.com/hebao0514/p/4825280.html

php 表格分页代码,[Php]分页及表格样式

writer:web wu 2007/11/29这个分页代码比较简单一些.操作用户列表include "conn.php"; //连接数据库文件mysql_select_db("admin"); //打开数据表$ssqlmysql_query("select count(*) as amcount from alluser",$con); //统计记录数if($my…

iPhone屏幕尺寸、分辨率及适配

目录(?)[-] iPhone尺寸规格单位inch英吋iPhone手机宽高屏幕尺寸像素密度PPI缩放因子scale factor between logic point and device pixel1Scale起源 2UIScreenscale 3UIScreennativeScale 4机型判别Resolutions Rendering2x3x以及高倍图适配12x 23x 3高倍图文件…

oracle中的and用法,Oracle bitand( )函数简介

Oracle bitand( )函数在Oracle数据库中是很常见的&#xff0c;下面就为您详细介绍Oracle bitand( )函数的用法&#xff0c;如果您感兴趣的话&#xff0c;不妨一看。Oracle bitand( )函数&#xff1a;返回两个数值型数值在按位进行AND 运算后的结果。语法BITAND(nExpression1, n…

Nagios显示器mysql定从库: libmysqlclient.so.18: cannot open shared object file: No such

做mysql的slave时间监控&#xff0c;必须check_mysql文字&#xff0c;check当误差&#xff1a;error while loading shared libraries: libmysqlclient.so.18: cannot open shared object file: No such file or directory1&#xff0c;错误信息例如以下&#xff1a;[rootslave…

oracle包如何进入编辑,修改 Oracle 的process和Session

1.process 和session的概念:process:这个参数限制了能够连接到SGA的操作系统进程数(或者是Windows 系统中的线程数),这个总数必须足够大,从而能够适用于后台进程与所有的专用服务器进程,此外,共享服务器进程与调度进程的数目也被计算在内.此外,共享 服务器进程与调度进程的数目…

Head First Python学习笔记4——处理数据

有这么几组数据需要你处理&#xff1a; James  2-34,3:21,2.34,2.45,3.01,2:01,2:01,3:10,2-22 Julia   2.59,2.11,2:11,2:23,3-10,2-23,3:10,3.21,3-21 Mikey  2:22,3.01,3:01,3.02,3:02,3.02,3:22,2.49,2:38 Sarah  2:58,2.58,2:39,2-25,2-55,2:54,2.18,2:55,2:55 这…

oracle ora 00910,NVARCHAR2字段超长问题:ORA-00910: specified length too long for its datatype

NVARCHAR2字段超长问题&#xff1a;ORA-00910: specified length too long for its datatype前几天在IMP的时候遇到了个问题&#xff1a;IMP-00017: following statement failed with ORACLE error 910:"CREATE TABLE "T_CSL_DYNAITEMDATAENTRY" ("FID&quo…

Swift - 触摸事件(点击,移动,抬起等)说明及用例

在iOS开发中&#xff0c;UIGestureRecognizer可以方便的响应处理手势事件。 而如果要想更精细的处理&#xff0c;我们还需要借助touchesBegan&#xff0c;touchesMoved&#xff0c;touchesEnded等触摸方法。这些方法 都是UIResponder中的方法。视图控制器和视图类&#xff0c;都…

鼠标移动响应php程序,jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】...

本文实例讲述了jQuery实现的响应鼠标移动方向插件用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;HTML代码如下&#xff1a;www.jb51.net jQuery响应鼠标移动*{margin:0;padding:0;}ul,li{list-style:none;}div{font-family:"Microsoft YaHei";}html,bo…

读《大道至简—是懒人造就了方法 》有感

读了大道至简第一章编程的精义之后&#xff0c;我觉得感触颇深&#xff0c;于是乎我又读了第二章是懒人造就了方法 &#xff0c;之后果然没有让我失望&#xff0c;第二章写的也是非常的好&#xff0c;非常的吸引我。 第二章的开头便引用了李冰凿山的故事&#xff0c;在战国时代…

《大道至简》第二篇读后感

今天把周爱民大道至简的第二章关于是懒人造就了方法读了几遍&#xff0c;作者通过战国时李冰凿山与愚公移山的比较来阐述懒人早就方法主题&#xff0c;以前听历史老师讲课的时候正是因为懒人才会有那么多可以节省人们力气和时间的发明&#xff0c;但懒人并不是真的懒&#xff0…

oracle备份磁盘头,ASM 磁盘头信息备份

ASM磁盘头信息保存在每个磁盘的前4K里面&#xff0c;这个信息的备份对于ASM的恢复非常重要&#xff0c;有下面的几种方法1.直接做dd来备份磁盘的前4K&#xff0c;磁盘头信息丢失时&#xff0c;dd回来 备份&#xff1a;dd if/dev/raw/raw1 of/gyj/asmheader.dd bs4096 coun…

var s=+newDate();的用法,表示对应的时间截

var snewDate(); var snewDate(); 解释如下:是不存在的; new Date()是一个东西; 相当于.valueOf(); 看到回复补充一下.getTime()这个也是得到毫秒数 //4个结果一样返回当前时间的毫秒数alert(new Date());alert(new Date);var snew Date();alert(s.valueOf()); alert(s.getTime…