王道数据结构易错点八章

04.对任意7个关键字进行基于比较的排序,至少要进行()次关键字之间的两两比较。
A.13
B.14
C.15
D.16
04.A 对于任意序列进行基于比较的排序,求至少的比较次数应考虑最坏情况。对任意n个关键字排序的比较次数至少为「log2(n!)]。将n=7代入公式,答案为13。上述公式证明如下(仅供有兴趣的同学参考):在基于比较的排序方法中,每次比较两个关键字后,仅出现两种可能的转移。假设整个排序过程至少需要做t次比较,则显然会有2^t种情况。由于n个记录共有n!种不同的排列,因而必须有n!种不同的比较路径,于是有2^t≥n!,即t≥log2(n!)。考虑到t为整数,故为「log2(n!)。

n个数组成的不同排列方式有n!个
已经排好序的数列(假设是从小到大排列)是这n!个序列中的一个,排序所作的就是找出这个序列。
设 这数列中有两个数 a ,b
这n!种排列组合中 a在b前 和 a在b后 的机会是均等的
比较一次a,b的大小(不妨假设a<b),那么所有 a排在b后的情况都是不符合从小到大的要求的。这样我们将n!个可能的情况剔除了一半。
重复以上步骤,理想状态下,每比较一次都可以排除一半的情况。
于是比较 log2(n!)次就可以将其他的错误排列全部排除,留下排好序的这一种情况。

07.希尔排序属于()。
A.插入排序
B.交换排序
C.选择排序
D.归并排序
07.A 希尔排序是对直接插入排序算法改进后提出来的,本质上仍属于插入排序的范畴。
直接插入法的总结:就是与前面的元素比较(前面已经排好序了),比较后,找到它应该放的位置就插入其中。希尔排序,就是有一定间隙后相互插入。
11.折半插入排序算法的时间复杂度为().
A. O(n)
B.O(nlog2n)
C. O(n²)
D. O(n^3)
11.C 虽然折半插入排序是对直接插入排序的改进,但它改进的只是比较的次数,而移动次数未发生变化,时间复杂度仍为O(n²)。
16.【2012 统考真题】对同一待排序序列分别进行折半插入排序和直接插入排序,两者之间可能的不同之处是().
A.排序的总趟数
B.元素的移动次数
C.使用辅助空间的数量
D.元素之间的比较次数
16.D 折半插入排序与直接插入排序都将待插入元素插入前面的有序子表,区别是:确定当前记录在前面有序子表中的位置时,直接插入排序采用顺序查找法,而折半插入排序采用折半查找法。排序的总趟数取决于元素个数n,两者都是n-1趟。元素的移动次数都取决于初始序列,两者相同。使用辅助空间的数量也都是0(1)。折半插入排序的比较次数与序列初态无关,为O(nlog2n);而直接插入排序的比较次数与序列初态有关,为O(n)~O(n²)。
18.【2015统考真题】希尔排序的组内排序采用的是().
A.直接插入排序
B.折半插入排序
C.快速排序
D.归并排序
18.A 希尔排序的思想是:先将待排元素序列分割成若干子序列(由相隔某个“增量”的元素组成),分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。

01.给出关键字序列{4,5, 1,2,6, 3}的直接插入排序过程。

01.给出关键字序列{4,5, 1,2,6, 3}的直接插入排序过程。
01.【解答]
直接插入排序过程如下。
初始序列:
4,5, 1, 2, 6,3
第一趟:
4, 5, 1,2, 6, 3
(将5插入{4})
第二趟:
1,4,5,2, 6, 3
(将1插入{4,5})
第三趟:
1,2,4,5, 6, 3
(将2插入{1,4,5})
第四趟:
1,2,4,5, 6, 3
(将6插入{1,2,4,5})
第五趟:
1, 2, 3, 4,5, 6
(将3插入{1,2,4, 5,6})

