数据结构_排序(直接插入排序、希尔排序、起泡排序、快速排序、简单选择排序、堆排序)

本文只讲思想,无代码实现

一、直接插入排序

思想:

  • 给定一组数,将其分为有序区和无序区
  • 初始状态,有序区为这组数中的第一个数,无序区为剩下数
  • 排序时,将无序区的第一个数与有序区的数进行比较,然后插入到合适的位置
  • 重复上一步骤直到无序区没有数

举例:
12 ,15 ,9 ,20 ,6 ,31,24 (以下【】内为有序区)
初始状态【12】 ,15 ,9 ,20 ,6 ,31 ,24
第一次排序:【12,15】,9,20,6,31,24(将无序区的15与有序区的12进行比较)
第二次排序:【9,12,15】,20,6,31,24(将无序区的9与有序区的12和15比较)
第三次排序:【9,12,15,20】,6,31,24
第四次排序:【6,9,12,15,20】,31,24
第五次排序:【6,9,12,15,20,31】,24
第六次排序:【6,9,12,15,20,24,31】

二、希尔排序(不稳定)

首先区分基本有序局部有序的概念
基本有序可以理解为一组数除个别数顺序不符合外,基本符合正序或逆序
局部有序可以理解为一组数有多组有序的数组成
举例:基本有序,{1,2,8,4,5,6,7,3,9}局部有序{6,7,8,9,1,2,3,4,5}

思想:

  • 一组含有n个数的序列,一般取间隔d=n/2(向下取整),按照d将这组数分为d组子序列
  • 对这d组子序列依次进行比较(将这组数构造成一个基本有序的序列)
  • 对d按照初始方法继续分割,将这组数按减小后的间隔再分为d组子序列
  • 继续比较,直到d=1

举例:
{59,20,17,36,98,14,23,83,13,28}共10个数,取d=10/2=5
将此序列分为5组子序列(59和14,20和23,17和83,36和13,98和28)
在这里插入图片描述
然后将这五组序列,每组中的两个数进行直接插入排列,结果如下图
在这里插入图片描述
然后将d减小d=5/2向下取整=2进行分组如上图,分为两组序列(14、17、28、23、36为一组,20、13、59、83、98为一组)。这两组每组中的五个数进行直接插入排列
在这里插入图片描述
继续缩小d=1分组如上图,也就是说此时整组数被分为一组,对这组数进行直接插入排序
即如上边所介绍的排序开始,最终结果如下
在这里插入图片描述

三、起泡排序

思想:

  • 给定一组数,两两进行比较,如按从小到大顺序,如果下标小的数大于下标大的数则这两个数进行交换,按从大到小排序,下标小的数小于下标大的数则交换。

举例:
{50,13,55,97,27,38,49,65}按从小到大顺序排
第一次排序:
50和13比,交换
{13,50,55,97,27,38,49,65}
50和55比,不用交换
55和97比,不用交换
97和27比,交换
{13,50,55,27,97,38,49,65}
97和38比,交换
{13,50,55,27,38,97,49,65}
97和49比,交换
{13,50,55,27,38,49,97,65}
97个65比,交换
{13,50,55,27,38,49,65}97
第一次结束,将最大的数97排到了最右边,第二次排从剩下的数中进行排
第二次排序
{13,50,55,27,38,49,65}
13和50比,不用交换
50和55比,不用交换
55和27比,交换
{13,50,27,55,38,49,65}
55和38比,交换
{13,50,27,38,55,49,65}
55和19比,交换
{13,50,27,38,49,55,65}
55和65比,不用交换
最后将65提取出来,下一趟排序在{13,50,27,38,49,55}中排
一词类推,最终每次排序将所排序列中最大的选出来,直到最后只剩一个数也就是整个数中最小的那一个

四、快速排序

思想:

  • 给定一组数中,选择一个轴值(这里讲解选取第一个数为轴值)
  • 然后在这组数的首尾均设置两个参数指向要与轴值进行比较的数
  • 将轴值的左右分为两组数,左边的数均小于轴值,右边的数均大于轴值
  • 排序一次后再对轴值两边的数进行上述排序方法,直到每个分区只剩一个数

举例:

{23,13,49,6,31,19,28}设置轴值为23(加粗),并设置i和j分别指向左右要与轴值进行比较的数
在这里插入图片描述
①i指向23,j指向28,23<28不交换
②j前移指向19,23>19,交换位置,i右移,j所指的位置不变
③13<23不交换,i右移
④49>23,交换位置,j左移
⑤23<31不交换,j左移
⑥23>6,交换,i右移,此时i和j均指向23即轴值,第一次排序结束
第二次对23左右两边进行上述同样方法排序
在这里插入图片描述
最终排好结果如上图

五、简单选择排序

思想:

  • 将一组数分为有序区和无序区,初始有序区没有数,无序区包含整组数
  • 然后在无序区中挑出最小数与无序区中的第一个数进行交换,并将其加入有序区
  • 重复上一步骤直至无序区只剩一个数

举例:
{49,18,65,97,76,13,38}【】内为有序区
初始【】49,18,65,97,76,13,38
第一次【13】49,18,65,97,76,38
第二次【13,18】49,65,97,76,38
第三次【13,18,38】49,65,97,76
第四次【13,18,38,49】65,97,76
第五次【13,18,38,49,65】97,76
第六次【13,18,38,49,65,76】97

