8.4 选择排序

一、单项选择题
01.在以下排序算法中,每次从未排序的记录中选取最小关键字的记录,加入已排序记录的末尾,该排序方法是 ( )。
A.简单选择排序
B.冒泡排序
C.堆排序
D.直接插入排序
01.A

02.简单选择排序算法的比较次数和移动次数分别为( )
AO(n),0(log2n)
B. O(log2n),O(n^2)
C.O(n^2),O(n)
D.O(nlog2n),O(n)
02.C 注意:读者应熟练掌握各种排序算法的思想、过程和特点。

03.设线性表中每个元素有两个数据项k1和 k2,现对线性表按以下规则进行排序: 先看数据项k1,k1值小的元素在前,大的元素在后;在k1值相同的情况下,再看k2,k2值小的在前,大的元素在后。满足这种要求的排序方法是( ).
A,先按k1进行直接插入排序,再按 k2进行简单选择排序
B,先按k2进行直接插入排序,再按k1进行简单选择排序
C.先按k1进行简单选择排序,再按k2进行直接插入排序
D.先按k2进行简单选择排序,再按k1进行直接插入排序
03,D 本题思路来自基数排序的 LSD,首先应确定k1、k2的排序顺序,若先排k1再排k2,则排序结果不符合题意,排除选项A 和 C。再考虑算法的稳定性,当k2排好序后,再对k1排序,若对k1排序采用的算法是不稳定的,则对于k1相同而k2不同的元素可能会改变相对次序,从而不一定能满足题设要求。直接插入排序算法是稳定的,而简单选择排序算法是不稳定的,故只能选择选项D。
04. 若只想得到 1000 个元素组成的序列中第 10 个最小元之前的部分排序的序列,用()方法最快。
A.冒泡排序
B.快速排序
C.希尔排序
D.堆排序
04.D希尔排序和快速排序要等排序全部完成之后才能确定最小的 10 个元素。冒泡排序需要从后向前执行 10 越冒泡才能得到 10 个小的元素,而堆排序只需调整 10 次小根堆,调整时间与树高成正比。显然堆排序所需的时间更短。通常,取一大堆数据中的k个最大(最小)的元素时,都优先采用堆排序。

05下列()是一个堆
A19,75,34,26,97,56
B.97,26,34,75,19,56
C19,56,26,97,34,75
D.19,34,26,97,56,75
05.D 可将每个选项中的序列表示成完全二叉树,再看父结点与子结点的关系是否全部满足堆的定义。例如,选项A 中序列对应的完全二叉树如右图所示。显然,最小元素 19 在根结点,因此可能是小根堆,但 75 与26 的关系却不满足小根堆的定义,所以选项A 中的序列不是一个堆。其他选项采用类似的过程分析。
在这里插入图片描述

06.有一组数(15,9,7,8,20,-1,7,4),用堆排序的筛选方法建立的初始小根堆为( )
A.-1,4,8,9,20,7,15,7
B.-1,7,15,7,4,8,20,9
C.-1,4,7,8,20,15,7,9
D.A、B、C 均不对
06.C 从Ln/2]~1依次筛选堆的过程如下图所示,显然选择选项 C。
在这里插入图片描述
07.在含有 n个关键宇的小根堆中,关键字最大的记录有可能存储在( )位置。
A.n/2
B.n/2 + 2
C.1
D.n/2-1
07.B 这是小根堆,关键字最大的记录一定存储在这个堆所对应的完全二叉树的叶结点中:又因为二叉树中的最后一个非叶结点存储在Ln/2]中,所以关键字最大记录的存储范围为Ln/2]+1~n,所以应该选择选项 B。

08.向具有 n个结点的堆中插入一个新元素的时间复杂度为( ),删除一个元素的时间复杂度().
A.O(1)
B.O(n)
C.O(log2n)
D.O(nlog2n)
08.C、C在向有 n 个元素的堆中插入一个新元素时,需要调用一个向上调整的算法,比较次数最多等于树的高度减1,由于树的高度为Llog2n]+1所以堆的向上调整算法的比较次数最多等于Llog2n+1]。此处需要注意,调整堆和建初始堆的时间复杂度是不一样的,读者可以仔细分析两个算法的具体执行过程。

09.构建n个记录的初始堆,其时间复杂度为( );对n个记录进行堆排序,最坏情况下其时间复杂度为( ).
A.O(n)
B.O(n*2)
c.O(log2n)
DO(nlog2n)
09.A、D 建堆过程中,向下调整的时间与树高h有关,为0(h)。每次向下调整时,大部分结点的高度都较小。因此,可以证明在元素个数为 n的序列上建堆,其时间复杂度为 0(n)。无论是在最好情况下还是在最坏情况下,堆排序的时间复杂度均为O(nlog2n)。
堆排序中,初始化堆(构建堆)的时间复杂度为O(N),反复重建(重建堆)的时间复杂度为O(logN),从而N个元素堆排序的时间复杂度为O(NlogN)