注意第一趟从哪里开始。
04.一组记录的关键码为(46, 79,56,38,40,84),则利用快速排序的方法,以第一个记录为基准,从小到大得到的一次划分结果为()。
A.(38,40,46,56, 79, 84)
B.(40,38,46,79, 56,84)
C.(40,38,46,56, 79,84)
D.(40,38,46,84,56,79)
04.C 以46为基准元素,首先从后向前扫描比46小的元素,并与之进行交换,而后从前向后扫描比46大的元素并将46与该元素交换,得到(40,46,56, 38, 79,84)。此后,继续重复从后向前扫描与从前往后扫描的操作,直到46处于最终位置,答案选择选项C.

05.快速排序算法在()情况下最不利于发挥其长处。
A.要排序的数据量太大
B.要排序的数据中含有多个相同值
C.要排序的数据个数为奇数
D.要排序的数据已基本有序
05.D 当待排序数据为基本有序时,每次选取第n个元素为基准,会导致划分区间分配不均匀,不利于发挥快速排序算法的优势。相反,当待排序数据分布较为随机时,基准元素能将序列划分为两个长度大致相等的序列,这时才能发挥快速排序的优势。
09.对下列关键字序列用快排进行排序时,速度最快的情形是(),速度最慢的情形是().
A.{21,25,5,17,9,23,30}
B.{25,23,30,17, 21,5,9}
C.{21,9,17,30,25,23,5}
D.{5,9,17,21,23,25,30}
09、A、D 当每次的枢轴都把表等分为长度相近的两个子表时,速度是最快的;当表本身已经有序或逆序时,速度最慢。选项D中的序列已按关键字排好序,因此它是最慢的,而选项A中第一趟枢轴值21将表划分为两个子表{9,17,5}和{25,23,30},而后对两个子表划分时,枢轴值再次将它们等分,所以该序列是快速排序最优的情况,速度最快。其他选项可以类似分析。

10.对下列4个序列,以第一个关键字为基准用快速排序算法进行排序,在第一趟过程中移动记录次数最多的是().
A.92,96,88,42,30,35,110,100
B.92.96,100,110,42,35,30,88
C.100,96,92,35,30,110,88,42
D.42,30, 35,92,100,96,88.110
10.B 对各序列分别执行一趟快速排序,可做如下分析(以选项A为例);由于枢轴值为92,因此35移动到第一个位置,96移动到第六个位置,30移动到第二个位置,再将枢轴值移动到30所在的单元,即第五个位置,所以选项A中序列移动的次数为4。同样,可以分析出选项B中序列的移动次数为8,选项C中序列的移动次数为4,选项D中序列的移动次数为2.
11.下列序列中,()可能是执行第一趟快速排序后所得到的序列,
I.{68,11,18,69,23,93,73}
Ⅱ. {68,11,69, 23,18, 93,73}
IIl.{93, 73, 68, 11, 69, 23,18}
IV.{68, 11,69,23,18,73,93)
A.I、IV
B.Ⅱ、III
C.II、IV
D.只有IV
11.C 显然,若按从小到大排序,则最终有序的序列是{11, 18,23, 68, 69, 73, 93};若按从大到小排序,则最终有序的序列是{93,73,69,68,23,18,11}。对比可知选项I、Ⅱ中没有处于最终位置的元素,故选项I、Ⅱ都不可能。选项III中73和93处于从大到小排序后的最终位置,而且73将序列分割成大于73和小于73的两部分,故选项III是有可能的。选项IV中73和93处于从小到大排列后的最终位置,73也将序列分割成大于73和小于73的两部分。

12.对n个关键字进行快速排序,最大递归深度为(),最小递归深度为()
A,1
B,n
C,log2n
D.,nlog2n
12.B、C 快速排序过程构成一个递归树,递归深度即递归树的高度。枢轴值每次都将子表等分时,递归树的高为log2n;枢轴值每次都是子表的最大值或最小值时,递归树退化为单链表,树高为n。