六、堆排序

首先明确的概念
堆是指一个完全二叉树,每个结点小于等于其孩子结点(小根堆)或大于等于其孩子结点(大根堆)

对于一个不是堆的完全二叉树,构造堆的方法为,从最后一个分支结点开始进行筛选。具体可参考此博文堆排序及其分析

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内部排序合集(插入、希尔、起泡、快速、选择、堆、归并和基数排序) 这是我在我们期末的时候写的一些内部排序的例子。因为我们的数据结构考试的范围就限定在内部排序上,所以我没有什么办法,只好对自己埋头苦干就行内部排序的编程了。有些内部排序的例子很是好理解,我们可以通过一些图示来很好地了解到这些排序的过程,但是这些程序的代码可能不是那么好写。而另外一些程序的思想既难以理解,也难于编码。着实地伤透了我的脑筋。下面就将我的程序的主框架代码展示给大家看看。注意,在这里我怎样也不好实现2-路插入排序,因为它这样的排序方法运用在顺序存储结构下不好,在判断数组越界的时候这样的复杂性使我最终放弃了这种方法。要不还不如使用其余的排序呢。 毕竟了解内部排序是一件好事,以后在看一些内部排序的时候也不至于摸不着头脑。最近我看到了一本有关介绍用C++来编辑游戏的书,它就以STL为例,讲解了STL内部实现的机理。 // 头文件 #include using namespace std; #include "InsertionSort.h" #include "Shell'sSort.h" #include "QuickSort.h" #include "SelectionSort.h" #include "MergingSort.h" #include "RadixSort.h" // 定义的宏 #define LENGTH 10 // 主函数 int main( int argc, char** argv ) { // 定义一个顺序表 SqList a; int objArray[LENGTH] = { 278, 109, 63, 930, 589, 184, 505, 269, 8, 83 }; a.length = LENGTH; int i; for ( i = 1; i < a.length + 1; i++ )// 需要将0号位设为监视哨 { a.r[i].key = objArray[i-1]; a.r[i].otherinfo = '\0'; } // 直接插入排序 //InsertSort( a ); // 折半插入排序 //BInsertSort( a ); // 2-路插入排序 //BinRouteInsertSort( a, 2 );// 这个算法有问题 // 希尔排序 /* { int dlta2[3] = { 3, 2, 1 }; ShellSort( a, dlta2, 3 ); } */ // 起泡排序 //BubbleSort( a ); // 快速排序 //QuickSort( a, 1, LENGTH ); // 选择排序 //SelectSort( a ); // 堆排序 //HeapSort( a ); // 归并排序 //MergeSort( a ); // 基数排序 { SLList b; int i; b.keynum = 3, b.recnum = LENGTH;// 对3位整数进行基数排序 for ( i = 1; i <= b.recnum; i++ ) { b.r[i].keys[0] = objArray[i-1] % 10;// 个位 b.r[i].keys[1] = objArray[i-1] % 100 / 10;// 十位 b.r[i].keys[2] = objArray[i-1] / 100;// 百位 } RadixSort( b ); } // 显示排序后的数组 for ( i = 1; i < a.length + 1; i++ )// 需要将0号位设为监视哨 cout<<a.r[i].key<<' '; cout<<'\n'; return 0; } 要想得到这些排序的具体实现,那么就下载我的代码吧。最近我的积分由于下载一些Boost的资料而变为0了。所以需要的朋友一定要支持一下哦。(使用VS2005开发,算法都是C风格的,可以直接使用。) 我最新的动态:最近在研究DirectInput,希望能够在几天后写一篇技术文章,分享一些我的经验。
以下是六种排序算法的比较: 1. 插入排序 插入排序是一种简单直观的排序算法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增加1的有序表。插入排序的时间复杂度为O(n^2),适用于数据量较小的排序。 2. 希尔排序 希尔排序是一种改进的插入排序,它的基本思想是将待排序的数组按照一定的间隔分成若干个子序列,对每个子序列进行插入排序,然后逐步缩小间隔,直到间隔为1,最后对整个数组进行插入排序希尔排序的时间复杂度为O(nlogn),适用于数据量较大的排序。 3. 选择排序 选择排序是一种简单直观的排序算法,它的基本思想是每次从待排序的数组中选择最小的元素,放到已排序的数组的末尾,直到所有元素都排序完毕。选择排序的时间复杂度为O(n^2),适用于数据量较小的排序。 4. 冒泡排序 冒泡排序是一种简单直观的排序算法,它的基本思想是每次比较相邻的两个元素,如果它们的顺序错误就交换它们的位置,直到所有元素都排序完毕。冒泡排序的时间复杂度为O(n^2),适用于数据量较小的排序。 5. 堆排序 堆排序是一种树形选择排序,它的基本思想是将待排序的数组构建成一个二叉堆,然后依次将堆顶元素与堆底元素交换,再重新调整堆,直到所有元素都排序完毕。堆排序的时间复杂度为O(nlogn),适用于数据量较大的排序。 6. 快速排序 快速排序是一种分治的排序算法,它的基本思想是选择一个基准元素,将数组分成两个子数组,小于基准元素的放在左边,大于基准元素的放在右边,然后递归地对子数组进行排序快速排序的时间复杂度为O(nlogn),是一种效率比较高的排序算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值