选择排序

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

3. 堆排序算法 假设当前要进行筛选的结点编号为k 假设当前要进行筛选的结点编号为k,堆中 最后一个结点的编号为m a[k+1]至a[m]之间 最后一个结点的编号为m,且a[k+1]至a[m]之间 的结点都已经满足堆的条件, 的结点都已经满足堆的条件,则调整过程可以描述 为: (1) 设置两个指针i和j: 设置两个指针i i指向当前(要筛选)的结点:i=k; 指向当前(要筛选)的结点: j指向当前结点的左孩子结点:j=2*i; 指向当前结点的左孩子结点: (2) 比较当前结点的左右孩子的关键字值, 比较当前结点的左右孩子的关键字值, 并用j指向关键字值较大的孩子结点。 并用j指向关键字值较大的孩子结点。 if (j<m && a[j].key<a[j+1]).key ) j++; (3) 用当前结点的关键字与j所指向的结点 用当前结点的关键字与j 关键字值进行比较,根据比较结果采取相应的操作, 关键字值进行比较,根据比较结果采取相应的操作, 即结束筛选或交换结点内容并继续进行筛选。 即结束筛选或交换结点内容并继续进行筛选。实现 这个操作的语句为: 这个操作的语句为:
简单选择排序算法简单,但是速度较慢,并且 简单选择排序算法简单,但是速度较慢,
是一种不稳定的排序方法. 是一种不稳定的排序方法.,但在排序过程中只需要一
个用来交换记录的暂存单元。 个用来交换记录的暂存单元。
8.4.2 堆排序 1. 堆排序的基本思想 堆排序是另一种基于选择的排序方法。下面我 堆排序是另一种基于选择的排序方法。 们先介绍一下什么是堆? 们先介绍一下什么是堆?然后再介绍如何利用堆进行 排序。 排序。 堆定义: 个元素组成的序列{k 堆定义:由n个元素组成的序列{k1, k2,……,kn-1,kn},当且仅当满足如下关系时,称 ……, 当且仅当满足如下关系时, 之为堆 之为堆。
在堆排序中,除建初堆以外, 在堆排序中,除建初堆以外,其余调整堆的过 程最多需要比较树深次,因此,与简单选择排序相比 程最多需要比较树深次,因此, 时间效率提高了很多;另外,不管原始记录如何排列, 时间效率提高了很多;另外,不管原始记录如何排列, 堆排序的比较次数变化不大,所以说, 堆排序的比较次数变化不大,所以说,堆排序对原始 记录的排列状态并不敏感。 记录的排列状态并不敏感。 在堆排序算法中只需要一个暂存被筛选记录 内容的单元和两个简单变量h 内容的单元和两个简单变量h和i,所以堆排序是一种 速度快且省空间的排序方法。堆排序是一种不稳定的。 速度快且省空间的排序方法。堆排序是一种不稳定的。
if (a[i].key>a[j].key) break; (a[i].key>a[j]. break; //结束筛选操作 //结束筛选操作 else { temp=a[i]; temp=a[i]; a[i]=a[j]; a[i]=a[j]; a[j]=temp; a[j]=temp; //交换结点内容 //交换结点内容 i=j;j=2*i; i=j;j=2*i; //准备继续筛选 //准备继续筛选 } 可以将交换改进为: 可以将交换改进为: if (a[i].key>a[j].key) break; (a[i].key>a[j]. break; else { a[i]=a[j]; i=j; j=2*i; } a[i]=a[j]; i=j; j=2*i;
例如序列(47,35,27,26,18, 例如序列(47,35,27,26,18,7,13,19)满 13,19) 足:
若将堆看成是一棵以k 为根的完全二叉树, 若将堆看成是一棵以 1为根的完全二叉树,则这 棵完全二叉树中的每个非终端结点的值均不大于( 棵完全二叉树中的每个非终端结点的值均不大于(或 不小于)其左、右孩子结点的值。由此可以看出, 不小于)其左、右孩子结点的值。由此可以看出,若 一棵完全二叉树是堆,则根结点一定是这n个结点中的 一棵完全二叉树是堆,则根结点一定是这 个结点中的 最小者或最大者。下面给出两个堆的示例。 最小者或最大者。下面给出两个堆的示例。
(2) 设置一个整型变量index,用于记录在一 设置一个整型变量index, 趟的比较过程中,当前关键字值最小的记录位置。 趟的比较过程中,当前关键字值最小的记录位置。开 始将它设定为当前无序区域的第一个位置, 始将它设定为当前无序区域的第一个位置,即假设这 个位置的关键字最小, 个位置的关键字最小,然后用它与无序区域中其他记 录进行比较,若发现有比它的关键字还小的记录, 录进行比较,若发现有比它的关键字还小的记录,就 index改为这个新的最小记录位置 改为这个新的最小记录位置, 将index改为这个新的最小记录位置,随后再用 a[index].key 与后面的记录进行比较,并根据比较结 与后面的记录进行比较, 随时修改index的值 一趟结束后index中保留的 的值, 果,随时修改index的值,一趟结束后index中保留的 就是本趟选择的关键字最小的记录位置。 就是本趟选择的关键字最小的记录位置。 (3) 将index位置的记录交换到无序区域的第 index位置的记录交换到无序区域的第 一个位置,使得有序区域扩展了一个记录, 一个位置,使得有序区域扩展了一个记录,而无序区 域减少了一个记录。 域减少了一个记录。 (2)、(3), 不断重复 (2)、(3),直到无序区域剩下一个 记录为止。 记录为止。此时所有的记录已经按关键字从小到大的 顺序排列就位。 顺序排列就位。
8.4 选择排序
选择排序是指在排序过程序中,依次从待排 选择排序是指在排序过程序中, 序的记录序列中选择出关键字值最小的记录、 序的记录序列中选择出关键字值最小的记录、关键字 值次小的记录、……,并分别将它们定位到序列左侧 值次小的记录、……, 的第1个位置、第二个位置、……, 的第1个位置、第二个位置、……,最后剩下一个关键 字值最大的记录位于序列的最后一个位置, 字值最大的记录位于序列的最后一个位置,从而使待 排序的记录序列成为按关键字值由小到大排列的的有 序序列。 序序列。
完整算法: 完整算法: void selecsort ( DataType a, int n) { for( i=1; i<n; i++) i=1 i<n; //对n个记录进行n-1趟的简单选择排序 //对 个记录进行n { index=i; index=i; //初始化第i趟简单选择排序的最小记录指针 //初始化第 初始化第i for (j=i+1;j<=n;j++) (j=i+1 j<=n; //搜索关键字最小的记录位置 //搜索关键字最小的记录位置 if (a[j].key<a[i].key) index=j; (a[j].key<a[i]. index=j; if (index!=i) { temp=a[i]; temp=a[i]; a[i]=a[index]; a[i]=a[index]; a[index]=temp; a[index]=temp; } } }
堆排序的筛选算法: 堆排序的筛选算法: void sift (DataType a,int k,int m) { i=k;;j=2*i;temp=a[i]; i=k;;j=2*i;temp=a[i]; while (j<=m) // { if ( j < m && a[j].key < a[j+1].key ) j++; if ( a[i].key > a[j] .key) break; break; else { a[i]=a[j] ;i=j;j=2*i; } i=j;j=2*i; } a[i] = temp; temp; }
8.4.1 简单选择排序 1. 简单选择排序的基本思想 简单选择排序的基本思想是:每一趟在n简单选择排序的基本思想是:每一趟在n i+1(i=1,2,3,...,n-1)个记录中选取关键字最小的记录 i+1(i=1,2,3,...,n-1)个记录中选取关键字最小的记录 作为有序序列中的第i个记录。它的具体实现过程为: 作为有序序列中的第i个记录。它的具体实现过程为: (1) 将整个记录序列划分为有序区域和无序 区域,有序区域位于最左端,无序区域位于右端, 区域,有序区域位于最左端,无序区域位于右端,初 始状态有序区域为空,无序区域含有待排序的所有n个 始状态有序区域为空,无序区域含有待排序的所有n 记录。 记录。
堆排序完整的算法。 堆排序完整的算法。 void heapsort (DataType a, int n) { h=n/2 ; //最后一个非终端结点 //最后一个非终端结点 的编号 for ( i=h ; i>=1; i--) i--) //初建堆。从最后一个非终端结点至根结点 //初建堆 初建堆。 sift ( a, i, n ) ; for ( i=n ; i>1 ; i-- ) i-//重复执行移走堆顶结点及重建堆的操作 //重复执行移走堆顶结点及重建堆的操作 { temp=a[1] ; a[1]=a[i]; a[i]=temp ; sift ( a , 1 , i-1 ); i} }
Fra Baidu bibliotek
图 811
下面我们讨论一下如何利用堆进行排序? 下面我们讨论一下如何利用堆进行排序? 从堆的定义可以看出,若将堆用一棵完全二 从堆的定义可以看出, 叉树表示,则根结点是当前堆中所有结点的最小者 叉树表示, (或最大者)。堆排序的基本思想是:首先将待排序 或最大者)。堆排序的基本思想是: )。堆排序的基本思想是 的记录序列构造一个堆,此时,选出了堆中所有记录 的记录序列构造一个堆,此时, 的最小者或最大者,然后将它从堆中移走, 的最小者或最大者,然后将它从堆中移走,并将剩余 的记录再调整成堆,这样又找出了次小(或次大) 的记录再调整成堆,这样又找出了次小(或次大)的 记录,以此类推,直到堆中只有一个记录为止,每个 记录,以此类推,直到堆中只有一个记录为止, 记录出堆的顺序就是一个有序序列。 记录出堆的顺序就是一个有序序列。
3. 简单选择排序算法 简单选择排序的整体结构应该为: 简单选择排序的整体结构应该为: for (i=1;i<n;i) { 第i趟简单选择排序; 趟简单选择排序; }
下面我们进一步分析一下“ 下面我们进一步分析一下“第i 趟简单选择排 的算法实现。 序”的算法实现。 (1)初始化:假设无序区域中的第一个记录为关 初始化: 键字值最小的元素,即将index=i; 键字值最小的元素,即将index=i; (2)搜索无序区域中关键字值最小的记录位置: 搜索无序区域中关键字值最小的记录位置: for (j=i+1;j< =n;j++) if (a[j].key<a.[index].ke) index=j; (3)将无序区域中关键字最小的记录与无序区域 的第一个记录进行交换,使得有序区域由原来的i 的第一个记录进行交换,使得有序区域由原来的i1个记录扩展到i个记录。 个记录扩展到i个记录。
相关文档
最新文档