15.【2011统考真题]为实现快速排序算法,待排序序列宜采用的存储方式是().
A.顺序存储
B.散列存储
C.链式存储
D.索引存储
15.A 绝大部分内部排序只适用于顺序存储结构。快速排序在排序的过程中,既要从后向前查找,又要从前向后查找,因此宜采用顺序存储。

16.【2014统考真题]下列选项中,不可能是快速排序第2趟排序结果的是()
A.2, 3, 5,4, 6, 7,9
B.2, 7,5, 6, 4, 3,9
C.3, 2, 5,4,7, 6,9
D.4, 2,3, 5, 7,6,9
16.C 快排的阶段性排序结果的特点是,第i趟完成时,会有i个以上的数出现在它最终将要出现的位置,即它左边的数都比它小,它右边的数都比它大。题目问第二趟排序的结果,即要找不存在两个这样的数的选项。选项A中2,3,6,7,9均符合,所以选项A排除:选项B中,2,9均符合,所以选项B排除:选项D中5,9均符合,所以选项D排除;最后看选项C,只有9一个数符合,所以选项C不可能是快速排序第二趟的结果。

17.【2019统考真题]排序过程中,对尚未确定最终位置的所有元素进行一遍处理称为一“趟”,下列序列中,不可能是快速排序第二趟结果的是().
A.5,2, 16,12,28,60,32,72
B.2,16,5,28,12,60,32,72
C.2,12,16,5,28, 32,72,60
D.5,2,12,28,16,32,72,60
17.D 要清晰掌握排序过程中“趟”的含义,题干也进行了解释一一对尚未确定最终位置的所有元素都处理一遍才是一趟,所以此时要对前后两块子表各做一次快速排序才是一“趟”,如果只对一块子表进行了排序,而未处理另一块子表,就不能算是完整的一趟。选项A,第一趟匹配72,只余一块无序序列,第二趟匹配28、选项A可能。选项B,第一趟匹配2,第二趟匹配72,B可能。选项C,第一趟匹配2,第二趟匹配28或32,选项C可能。选项D,无论是先匹配12还是先匹配32,都会将序列分成两块,那么第二趟必须有两个元素匹配,所以选项D不可能。

01.在使用非递归方法实现快速排序时,通常要利用一个栈记忆待排序区间的两个端点。能否用队列来实现这个栈?为什么?
01.[解答] 可以用队列来代替栈。在快速排序的过程中,通过一趟划分,可以把一个待排序区间分为两个子区间,然后分别对这两个子区间施行同样的划分。栈的作用是在处理一个子区间时,保存另一个子区间的上界和下界(排序过程中可能产生新的左、右子区间),待该区间处理完后再从栈中取出另一子区间的边界,对其进行处理。这个功能用队列也可以实现,只不过处理子区间的顺序有所变动而已。

02.编写双向冒泡排序算法,在正反两个方向交替进行扫描,即第一趟把关键字最大的元素放在序列的最后面,第二趟把关键字最小的元素放在序列的最前面,如此反复进行。
02.[解答] 这种排序方法又称双向起泡。奇数趟时,从前向后比较相邻元素的关键字,遇到逆序即交换,直到把序列中关键字最大的元素移动到序列尾部。偶数趟时,从后往前比较相邻元素的关键字,遇到逆序即交换,直到把序列中关键字最小的元素移动到序列前端。


程序代码如下:
void BubbleSort (ElemType A[],int n){
//双向起泡排序,交替进行正反两个方向的起泡过程
int low=0,high=n-1;
bool flag=true;
//一趟冒泡后记录元素是否交换标志
while(low<high&&flag){//循环跳出条件,当flag为false说明已没有逆序
flag=false;
//每趟初始置flag为false
for(i=low;i<high;i++)
//从前向后起泡
if(A[i]>A [i+1]){
//发生逆序
swap(A[i],A[i+1]);//交换
flag=true;
//置flag
high--;
//更新上界
for(i=high;i>low;i--)
//从后往前起泡
if(A[i]<A[i-1]){
//发生逆序
swap(A[i],A[i-1]);//交换
flag=true;
//置flag
}
low++;
//修改下界
}
}

03.已知线性表按顺序存储,且每个元素都是不相同的整数型元素,设计把所有奇数移动到所有偶数前边的算法(要求时间最少,辅助空间最少)。
03.【解答]本题可采用基于快速排序的划分思想来设计算法,只需遍历一次即可,其时间复杂度为0(n),空间复杂度为0(1)。假设表为L[1..n],基本思想是:先从前向后找到一个偶数元素L(i),再从后向前找到一个奇数元素L(j),将二者交换;重复上述过程直到i大于j。

