排序算法之选择排序

罗朝辉(http://www.cppblog.com/kesalin)

转载请注明出处

排序是数据处理中经常使用的一种重要运算,在计算机及其应用系统中,花费在排序上的时间在系统运行时间中占有很大比重,其重要性无需多言。下文将介绍常用的如下排序方法,对它们进行简单的分析和比较,并提供 C 语言实现。

所谓排序,就是要将一堆记录,使之按关键字递增(或递减)次序排列起来。根据排序所采用的策略,可以分为如下五种:

3、选择排序(直接选择排序、堆排序)

4、归并排序;

5、桶排序(桶排序,基数排序);

---------------------------------------------------------------------------------

前面讲了插入,交换排序,下面接着来讲选择排序。

选择排序(Selection Sort)的基本思想是:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子文件的最后,直到全部记录排序完毕。

常用的选择排序方法有直接选择排序和堆排序。

直接选择排序

基本思想:将待排序记录分成有序区和无序区,初始状态下有序区位空,无序区为整个待排序记录。每一趟选择排序就是在无序区中选择最小(或最大)的记录,插入到有序区的最后。如此循环直到无序区为空,完成排序。

代码实现

//直接选择排序//voidselect_sort(int*array,intlength)

{

assert(array&&length>=0);inti, j, k, temp;for(i=1; i

k=i;for(j=i+1; j

k=j;

}

}if(k!=i) {

temp=array[i];

array[i]=array[k];

array[k]=temp;

}

}

}

时间复杂度分析:

无论待排序记录的初始状态如何,在第 i 趟排序中选出最小关键字的记录,需做 n - i 次比较,因此,总的比较次数为: n * (n - 1) / 2 = 0(n ^ 2),当待排序记录的初始状态为正序时,移动次数为 0;当初始状态为反序时,每趟排序均要执行交换操作,总的移动次数取最大值 3 * (n-1)。所以,直接选择排序的平均时间复杂度为 0(n ^ 2)。

空间复杂度:

很明显,0(1)。

补充:

直接选择排序是一个就地排序,且是非稳定排序。

堆排序

堆的定义:满足如下约束的 n 个关键字序列 Kl,K2,…,Kn称为堆,1 ≤ i ≤n/2,

(1) ki≤ K2i且 ki≤ K2i+1 (小根堆)   或

(2) Ki≥ K2i且 ki≥ K2i+1 (大根堆)

从定义来看,堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在的话)结点的关键字。堆排序就是充分利用堆这种堆顶记录要么是最大的要么是最小的有序性质,每次在堆中选择最大或最小关键字完成排序。堆排序也是选择排序的一种,它比直接选择排序平均效率要高,因为直接选择排序,每次比较之后并没有对比较结果进行保存,导致可能存在重复的比较,而堆则利用其堆性质将比较结果保存在堆中了(非叶子节点的左边孩子一定不大于或不小于比右边的孩子)。

堆排序的关键就在于将待排序记录的建立成堆,建好堆之后,将无序区的堆顶记录(总是无序区的最大或最小)和无序区最后一个记录交换,交换之后,无序区的最后一个记录变成有序区的第一个记录,而无序区新的的堆顶记录不一定满足堆性质了,因而需要将无序区调整而堆。如此循环,直到无序区为空,结束排序。

所以堆排序的主要步骤就分三步:

1,建立初始堆;

2,将无序的堆顶记录与最后一个记录交换,缩小无序区;

3,将交换之后的无序区调整为堆,重复步骤 2。

代码实现:

//筛选法调整堆,除 [low] 之外,[low] 的两个孩子均已是大根堆voidadjust_heap(int*heap,intlow,inthigh)

{

assert(heap);#if1//循环实现inti=low;intj=2*i;inttemp=heap[i];while(j<=high) {//若有两个孩子,j 为孩子中大的那个的下标if(j

j=j+1;

}//已是堆if(temp>=heap[j]) {break;

}//继续筛选else{

heap[i]=heap[j];

i=j;

j=2*i;

}

}

heap[i]=temp;#else//递归实现inti=low;intj=2*i;inttemp=heap[i];if(j>=high) {return;

}//若有两个孩子,j 为孩子中大的那个的下标if(jheap[j]) {

j=j+1;

}//已经为堆,无需调整if(heap[low]>=heap[j]) {return;

}

heap[i]=heap[j];

heap[j]=temp;//调整之后,[j, high] 可能不满足堆了,需继续调整adjust_heap(heap, j, high);#endif}//只有一个结点的树是堆,而在完全二叉树中,所有序号 i > n/2 的结点都是叶子,//因此以这些结点为根的子树均已是堆。这样,我们只需依次将以序号为//n/2, n/2 - 1, …, 0 的结点作为根的子树都调整为堆即可。voidbuild_heap(int*heap,intlength)

{

assert(heap&&length>=0);inti;for(i=length/2; i>=0;--i) {

adjust_heap(heap, i, length-1);

}

}//堆排序//voidheap_sort(int*array,intlength)