10.对关键码序列{23,17,72,60,25,8,68,71,52)进行排序,输出两个最小关键码后的剩余堆是( ).
A.{23,72,60,25,68,71,52}
B.{23,25,52,60,71,72,68}
C.{71,25,23,52,60,72,68}
D.{23,25,68,52,60,72,71}
10.D 筛选法初始建堆为{8,17,23,52,25,72,68,71,60}输出8后重建的堆为{17,25,23,52,60,72,68,71},输出 17 后重建的堆为{23,25,68,52,60,72,71}

11.[2009 统真题】已知关键字序列5,8,12,19,28,20,15,22 是小根堆,插入关键字3,调整好后得到的小根堆是( )
A.3,5,12,8,28,20,15,22,19
B.3,5,12,19,20,15,22,8,28
C.3,8,12,5,20,15,22,28,19
D.3,12,5,8,28,20,15,22,19
11,A 插入关键字3 后,堆的变化过程如下图所示。在这里插入图片描述

12.[2011统考真题] 已知序列 25,13,10,12,9是大根堆,在序列尾部插入新元素 18,将其再调整为大根堆,调整过程中元素之间进行的比较次数是。
A.
B,3,5,12,19,20,15,22,8,28
D,3,12,5,8,28,20,15,22,19
B.2
12.8首先18与10 比较,交换位置,再与 25 比较,不交换位置。共比较了 2 次,调整的过程如下图所示。在这里插入图片描述

13.下列 4种排序方法中,排序过程中的比较次数与序列初始状态无关的是( )
A,选择摔序法
B.插入排序法
C.快速排序法
D.冒泡排序法
13.A 选择排序算法的比较次数始终为 n(n -1)2,与序列状态无关
14.【2015 统考真题】已知小根堆为8,15,10,21,34,16,12,删除关键字8之后需重建堆,在此过程中,关键字之间的比较次数是( )
A.1
B.2
C.3
D.4
删除8 后,将 12 移动到堆顶,第一次是 15 和 10 比较,第二次是 10 和 12 比较并交换,第三次还需比较 12 和 16,故比较次数为 3。
15.【2018统考真题】在将序列(6,1,5,9,8,4,7)建成大根堆时,正确的序列变化过程是( )
A.6,1,7,9,8,4,5 -> 6,9,7,1,8,4,5 -> 9,6,7,1,8,4,5 -> 9,8,7,1,6,4,5
B.6,9,5,1,8,4,7-> 6,9,7,1,8,4,5-> 9,6,7,1,8,4,5-> 9,8,7,_
C.6,9,5,1,8,4,7-> 9,6,5,1,8,4,7-> 9,6,7,1,8,4,5-> 9,8,7,1,6,4,5
D.6,1,7,9,8,4,5-> 7,1,6,9,8,4,5-> 7,9,6,1,8,4,5-> 9,7,6,1,8,4,5–9,8,6,1,7,4,5
15.A 要熟练掌握建堆和调整堆的方法,从序列末尾开始向前遍历,变换过程如下图所示。
在这里插入图片描述

16.【2020统考真题】下列关于大根堆(至少 2个元素) 的中,正确的是()
I.可以将堆视为一棵完全二叉树
Il.可以采用顺序存储方式保存堆
III.可以将堆视为一棵二叉排序树
IV.堆中的次大值一定在根的下一层
A.仅I、II
B.仅 I、Ⅲ
C.仅I、I和IV
D.I、Ⅲ和IV
这是一道简单的概念题。堆是一棵完全树,采用一维数组存储,故选项I正确,选项II正确。大根堆只要求根结点值大于左右孩子值,并不要求左右孩子值有序,选项 Ⅲ错误。堆的定义是递归的,所以其左右子树也是大根堆,所以堆的次大值一定是其左孩子或右孩子,选项IV 正确。

17.[2021统考真题]将关健 6,9,1,5,8,4,7依次插入到初为空的大根堆H中,得到的H是( ),
A.9,8,7,6,5,4,1
B.9,8,7,5,6,1,4
C.9,8,7,5,6,4,1
D,9,6,7,5,8,4,1
要熟练掌握调整堆的方法,建堆的过程如下图所示,故答案选择选项B。在这里插入图片描述

二、综合应用题
01.指出堆和二叉排序树的区别?
01[解答] 以小根堆为例,堆的特点是双亲结点的关键字必然小于或等于该孩子结点的关键字,而两个孩子结点的关键字没有次序规定。在二叉排序树中,每个双亲结点的关键字均大于左子树结点的关键字,均小于右子树结点的关键字,也就是说,每个双亲结点的左、右孩子的关键字有次序关系。这样,当对两种树执行中序遍历后,二叉排序树会得到一个有序的序列,而堆则不一定能得到一个有序的序列。

02.若只想得到一个序列中第 k(k>=5) 个最小元责之前的部分排序序列,则最好采用什么排序方法?
02.[解答] 在基于比较的排序方法中,插入排序、快速排序和归并排序只有在将元素全部排完序后,才能得到前k小的元素序列,算法的效率不高。 冒泡排序、堆排序和简单选择排序可以,因为它们在每一越中都可以确定一个最小的元素。采用堆排序最合适,对于n个元素的序列,建立初始堆的时间不超过4n,取得第k个最小元素之前的排序序列所花的时间为 klog2n,总时间为 4n +log2n;冒泡与简单排序完成此功能所花时间为 kn,当k>=5 时,通过比较可以得出堆排序优。 注意: 从本题可以得出结论,只需得到前 k小元素的顺序排列可采用的排序算法有冒泡排序、堆排序和简单选择排序。

03.有 n个元素已构成一个小根堆,现在要增加一个元素 Kn+1,请用文字简要说明如何在 log2n的时间内将其重新调整为一个堆。

03.[解答]将K n+1入数的第n+1个位置(即作为一个树叶插入),然后将其与它于其双亲比较,若它大于其双亲则停止调整,否则K n+1与其双亲交换,重复地将K n+1与其新的双亲比较,算法终止于K n+1大于或等于其双亲或K n+1本身已升为根 。

04,编写一个算法,在基于单链表表示的待排序关健字序列上进行简单选择排序.

04.[解答]
算法的思想是:每趟在原始链表中摘下关键字最大的结点,把它插入结果链表的最前端。由于在原始链表中摘下的关键字越来越小,在结果链表前端插入的关键字也越来越小,因此最后形成的结果链表中的结点将按关键字非递减的顺序有序链接。单链表的定义如第 2 章所述,假设它不带表头结点。
void selectSort(linkedlista &L){
//对不带表头结点的单链表L执行简单选择排序
LinkNode *h=L,*p,*q,*r,*s;
L=NULL;
while(h!=NULL){
//持续扫描原链表
p=s=h;q=r=NULL;  //指针 s 和记忆最大结点和其前驱;P 为工作指针,q为其前驱
while(p!=NULL)//扫插原链表寻找最大结点s
if(p->data>s->data)(s=p;r=q;}//找到更大的,记忆它和它的前驱
q=p;p=p->link;//继续寻找
if(s=h)
h=h->link;
//最大结点在原链表前端
else
I->link=s->link;
//最大结点在原链表表内
s->link=L;L=s;
//结点s插入结果链前端

05.试设计一个算法,判断一个数据序列是否构成一个小根堆。

05.[解答]
将顺序表 L[l...n]视为一个完全二叉树,扫描所有分支结点,遇到孩子结点的关键字小于根结点的关键字时返回 false,扫描完后返回 true。算法的实现如下:
bool IsMinHeap(ElemType A[],int len)[
if(len%2==0){  // len 为偶数,有一个单分支结点if(A[len/2]>A[len])  //判断单分支结点
return false;
for(i=len/2-1;i>=1;i--] //判断所有双分支结点
if(A[i]>A[2*1] || A[i]>A[2*i+1]
return false;
}
else{
//len 为奇数时,没有单分支结点
for(i=len/2-1;i>=1;i--)    //判断所有双分支结点
if(A[i]>A[2*1] ||  A[i]>A[2*i+1])
return false;
}
return true;

06.【2022 统考真题]】现有 (n>100000)个数保存在一维数组 M 中,需要查找 M中最小的 10 个数。请回答下列问题。
1)设计一个完成上述查找任务的算法,要求平均情况下的比较次数尽可能少,简述其算法思想(不需要程序实现)
2)说明你所设计的算法平均情况下的时间复杂度和空间复杂度。
06.[解答] 1)算法思想
[方法 1]定义含 10个元素的数组 A,初始时元素值均为该数组类型能表示的最大数 MAX。 for M中的每个元素s if (s<A[9]) 丢弃 A[9]并将 s 按升序插入到A中; 当数据全部扫描完毕,数组 A[0]~A[9]保存的即是最小的 10 个数。
[方法 2]定义含 10 个元素的大根堆 H,元素值均为该元素类型能表示的大数 MAX。 for M中的每个元素s
if (s<H 的堆项元素) 删除堆顶元素并将 s 插入到H中; 当数据全部扫描完毕,堆H中保存的即是最小的 10 个数。
2)算法平均情况下的时间复杂度是 O(n),空间复杂度是 0(1)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值