算法的实现如下:
void move (ElemType All,int len) {
//对表A按奇偶进行一趟划分
int i-0,j=len-1;
//i表示左端偶数元素的下标;j表示右端奇数元素的下标
while(i<j){
while(i<j&&A[i]*2!=0) i++;//从前向后找到一个偶数元素
while(i<j&&A[j]%2!=1) j--; //从后向前找到一个奇数元素
if(i<j){
Swap (A[i],A[j]);
//交换这两个元素
}

04.试重新编写考点精析中的快速排序的划分算法,使之每次选取的枢轴值都是随机地从当前子表中选择的。

04.【解答]
这类题目比较简单,为方便起见,可直接先随机地求出枢轴的下标,然后将枢轴值与A[low]交换,而后的思想就与前面的划分算法一样。算法的实现如下:
int Partition2(ElemType A[],int low,int high){
int rand_Index=low+rand()*(high-low+1):
Swap(A[rand_Index],A[low];
//将枢轴值交换到第一个元素
ElemType pivot=A[low);
//置当前表中的第一个元素为枢轴值
int i=low;
//使得表A[low..i]中的所有元素小于pivot,初始为空表
for(int j=low+1;j<=high;j++}
//从第二个元素开始寻找小于基准的元素
if (A[j]<pivot)
//找到后,交换到前面
swap(A[++i],A[j]);
swap (A[i],A[low]);
//将基准元素插入最终位置
return i;
//返回基准元素的位置
注意:本题代码中的比较方法和考点精析中的两种方法均不相同,请读者仔细模拟各种划分算法的执行步骤,做到真正掌握。对于下一题,读者可以尝试采用这三种比较方法来分别解决。

05.试编写一个算法,使之能够在数组L[1…n]中找出第k小的元素(即从小到大排序后处于第k个位置的元素)。

05.[解答]
显然,本题最直接的做法是用排序算法对数组先进行从小到大的排序,然后直接提取L(k)便得到了第k小元素,但其平均时间复杂度将达到O(nlog2n)以上。此外,还可采用小顶堆的方法,每次堆顶元素都是最小值元素,时间复杂度为O(n + k log2n)。下面介绍一个更精彩的算法,它基于快速排序的划分操作。
这个算法的主要思想如下:从数组L[1...n]中选择枢轴pivot(随机或直接取第一个)进行和快速排序一样的划分操作后,表L[1..n]被划分为L[1...m-1]和L[m+1_n),其中L(m)=pivot。
讨论m与k的大小关系:
1)当m=k时,显然pivot就是所要寻找的元素,直接返回pivot即可。
2)当m<k时,所要寻找的元素一定落在L[m+1....n)中,因此可对L[m+1...n]递归地查找第k-m小的元素。
3)当m>k时,所要寻找的元素一定落在L[1....m-1)中,因此可对L[1...m-1]递归地查找第k小的元素。
该算法的时间复杂度在平均情况下可以达到0(n),而所占空间的复杂度则取决于划分的方法。算法的实现如下:
int kth_elem(int a[],int low,int high,int k)(
int pivot=a[low];
int low_temp=low;
//由于下面会修改low与high,在递归时又要用到它们
int high_temp=high;
while(low<high){
while(low<high&&a[high]>=pivot)
--high;
a[low]=a[high];
while(low<high&óa[low]<=pivot)
++low;
a[high]=a[low];
}
a[low]=pivot;
//上面即为快速排序中的划分算法
//以下就是本算法思想中所述的内容
if (low==k)
//由于与k相同,直接返回pivot元素
return a[low];
else if(low>k)
//在前一部分表中递归寻找
return kth_elem(a,low_temp,low-1,k);
else
//在后一部分表中递归寻找
return kth_elem(a,low+1,high_temp,k);

06.荷兰国旗问题:设有一个仅由红、白、蓝三种颜色的条块组成的条块序列,请编写一个时间复杂度为O(n)的算法,使得这些条块按红,白、蓝的顺序排好,即排成荷兰国旗图案。

06.【解答]
算法思想:顺序扫描线性表,将红色条块交换到线性表的最前面,蓝色条块交换到线性表的最后面。为此,设立三个指针,其中,j为工作指针,表示当前扫描的元素,i以前的元素全部为红色,k以后的元素全部为蓝色。根据j所指示元素的颜色,决定将其交换到序列的前部或尾部。
初始时i=0,k=n-1,算法的实现如下:
typedef  enum{RED,WHITE, BLUE} color; //设置枚举数组
void Flag_Arrange(color a[],int n){
int i=0,j=0,k=n-1;
while (j<=k)
switch(a[j]){  //判断条块的颜色
case   RED: Swap(a[i],a[j]);i++;j++;break;
//红色,则和i交换
case WHITE: j++;break;
case   BLUE: Swap(a[j),a[k]);k--;
//蓝色,则和k交换
//这里没有j++语句以防止交换后a[j]仍为蓝色的情况
}
例如,将元素值正数、负数和零排序为前面都是负数,接着是0,最后是正数,也用同样的方法。思考:为什么case   RED时不用考虑交换后a[j]仍为红色,而case BLUE却需要考虑交换后 alj]仍为蓝色?