{

assert(array&&length>=0);if(length<=1) {return;

}inti, temp;//将 [0, length - 1] 建成初始堆build_heap(array, length);//对当前无序区 [0, i - 1] 进行堆排序,共做 length - 1 趟。for(i=length-1; i>0;--i) {//将堆顶和堆中最后一个记录交换temp=array[0];

array[0]=array[i];

array[i]=temp;//将 [0, i - 1] 重新调整为堆,仅有 [0] 可能违反堆性质adjust_heap(array,0, i-1);

}

}

时间复杂度分析:

堆排序算法c语言筛选法,【排序】排序算法之选择排序相关推荐

  1. C语言——十四种内部排序算法【直接插入排序-冒泡排序-选择排序-插入排序-希尔排序-归并排序-快速排序-堆排序-折半插入排序-二分查找-路插入排序-表插入排序-简单选择排序-直接选择排序-树形选择】

    目录: 一:插入排序 A:直接插入排序 1.定义: 2.算法演示 实例1: 3.基本思想 4.排序流程图 实例1: B:希尔排序 1.定义: 2.算法演示 实例2: C:其他插入排序 a:折半插入排序 ...

  2. 数据结构(八):排序 | 插入排序 | 希尔排序 | 冒泡排序 | 快速排序 | 简单选择排序 | 堆排序 | 归并排序 | 基数排序 | 外部排序 | 败者树 | 置换-选择排序 | 最佳归并树

    文章目录 第八章 排序 一.排序的基本概念 (一)什么是排序 (二)排序的应用 (三)排序算法的评价指标 (四)排序算法的分类 (五)总结 二.插入排序 (一)算法思想 (二)算法实现 (三)算法效率 ...

  3. 张仰彪第二排序法_十大排序之冒泡和选择排序

    你好,我是goldsunC 让我们一起进步吧! 排序 所谓排序,就是指将一组数据,按照特定规则调换位置,使数据具有某种顺序关系(递增或递减).在排序过程中,数据的移动方式可分为直接移动和逻辑移动两种. ...

  4. C语言排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)

    参考:C语言五大排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)动态演示 作者:一只青木呀 发布时间: 2020-09-09 20:18:43 网址:https://blog.csdn.net/ ...

  5. C语言版--单链表排序,冒泡排序,选择排序,插入排序,快速排序,应有尽有,保证看懂,没有bug!交换节点版本!

    一.废话不多说,直接上代码.如果想看双向循环链表的朋友,可以在我的博客里找. 你好 #include <stdio.h> #include <stdlib.h>typedef ...

  6. 【经典算法学习-排序篇】直接选择排序

    一.选择排序 1.基本概念和介绍 选择排序的核心思想是:每一趟从无序区中选出关键字最小(或最大)的元素,按顺序放在有序区的最后(生成新的有序区,无序区元素个数减1),直到全部排完为止. 换句话说就是: ...

  7. java 排序原理_简单选择排序算法原理及java实现(超详细)

    简单选择排序的原理 简单选择排序的原理非常简单,即在待排序的数列中寻找最大(或者最小)的一个数,与第 1 个元素进行交换,接着在剩余的待排序的数列中继续找最大(最小)的一个数,与第 2 个元素交换.以 ...

  8. 《大话数据结构》第9章 排序 9.4 简单选择排序

    9.4.1 简单选择排序算法 爱炒股票短线的人,总是喜欢不断的买进卖出,想通过价差来实现盈利.但通常这种频繁操作的人,即使失误不多,也会因为操作的手续费和印花税过高而获利很少.还有一种做股票的人,他们 ...

  9. 排序:冒泡排序与选择排序

    冒泡排序 冒泡排序(英语:Bubble Sort)是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.遍历数列的工作是重复地进行直到没有再需要交换,也 ...

最新文章

  1. 一个精简的开源点云库
  2. react中component存在性能问题
  3. JSTL笔记—c标签
  4. 把Liststring集合,编程string,并以“,”号分割
  5. C++类模板实例化条件
  6. 【POJ - 2663】Tri Tiling (简单dp)
  7. 使用matlab画半透明椭圆
  8. LeetCode 1620. 网络信号最好的坐标
  9. 译:重置/还原Windows IIs设置为默认设置
  10. 三、Tableau筛选器的使用
  11. erlang开发工具之intellij idea基本使用
  12. 看法:2017会带给我们的文化和方法
  13. 10大计算机经典算法
  14. 从亏损19亿到盈利6亿,恺英网络做对了什么?
  15. 本周(12.23-12.29)半价电子书 1
  16. favicon.ico图标制作
  17. FITC-Dextran,Dextran-FITC,右旋糖酐荧光素,一种被标记的多糖
  18. matlab bfs函数,Matlab脚本和函数
  19. Rasa课程、Rasa培训、Rasa面试、Rasa实战系列之RegexFeaturizer
  20. Mysql8.0和Mysql5.0访问jdbc连接

热门文章

  1. 一篇漫画,看懂云计算!
  2. 谈谈前后端分离实践中如何提升RESTful API开发效率
  3. 干掉 Swagger,试试这个!
  4. MySQL:为什么用limit时,offset很大会影响性能
  5. 为什么 Java 中 2*(i*i) 比 2*i*i 更快?
  6. OS- -计算机硬件简介
  7. 计算机基础- -计算机为什么要使用二进制
  8. Vimeo针对GIF性能和质量的改进
  9. 大牛书单 | 读懂5G,改变社会
  10. NodeJS开发c++扩展模块