07.【2016统考真题】已知由n(n≥2)个正整数构成的集合A={ ak]0≤k<n},将其划分为两个不相交的子集A1和A2,元素个数分别是n1和n2,A1和h2中的元素之和分别为S1和S2。设计一个尽可能高效的划分算法,满足|n1-n2|最小且|S1-S2|最大。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
3)说明你所设计算法的平均时间复杂度和空间复杂度。

07.【解答]
1)算法的基本设计思想
由题意知,将最小的  Ln/2」个元素放在A1中,其余的元素放在A2中,分组结果即可满足题目要求。仿照快速排序的思想,基于枢轴将n个整数划分为两个子集。根据划分后枢轴所处的位置
i分别处理:
①若i=Ln/2」,则分组完成,算法结束。
② 若i<Ln2」,则枢轴及之前的所有元素均属于A1,继续对i之后的元素进行划分。
③ 若i>Ln/2」,则枢轴及之后的所有元素均属于A2,继续对i之前的元素进行划分。
基于该设计思想实现的算法,无须对全部元素进行全排序,其平均时间复杂度是0(n),空间复杂度是0(1)。
2)算法实现
int setPartition( int a[], int n){
int pivotkey, low=0,low0=0,high-n-1,high0=n-1,flag=1,k=n/2,i;
int s1=0,s2=0;
while(flag){
pivotkey=a[low];
//选择枢轴
while(low<high){
//基于枢轴对数据进行划分
while(low<high && a[high)>=pivotkey) --high;
if(low!=high) a[low]=a[high];
while(low<high && a[low]<-pivotkey) ++low;
if(low!=high) a[high]=a[low);
}
//end of while(low<high)
a[lowl=pivotkey;
if(low==k-1)
//若枢轴是第n/2小元素,划分成功
flag=0;
else(
//是否继续划分
if(low<k-1){
low0=++low;
high=high0;
}
else(
high0=--high;
low=low0;
}
}
}
for(i-0;i<k;i++) s1+=a[i);
for(i=k;i<n;i++) s2+=a[i];
return s2-sl;
}
3)本答案给出的算法平均时间复杂度是0(n),空间复杂度是0(1)。

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)。

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值