哎呀自己好久没写博客了,赶紧水一篇,专业课摘记全部都写在电脑上,以后也会更新!爱你。下面的题目也是我自己写了王道数据结构题目之后总结的易错题,包含错误分析。
一个算法应该是(B
D)A. 程序
B. 问题求解步骤的描述
C. 要满足五个基本特性
D. A 和 C
**PS:**算法是一个思想,程序是它具体化的一个表现形式
某算法的时间复杂度为O(n^2),表名该算法(C
D)A. 问题规模为n^2
B. 执行时间为n^2
C. 执行时间和n^2成正比
D. 问题规模与n^2 成正比
**PS:**时间复杂度就是和执行时间成正比关系的,
算法的问题规模没有非常精准的定义,一般指运行时间和输入参数n之间的表达方式。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。本题的D选项的正确解释就是应该是问题规模T(n)和n有关
下面算法加下划线的语句的执行次数(A
D)int m = 0, i, j; for (int i = 1; i >= n; i++) { for (int j = 1; j <= 2 i; j++) { m++; } }
A. n(n+1)
B. n
C. n + 1
D. n^2
PS: 求执行次数必须精确计算,不能像计算时间复杂度一样抛弃次数较小的项。
下面说法错误的是(A
B)I.算法原地工作的含义是指不需要任何额外的辅助空间
II.在相同规模n下,复杂度为O(n)的算法在时间上总是优于复杂度为0(2^n)的算法
II.所谓时间复杂度,是指最坏情况下估算算法执行时间的一个上界
IV.同一个算法,实现语言的级别越高,执行效率越低A. I B. I, II C. I, IV D. III
PS:第二项是错的,求导就知道了在n大于0的时候
2^n > n
恒成立
第一项的算法原地工作意思是指算法所需的辅助空间是常量
线性表的顺序存储结构是(A
B)A.随机存储的存储结构
B.顺序存取的存储结构
C.索引存取的xxx
D.散列存取的xxx
存取方式指的是读写方式,顺序表支持随机存取
一个线性表最常用的操作是存取任一指定序号的元素并在最后进行插入,删除操作,则利用(A
C)存储方式可以节省时间A.顺序表
B.双链表
C.带头结点的双循环链表
D.单循环链表
PS:插入删除操作一起进行的话就不需要进行后继元素的迁移,直接在指定地址进行数值替换就可以了,时间复杂度为O(1)
在n个元素的线性表的数组表示中,时间复杂度为O(1)的操作是(C
A)I 访问第i (1≤i≤n)个结点和求第i (2≤i≤n)个结点的直接前驱
II 在最后一个结点后插入一个新的结点
III 删除第1个结点
IV 在第 i ( 1≤i≤n)个结点后插入一个结点A. I
B. II III
C. I II
D. I II III
PS: 选项二也是对的,因为是最后一个元素,插入新的节点无序额外的移动其他元素的步骤。
若长度为n的非空线性表采用顺序存储结构,在表的第i个位置插入一个数据元素,则i的合法值应该是(B
D)A. [i, n]
B. [1, i+1]
C. [0, n-1]
D. [0, n]
PS: 顺序表的地址默认从1开始,第n+1个位置说明是在尾部插入
关于线性表的顺序存储结构和链式存储结构的描述中,正确的是(B
C)。I.线性表的顺序存储结构优于其链式存储结构
II.链式存储结构比顺序存储结构能更方便地表示各种逻辑结构
Ⅲ.若频繁使用插入和删除结点操作,则顺序存储结构更优于链式存储结构IV.顺序存储结构和链式存储结构都可以进行顺序存取
A. 1 2 3
B. 2 4
C. 2 3
D. 3 4
PS:3错得显而易见,插入删除还是链式更加方便呢
下列关于线性表说法中,正确的是(D
C)I.顺序存储方式只能用于存储线性结构
II.取线性表的第i个元素的时间与i的大小有关
III.静态链表需要分配较大的连续空间,插入和删除不需要移动元素
IV.在一个长度为n的有序单链表中插入一个新结点并仍保持有序的时间复杂度为O(n)、V.若用单链表来表示队列,则应该选用带尾指针的循环链表
A. I、II
B. I、III、IV、 VC. IV、V
D.III、IV、VPS:3是对的,因为静态链表在创建的时候已经分配好所有的空间了,增删改查不改变表不动
给定有n个元素的一维数组,建立一个有序单链表需要的最低时间复杂度为(D
B)A. O(1)
B. O(N)
C. O(N^2)
D. O(nlog2(n))
PS:要算上排序的时间,排序最短时间nlog2(n),建立链表最短时间为n,所以取最大的,就是nlog2(n)
将长度为n的单链表接在长度为m的单链表后面,其算法的时间复杂度为(C
A)A. O(1)
B. O(n)
C. O(m)
D. O(m+n)
PS:在拼接时间需要先从头节点走到尾节点,然后再接上下一个链表的头结点。
单链表中,增加一个头结点的目的是(C
B)A. 使单链表至少有一个节点
B. 标识表节点中首节点的位置
C. 方便运算的实现
D. 说明单链表是线性表的链式存储
PS: 这里的运算指的是增删改查运算,这个确实比一般的单链表要更加方便(插入删除算法统一了)。B选项的标识首节点的位置这个普通的单链表也可以做到。
栈和队列有相同的(B
C)A. 抽象数据类型
B. 逻辑结构
C. 存储结构
D. 运算
PS: 都是线性结构
设有一个空栈,栈顶指针为1000H,每个元素需要一个存储单元,经过push push pop push pop push pop push操作之后,栈顶的值为(A
B)A. 1002H
B. 1003H
C. 1004H
D. 1005H
**PS:**一共有5个push,三个pop,最后栈里面存在两个元素,指针需要向上抬两个单位(这题纯粗心)
三个不同的元素依次进栈,有(B
A)种不同的出栈序列A. 4
B. 5
C. 6
D. 7
**PS:**现在假设有三个元素ABC,有出栈顺序ABC CBA ACB BAC BCA,做这题的技巧就是在每次做抉择的时候分支,在草稿纸上画二叉树,每个节点里面画好栈中元素,未入栈元素,输出元素,然后最后汇总。
若一个栈是输入序列是P1 P2 P3…Pn,输出序列为1,2,3,4…n,若p3=1,则p1的值(C
A)、A. 可能是2
B. 一定是2
C. 不可能是2
D. 不可能是3
PS:由题意得,p3=1,说明p3是被第一个被弹出栈的,那么在p3被弹出之前,栈中元素为
[p1, p2, p3] // 右边是栈顶
弹出之后,栈中元素变为
[p1, p2] // 右边是栈顶
那么第二个弹出的元素必不可能为p1,所以选C
一个栈的输入序列为1,2,3…n,输出序列第一个元素为i,第j个元素为(D)
A. i - j - 1
B. i - j
C. j - i + 1
D. 不确定
PS:这题因为不确定答案被列出来,因为上面的流程中,元素没有完全入栈就出栈了,所以在出了第一个元素之后,后面的入栈出栈指令不确定,所以,无法确定出栈序列,所以无法缺点第j个出栈元素的元素大小。如果元素全部入栈的话,后面就只能出栈了,所以第j个出栈元素是知道的。(详见这题的上一题)
一个栈的入栈序列是1,2,3…n,出栈序列为p1,p2,p3…,若p2 = 3,则p3可能取值的个数为(C
A)个A. n - 3
B. n - 2
C. n - 1
D. 无法确定
PS:分析在当前栈出栈之后的栈顶元素。
已知p2 = 3所以3之后的值都有可能成为下一个出栈元素,
接下来分析1 2 3
首先p2 = 3,p3不可能等于3,排除
然后是1,先进栈1 2,第一个出2,p1 = 2,栈内剩余1,然后入栈3,栈内剩余1 3,然后出3, p2 = 3,栈内剩余1,如果下一步马上把1出了,那么p3就会取1
然后是2,先进栈1,马上出栈,p1 = 1,然后2 3 连续进栈,栈内剩余2 3 ,然后出3,p2 = 3,栈内剩余2,如果下一步马上把2出了的话,那么p3就会取2
分析结束,得出结论,p3会取除了3以外的所有值,取值可能数有n-1个
元素a,b,c,d,e依次进栈,元素可停留可出栈,直到所有元素出栈,在所有可能的出栈序列中,以元素d为开头的序列有(B
A)种A. 3
B. 4
C. 5
D. 6
PS:由题意得,出栈序列以d开头,所以在第一次出栈之前,栈内元素必定为
[a, b, c, d] // 右侧为栈头
出掉一个元素之后
[a, b, c] // 右侧为栈头
现在没有入栈的元素就剩下e,所以目前剩下的可执行指令有四个pop指令和一个push指令,(push指令不可放在最后),通过排列组合之后产生了4种结果,所以选B。
对于一个问题的递归算法求解和其相对应的非递归算法求解,(B
A)A. 递归算法通常效率高些
B. 非递归算法通常效率高些
C. 一样
D. 无法比较
PS: 递归算法还要使用空间来计算调用函数地址,还有很多重复计算,所以效率一般比非递归的低
下列说法中正确的是(A
D)A. 消除递归不一定需要栈
B. 对同一输入序列进行两种不同的合法入栈和出栈组合操作,所得的输出序列也一定相同
C. 通常使用队列来处理函数或过程调用
D. 队列和栈都是运算受限的线性包,只允许在表的两端进行运算
PS: 针对A选项,对于单项递归和尾递归而言可以使用迭代的方式来模拟(阶乘),D选项就是在玩文字游戏了,栈只能在表的一端进行运算。
已知操作符包括
+
-
*
/
(
)
,将中缀表达式a + b - a * ((c + d) / e - f) + g
转化为后缀表达式ab+acd+e/f-*-g+
时,用栈来存储临时的运算符,若初始栈为空,那么转化过程同时保存在栈中的运算符的最大个数为()A. 5
B. 7
C. 8
D. 11
PS: 这题纯纯的就是因为不会写,下面开始疏通思路,王道课本里面写了后缀转中缀的,中缀转后缀的会更加麻烦
首先说明机制开始按字符开始读取中缀式,碰到数字,直接输入,碰到运算符,如果栈中无元素,入栈,如果当前运算符优先度小于等于当前栈顶的运算符,退栈(前括号这个是特殊的,如果栈顶是前括号,又碰到了前括号,那么不会使当前栈顶的前括号出栈,而是直接入栈),直到碰到比自己优先度大的,如果碰到后括号,直接一直退栈,直到把碰到的第一个前括号出栈,(课本对优先度和前后括号的解释有点麻烦,我这里直接面向应用和机制解释)
然后开始遍历
a + b - a * ((c + d) / e - f) + g
碰到
a
,是数字,输出栈:[] // 右边是栈头 输入序列:a
碰到
+
是运算符,入栈栈:[+] // 右边是栈头 输入序列:a
碰到
b
,是数字,输出栈:[+] // 右边是栈头 输入序列:ab
碰到
-
,是运算符,它和+
优先度是一样的,+
出栈,-
入栈、栈:[-] // 右边是栈头 输入序列:ab+
碰到
a
,是数字,输出栈:[-] // 右边是栈头 输入序列:ab+a
碰到
*
,是运算符,它比-
优先度高,入栈栈:[-, *] // 右边是栈头 输入序列:ab+a
碰到两个
(
,是运算符,它比*
优先度高,入栈栈:[-, *,(, (] // 右边是栈头 输入序列:ab+a
碰到
c
,是数字,输出栈:[-, *,(, (] // 右边是栈头 输入序列:ab+ac
碰到
+
是运算符,运算符不会在意括号的优先度,入栈栈:[-, *,(, (, +] // 右边是栈头 输入序列:ab+ac
碰到
d
,是数字,输出栈:[-, *,(, (, +] // 右边是栈头 输入序列:ab+acd
碰到
)
,是运算符,泄洪式出栈,直到碰到第一个前括号(括号出栈后不输出到结果队列)栈:[-, *,(] // 右边是栈头 输入序列:ab+acd+
碰到
/
是运算符,运算符不会在意括号的优先度,入栈栈:[-, *,(, /] // 右边是栈头 输入序列:ab+acd+
碰到
e
,是数字,输出栈:[-, *,(, /] // 右边是栈头 输入序列:ab+acd+e
碰到
-
优先度比/
低,/
出栈,-
入栈栈:[-, *,(, -] // 右边是栈头 输入序列:ab+acd+e/
碰到
f
,是数字,输出栈:[-, *,(, -] // 右边是栈头 输入序列:ab+acd+e/f
碰到
)
,是运算符,泄洪式出栈,直到碰到第一个前括号(括号出栈后不输出到结果队列)栈:[-, *] // 右边是栈头 输入序列:ab+acd+e/f-
碰到
+
,是运算符,优先度比*
低,*
出栈,-
优先度和+
一样,也出栈,最后+
入栈栈:[+] // 右边是栈头 输入序列:ab+acd+e/f-*-
碰到
g
,是数字,输出栈:[+] // 右边是栈头 输入序列:ab+acd+e/f-*-g
到这里,算术表达式(中缀表达式)已经遍历完成,把栈中所有元素都倒出来
栈:[] // 右边是栈头 输入序列:ab+acd+e/f-*-g+
最后得出结果
ab+acd+e/f-*-g+
,程序结束
适用于压缩矩阵稀疏存储的两种存储结构为(A)
A. 三元组表 十字链表
B. 三元组表 邻接矩阵
C. 十字链表 二叉链表
D. 邻接矩阵 十字链表
PS: 解释一些上面的存储结构的特征
三元组表
:使用三元组存储数据,每一个成员包含了 行值,列值和val,可以通过这个三元组把其中的元素映射到二维数组中(PS:三元组本质是一维数组,通过三元组映射后的数据结构才是二维数组)
十字链表
:一个n维矩阵有n个链表,每个链表存储当前行的信息,每个链表中的成员包含行值,列值,val 右值和下值指针
邻接矩阵
:老数学概念了,本质是对称矩阵,也就是三角矩阵结构
二叉链表
:这个是用来表示二叉树结构的
一棵有n个节点的树的所有节点的度数之和(A
C)A. n - 1
B. n
C. n + 1
D. 2n
PS: 这题考察树的基本性质,(其实我就是纯粗心),这题先有度数后有节点数,节点数比度数多1,所以选A
下列说法中,正确的是(A
D)A. 在完全二叉树中,叶子节点的双亲的左兄弟(若存在)一定不是叶子节点
B. 任意一颗二叉树,叶子节点个数为度为2节点数减1,即n0 = n2 - 1
C. 完全二叉树不适合顺序存储结构,只有满二叉树适合
D. 节点按完全二叉树层序编号的二叉树中,第i个节点的左孩子的编号为2i
PS: 这题每一个选项都值得考究,A是对的,画一下图就可以知道了,B是错的,应该是n2 = n0 - 1,C这个完全不对了,D这个编号是从0开始还是从1开始都不知道,就很模糊,错误。
一棵有n个节点的二叉树采用二叉链存储结构,其中空指针数为(B
C)A. n
B. n + 1
C. n - 1
D. 2n
PS: 首先了解下什么是二叉链结构
也就是说一个节点有三个成员组成,其中lchild和rchild都是指向相应节点的指针,所以有n个节点的二叉树有2n个指针。
题目中让我们求空指针的个数,这个很难,我们可以逆向思维一下,求非空的指针的个数,这个很简单,就是求一棵树的指针数,发现指针数为n - 1,于是空指针就有n + 1个了。
已知一棵树有2011个节点,其叶节点个数为116,该树对应的二叉树中,无右孩子的节点个数是(D
A)A. 115
B. 116
C. 1895
D. 1896
PS:
首先了解这样一个概念就是普通树转化为二叉树的过程,就是在遍历树的时候往一个节点的左孩子插入原树的第一个孩子,往一个节点的右孩子插入下一个兄弟节点
nextsibi
这题看似无解,我们其实可以采取极端法来算
建立这样一颗树之后开始分析,发现前面的1895个节点和最后一层树的最后一个节点是没有
下一个兄弟节点
的,所以这些节点转化为二叉树节点后没有右孩子,所以没有右孩子的节点有1896个。
对于任意一颗高度为5且有10个节点的二叉树,若采用顺序存储结构保存,每个节点占1个存储单元(存放节点的数据信息),则存放该二叉树需要存储单元数量至少是(A
C)A. 31
B. 16
C. 15
D. 10
PS: 这个要在考虑最坏的情况的前提下尽量少用存储空间。假设有节点占用了第31个存储单元,就必须要动用31个存储单元。但是节点再怎么跳脱也不会出现在第6层,所以最多就是31个!
下列序列中,不能唯一确定一个二叉树的是(D
A)A. 层序 中序
B. 先序 中序
C. 后序 中序
D. 先序 后序
PS: 先序和后序的遍历顺序分别是
中左右
左右中
,虽然可以确定一棵树的根节点但是无法划分左右子树**(不要把这棵树想得太大,就是最小的一颗子树,只有两个节点)**
线索二叉树是一种(C
D)结构A. 逻辑
B. 逻辑和存储
C. 物理
D. 线性
PS: 年度迷惑题目,要解释起来是这样的:
线索二叉树本质是加上线索后的链表结构,它是二叉树在计算机内部的一种存储结构,所以是一种物理结构
n个节点的线索二叉树含有线索数(C
B)A. 2n
B. n - 1
C. n + 1
D. n
PS: n个节点的一棵树一共有2n个指针,原生就有n - 1个指针了,那么就剩下n + 1个指针没有利用,在描绘线索的时候会全部利用起来(第一个节点的前序和最后一个节点的后序会指向空值)
一个左子树为空的二叉树在先序化之后,会有几个空的链域(C
D)A. 不确定
B. 0
C. 1
D. 2
PS: 题目的意思是这个二叉树的根节点只有右孩子,所以在先序化之后根节点是第一个节点,它的左节点将指向它的前一个节点,又因为它没有,所以这个根节点的左指针会指向null,
还有另一个空的链域就是序列最后一位节点的右指针,因为先序遍历的最后一个节点必然是叶节点,叶节点的两个指针都没有指向,所以在序列化的时候会都用起。又因为最后一个节点没有下一个节点,所以这个指针指空。综上所述,一共有两个空指针
在线索二叉树中,下列说法不正确的是(D)
A. 在中序线索数中,若某节点有右孩子,则其后继节点是它的右子树最左下节点(node.right.left.left…)。
B. 在中序线索数中,若某节点有左孩子,则其前驱节点是它的左子树最右下节点(node.left.right.right…)。
C. 线索二叉树是利用二叉树的n + 1个空指针来存放节点的前驱和后继信息的。
D. 每个节点通过线索又可以直接找到它的前驱和后继
PS: 这题有点完文字游戏,好在D选项错得比较明显,后序线索二叉树查找其后继节点比较麻烦,因为二叉树节点没有存放其父节点的指针(如果某个节点的前驱刚好是它的右孩子,那么找它的后继节点时就需要回到父节点,此时需要利用栈结构回溯到父节点)
二叉树在线索化之后仍不能有效解决问题的是(D)
A. 先序线索求后继
B. 中序/求后继
C. 中序/求前驱
D. 后继/求后继
PS: 和上一题的问题是一样的,后继线索二叉树求后继还需要指向父节点指针。
若X是二叉中序树中一个有左孩子的节点,且X不为根节点,那么X的前驱是(C
D)A. X的双亲
B. X右子树的最左节点
C. X左子树的最右节点
D. X左子树的最右叶节点
PS: 又是玩文字游戏的一题,最右节点和最右叶节点的区别
二叉树有两个节点m n ,其中m是n祖先使用(C
A)可以找到m到n的路径A. 先序
B. 中序
C. 后序
D. 层序
PS: 后序遍历会回到父节点(如果上一个访问的节点是当前节点是右孩子,那么开始记录,然后回溯),此时记录所有的返回的父节点就可以记录路径了。
对二叉树开始连续编号(从1开始编号,遍历到下一个节点时编号自加),要求每个节点编号大于其左右孩子的编号,同一个节点的左右孩子中,左孩子的编号要小于右孩子的编号,可采用(C
A)标号A. 先序
B. 中序
C. 后序
D. 层序
PS: 这里是从1开始编号的由题意得,节点越靠后越大,最大的是根节点,根据后序遍历的左右中的顺序,我们发现,这刚好符合题意(左<右<中)
在二叉树的前序,中序,后序遍历中,所有的叶子节点的先后顺序(B)
A. 都不相同
B. 完全相同
C. 前序,中序相同,后序不同
D. 中序,后序相同,前序不同
PS:在一颗子树中,访问左右孩子的顺序都是相同的(标准的一颗子树就是一个根节点和两个孩子)
利用二叉链表存储森林的时候,根节点的右指针(D
C)A. 指向最左兄弟
B. 指向最右兄弟
C. 一定为空
D. 不一定为空
PS: 因为一片森林中可能只有一棵树,可能不止,如果只有一棵树的话,那么根节点就没有右指针,反之有。
设森林F对应的二叉树为B,它有m个节点,B的根为p,p的右子树节点数为n,那么森林F中第一课数有多少节点(A)
A. m - n
B. m - n - 1
C. n + 1
D. 条件不足,无法判断
PS: 这题的意思很明了,这个森林F中,有多棵树,所以根节点不算在总节点数中,所以B是错的,又因为p的右子树节点数为n,这表示森林F除第一课数4树以外的其他树的节点数之和为n,那么第一棵树的节点数就是m - n了。
设F是一个森林,B是由F变换来的二叉树,若F中有n个非终端节点,则B中右指针为空的节点有©个
A. n - 1
B. n
C. n + 1
D. n + 2
PS: 这题很抽象,首先明确非终端节点的含义,就是(在原森林中)不是叶子节点的节点,然后看题
首先看森林的根节点,最后一棵树必然没有右指针,然后看非根节点,F中有n个非终端节点,每一个非终端节点子树中(只包含这个节点和它的直系孩子)都会有一个孩子没有右指针(最后一个孩子)那么,一共就有n + 1个。
已知森林F及与之相对应的二叉树T,若F的先根遍历序列是abcdee,中根遍历是badeec,那么T的后根遍历序列为(C
B)A. badeec
B. bdeeca
C. beedca
D. eedcba
PS: 首先了解下这个不怎么用的中根遍历,这个其实就是后根遍历,所以这只是后根遍历的一种叫法。
按照这个规则,我们就可以画出相应的树了,然后构造对应的二叉树,中序遍历,完事!
在二叉排序树中进行查找的效率与(A
D)有关A. 二叉排序树的深度
B. 节点个数
C. 被查找节点的度
D. 存储结构
PS: 树的深度比存储结构更加实在一些(D选项的存储结构不要忘记了,这是第一章的内容,指的是链式存储或顺序存储啥的,和本题无关)
含有20个节点的平衡二叉树的最大深度为(C
B)A. 4
B. 5
C. 6
D. 7
PS: 一颗平衡二叉树并不是意味着它要像完全二叉树一样把所有的点填满。平衡二叉树的最大节点数遵循斐波那契数列
F(n) = F(n - 1) + F(n - 2) + 1 (其中 n0 = 0 n1 = 1 n2 = 2 前两行必须填满,通过如此构建,树中所有非叶子节点的平衡因子均为1),通过计算,我们得出构造5层平衡二叉树至少要12个,构造六层平衡二叉树至少要20个,那么答案直接出来了。
补充:就以上面为例,假设如果一共有18个节点,那么这些节点就要塞到第五层上面,如果强行放到第六层,那么必定不平衡。这。
具有5层节点的AVL至少有(B)节点
A. 10
B. 12
C. 15
D. 17
PS: 和上题一样,斐波那契数列套一下。(PS:AVL就是自平衡二叉查找树)
若平衡二叉树的高度为6,且所有非叶子节点的平衡因子均为1,该平衡二叉树的节点总数为(B)
A. 12
B. 20
C. 32
D. 33
PS: 这个树就是让你求固定层数的维持平衡二叉树的最少节点数,和前一题是一样的
将关键字1 2 3 4 5 6 7依次插入初始为空的平衡二叉树T,则T中平衡因子为0的分支节点个数为(D
A)A. 0
B. 1
C. 2
D. 3
PS: 算平衡二叉树的分支节点不要带入叶节点。
一颗哈夫曼树一共有215个节点,对其进行哈夫曼编码,一共可以得到(B
C)不同的码字A. 107
B. 108
C. 214
D. 215
PS: 哈夫曼树只有度为2和度为0的节点 N = n0 + n2 N-1 = 2 * n2 n2 = 107 n0 = 108
又因为所有的码字都位于叶子节点处,所以答案为108
现有一颗无重复关键字的平衡二叉树(AVL)对其进行中序遍历可得到一个降序序列,下列关于该平衡二叉树的叙述中,正确的是(D
C)A. 根节点的度一定为2
B. 树中最小元素一定是叶节点
C. 最后插入的一定是叶节点
D. 树中最大元素一定没有左子树
PS: 这棵树是二叉排序树,D选项直接对了,C选项的话如果最后插入的节点导致树的不平衡会调整,C错
已知二叉排序树如下结构,元素之间大小关系为(C
D)A. x1
B. x1
C. x3
D. x4
PS: 自己算,举个例子,x2比x1大,那么x2下面的所有节点都比x1大,以上!
在一个任意非空平衡二叉树T1中,删除某个节点v之后调整形成平衡二叉树T2,再将v插入,形成平衡二叉树T3,那么(A
D)1 如果T1是叶节点,T1 T3可能不相同
2 如果T1不是叶节点,T1 T3一定不相同
3 如果T1不是叶节点,T1 T3一定相同
A. 1对
B. 2对
C. 1 2 对
D. 1 3 对
PS:实际上2 3 都不对,举出反例就可以了,实际上不相同的情况占多数,在删除某个非叶节点之后,如果插入节点的时候不经过调整,那么T1 T3一定不相同,如果调整了,那么就有可能相同。
图中有关路径的定义,正确的是(A)
A. 由顶点和相邻顶点序偶构成的边所形成的序列
B. 由不同的顶点构成的序列
C. 由不同的边形成的序列
D. 以上都不对
PS: 基础概念
下列关于图的叙述,正确的是(C
D)1。 回路是简单路径
2。 存储稀疏图,用邻接矩阵比邻接表更省空间
3。 若有向图中存在拓扑序列,则该图不存在回路A. 2对
B. 12对
C. 3对
D. 13对
PS: 1是错的因为回路对应路径,简单回路对应简单路径,如果是一个回路的话,就有可能出现自己指向自己的回路,那么就不是简单路径了
下列关于无向连通图特性的叙述中,正确的是(A
D)1。 所有顶点的度之和为偶数
2。 边数大于顶点数减一
3。 至少有一个顶点的度为1A. 1对
B. 2对
C. 12对
D. 13对
PS: 3是错的,如果出现所有顶点恰好构成一个大环的话,就没有顶点度为1的节点。
下列关于图是叙述正确的是(C
D)A. 强连通有向图的任何顶点到其他所有顶点都有弧
B. 图的任意顶点入度等于出度
C. 有向完全图一定是强连通有向图
D. 有向图的边集的子集和顶点集的子集可构成原有向图的子图。
PS: 这题考察基本概念,说明一下其中弧的意思是
- 弧:指的是有向图里面的**边,**他是有明确方向的。如果是无向图的边,直接叫做“边”。比如有向图的 v1 结点到 v2 结点的弧可能是:
; 但是实际上,强连通有向图一个节点到任何顶点上都有路径,但是并不是通过一条弧就可以直接到达
设图的邻接矩阵A如下所示,各顶点的度依次是(C
B)[0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0]
A. 1 2 1 2
B. 2 2 1 1
C. 3 4 2 3
D. 4 4 2 2
PS: 如果描述的是一个节点的度的话那么就包含入度和出度,所以只有入度是不对的
对于一个有n个顶点的图,若是连通无向图,其边的个数至少为(),若其是强连通有向图,其边的个数至少为() (A
B)A. n - 1, n
B. n - 1, n(n - 1)
C. n, n
D. n, n(n - 1)
PS: 第一个选项毋庸置疑,就是n - 1,第二个选项需要注意一个概念,那就是需要注意强连通图和完全图的区别,完全图是图中所有该连的线都已经连完了,强连通图并没有,也就是说完全图包含强连通图。所以边个数为n的情况就是一系列边形成一个环,最后每个节点都可以到达其他节点。
在有n个节点的有向图中,每一个顶点的最大的度可以达到(D
B)A. n
B. n - 1
C. 2n
D. 2n - 2
PS: 注意题目里面说的是有向图,所以度包含入度出度,是2(n - 1)
具有6个顶点的无向图,当有(D
C)边时可以确保是一个连通图A. 8
B. 9
C. 10
D. 11
PS: 注意审题,这里说是确保是一个连通图,所以不管怎么连都是连通的,所以只需要这样,先准备一个有5个顶点的无向完全图,然后再随意选择一个节点和第6个节点相连,就可以了,所以是10 + 1 = 11个。
设有无向图G=(V, E) G’=(V’, E’) 若G‘是G的生成树,下列不正确的是(D
C)
- G’是G的连通分量
- G‘是G的无环子图
- G‘是G的极小连通子图且 V’=V
A. 1 2
B. 3
C. 2 3
D. 1
PS: 1是错的,任何连通图的连通分量只有一个,即是其自身,非连通的无向图有多个连通分量。
带权有向图G用邻接矩阵存储,则Vi的入度等于邻接矩阵的(D
C)A. 第i行非∞的元素个数
B. 第i列非∞的元素个数
C. 第i行非0且非∞的元素个数
D. 第i列非0且非∞的元素个数
PS: 不要看错入度和出度!
用邻接表法存储图所需的空间大小为(A
C)A. 和图的顶点数和边数有关
B. 和图的边数有关
C. 和图的顶点数有关
D. 和边数的平方有关
PS: 这题错的拉出去枪毙罢了!(自裁!!!)不要看错邻接表和邻接矩阵,认真读题。
在有向图的邻接表的存储结构中,顶点v在边表中出现的次数为(C
A)A. 顶点v的度
B. 顶点v的出度
C. 顶点v的入度
D. 依附于顶点v的边数
PS: 每个顶点链表的长度代表了该顶点的入度,反过来,顶点v在边表中出现了意味了它被某个节点连了,每连一次算一个入度。
对邻接表的叙述中正确的是(D)
A. 无向图的邻接表中,第i个顶点的度为第i个链表中节点数的两倍
B. 邻接表操作比邻接矩阵更方便
C. 邻接矩阵操作比邻接表更方便
D. 求有向图的节点的度,必须遍历整个邻接表
PS: A不用看就是错的,无向图不分入度和出度,第i个顶点的度就是第i个链表的节点数
**(重点,有争议)**关于广度优先算法,说法正确的是(A
C)
- 当各边的权值相等的时候,广度优先算法可以解决单元最短路径问题
- 当各边的权值不相等的时候,广度优先算法可以解决单元最短路径问题
- 广度优先算法类似于树中的后序遍历算法
- 实现图的广度优先算法时,使用的数据结构是队列
A. 1 4
B. 2 3 4
C. 2 4
D. 1 3 4
PS: 4想都不用想,就是对的,这题主要看1 2项,因为广度优先算法不能考虑边的权值,无法比较与某个节点相连的边的权值,所以适合没有权值的图的单元最短路径问题的求解。
对于一个非联通无向图G,采用深度优先遍历访问所有的节点,调用DFS的次数为(C
A)A. 顶点数
B. 边数
C. 连通分量数
D. 不确定
PS: 严格来说次数就是C,因为顶点数并不严谨,本来DFS会for循环所有的节点,但是如果前面的DFS遍历了一些节点,在后面的for循环出现,那么不会在已经遍历的节点上再遍历,所以,最后只会调用的次数等同于连通分量数。
判断有向图中是否有回路,除了利用拓扑排序以外,还可以使用(C
A)A. 求关键路径的方法
B. 求最短路径的迪杰斯特拉算法
C. DFS
D. BFS
PS: 求关键路径的方法最后只会得出结论,无法判断是否有环,使用DFS,如果在遍历的时候出现已经遍历的节点,那么就判断有环。
设无向图G = (V, E) G’ = (V’, E’) ,若G’是G的生成树,下列说法错误的是(B
C)A. G’是G的子图
B. G’是G的连通分量
C. G’是G的极小连通子图且V = V’
D. G’是G的一个无环子图
PS: B必定是错的,如果这个无向图不是完全连通的,G’严格来说就是一个生成森林,并不是单独一颗树,更不是原图的连通分量。
图的广度优先生成树的树高比深度优先生成树的树高(A)
A. 小或相等
B. 小
C. 大或相等
D. 大
PS: https://blog.csdn.net/qq_25775935/article/details/88697263
(重点)下列关于最小生成树的叙述,正确的是(A
B)
- 最小生成树的代价唯一
- 所有权值最小的边一定会出现在所有最小生成树中
- 使用prim算法从不同顶点开始得到的最小生成树一定相同
- 使用prim算法和kruskal算法得到的最小生成树总不相同
A. 1
B. 2
C. 1 3
D. 2 4
PS: 4必定错,3太绝对了,必错,随便举一个反例,大概率不能够印证,2中如果较小边会使当前的图结构产生环的话,那么就会忽略这个边,选择一个相对大点的。1选项中代价的含义是树的所有权值之和,这里要记住一个概念就是最小生成树的权值总和一定是相同的,尽管生成树的结构会不同
下列(A
D)可以判断一个有向图是否有环
- DFS 2. 拓扑排序 3. 求最短路径 4. 求关键路径
A. 1 2 4
B. 1 3 4
C. 1 2 3
D. all
PS: 这题出得不是很好,有争议。
求最短路径允许有环,所以不会刻意去判断是否有环,
求关键路径的时候其实已经默认这个图是有向无环图,可能代码里面不会再去检查是否有环。
下列关于拓扑排序的说法,错误的是(D
C)
- 若某个有向图有环,那么一定不存在拓扑排序
- 在拓扑排序算法中,暂存入度为0的节点,可以使用栈,队列
- 若有向图的拓扑排序算法序列唯一则每一个顶点的入度和出度最多为1。
A. 1 3
B. 2 3
C. 2
D. 3
PS: 3是错的,拓扑排序唯一不一定这个有向图就是链式结构。2是对的,拓扑排序存放当前入度为0的节点用什么数据结构都可以,当前随机取入度为0的节点也可以,因为拓扑排序并不是唯一的。
关于图的说法,正确的是(C
D)
- 有向图中顶点V的度等于其邻接矩阵中第V行中1的个数。
- 无向图的邻接矩阵一定是对称矩阵,有向图的邻接矩阵一定是非对称矩阵
- 在图G的最小生成树中,某条边的权值可能比未选边大
- 若有向无环图的拓扑序列唯一,那么可以唯一确认该图。
A. 1 2 3
B. 3 4
C. 3
D. 4
PS: 1错,因为这只有出度,2错,一眼看出来,3对,如果这个较小边会导致当前图结构产生环,那么舍弃,选择较大的。4错,无环图有唯一拓扑序列,可能是链式结构可能不是。
(反复琢磨)下列关于关键路径说法不正确的是(C)
A. 求关键路径是以拓扑排序为基础的
B. 一个事件的最早发生时间是以该事件为始的弧的活动的最早开始时间相同
C. 一个事件的最迟发生时间是以该事件为尾的弧的活动的最迟开始时间与该活动的持续时间的差
D. 关键活动一定在关键路径上。
PS: 文字游戏,事件就是表示主要活动结束的那一点,活动表示从一个事件到另一个事件之间的过程
一个事件的最迟发生时间是以该事件为尾的弧的活动的最迟开始时间,最迟结束时间与该活动的持续时间之差。最迟开始时间是事件为头(也就是箭头的线的终点)活动的最迟允许开始时间与该活动持续时间的差。
若用邻接矩阵存储有向图,矩阵中主对角线以下的元素均为0,关于该图的拓扑序列结论是()
A. 存在,且唯一
B. 存在,且不唯一
C. 存在,可能不唯一
D. 无法确定是否存在
PS:由题意得,这个图结构不存在环,然后可能有多个连通分量,那么一开始入度为0的节点就有多个,那么拓扑图就不会是唯一的。
下列所示的AOE往包含如下活动,活动d的最早开始时间和最晚开始时间分别是(C
A)A. 3 7
B. 12 12
C. 12 14
D. 15 15
PS: 求最早开始时间,就是求1到2的关键路径长度,为12,求最迟开始时间,先求起点到终点的关键路径,长度为27,然后求d活动的终点----事件4的最迟结束时间,27 - 6 = 21,所以时间4的最迟结束时间为21,然后21 - 7 = 14,这个14就是活动d的最迟开始时间了。
用有向无环图描述表达式(x + y)*((x + y) / x)需要(A
C)个顶点A. 5
B. 6
C. 8
D. 9
其实相同的操作可以复用,分别需要 节点x 节点y 节点+ 节点* 节点/一共5个
对长度为3的顺序表进行查找,若查找的元素的概率分别为 1/2 1/3 1/6,则查找任意元素的平均长度为(A
D)A. 5/3
B. 2
C. 7/3
D. 4/3
PS: 计算概率不一的顺序表的平均查找长度计算公式,先计算每一个元素的查找长度,上题每一个元素的查找长度分别为 1 2 3,然后和概率一起计算 res = (1 * 1/2) + (2 * 1/3) + (3 * 1/6) = 5 / 3
折半查找过程对应的判断树为(B
A)A. 最小生成树
B. 平衡二叉树
C. 完全二叉树
D. 满二叉树
PS: 不用解释,自己画一下然后就可以排除其他选项了
下列二叉树中,可能成为折半查找二叉树判断树的是(A
B)PS: 折半查找判断树本质是二叉排序树,可以使用中序写入数字,如果符合折半查找的就是对的,结果只有A是符合的。
对2500个记录的索引顺序表(分块表)进行查找,最理想的块长是(A
D)A. 50
B. 125
C. 500
D. Math.ceil(log2(2500))
PS: 题目中块查找和块内查找都是使用顺序查找,假设块长为n ,那么就有 2500 / n 块,索引表ASL (2500 / n + 1) / 2 =,块内ASL (n + 1) / 2, 总ASL(1250 / n + n / 2 + 1),求导,得n = 50时,取极值,所以最理想的块长是50
下列序列中,不可以作为折半查找中关键字比较序列的是(A
C)A. 500 200 450 180
B. 500 450 200 180
C. 180 500 200 450
D. 180 200 500 450
PS: 注意审题这里是比较序列,选项中的不是整个数列!本题通过画出判断路径就可以了,如果树结构不符合二叉排序树的基本要求的那就是错的。
下图是一颗(A
C)A. 4阶B树
B. 4阶B+树
C. 3阶B树
D. 3阶B+树
PS: 有一个节点有三个关键字,所以会延伸出4个子树,所以是4阶。
下列关于m阶B树的说法,正确的是()
- 每个节点至少有2颗非空子树
- 树中每个节点至多有m - 1个关键字
- 所有叶节点都在同一层
- 插入一个元素引起B树分裂,树就会长高一层
A. 1 2
B. 2 3
C. 3 4
D. 1 2 4
PS: 这题只解释4,插入一个元素引起B树分裂,如果树中节点还有没被填满的元素的话,那么树就不会长高。
在一棵高度为2的5阶B树中所含关键字的个数至少为(A
D)A. 5
B. 7
C. 8
D. 14
PS: 高度为1的5阶B树最多有4个关键字,再加一个数据,树的高度就必须+1了,所以至少5个
已知一棵5阶B树共拥有53个关键字,树最大高度为(C
D),最小高度为(BC)A. 2
B. 3
C. 4
D. 5
PS: 5阶B树,一个节点最多有(5-1)=4个关键字,最少有(Math.ceil(5 / 2) - 1)= 2个关键字,那么开始分配
先分析最大高度,逐层分析,
根节点最少有1个关键字,分出两个子树,
第二层有2个节点,最多有4个关键字,分出6个子树
第三层有6个节点,最多有12个关键字,分出18个子树
第四层有18个节点,最多有36个节点,分出54个子树关键字累加,发现前四层刚好53个节点,那这个B数最大高度为4
然后分析最小高度,逐层分析
根节点最多4个关键字,分出5个子树
第二层有5个节点,最多有20个关键字,分出25个子树
第三层有25个节点,最多有100个关键字,分出125个子树不用想,最小高度就是3层。
下列应用适合使用B+树的是(B
C)A. 编译器的词法分析
B. 关系数据库系统中的索引
C. 网络中路由表快速查找
D. 操作系统的磁盘空闲块管理
PS: A使用编译器中有穷自动机和语法树,C使用高速缓存路由表压缩技术,D使用空闲空间链表
依次将关键字5 6 9 13 8 2 12 15 插入初始为空的4阶B树后,根节点包含关键字为(B
D)A. 8
B. 6 9
C. 8 13
D. 9 12
PS: 自己画一遍,插入原则就是尽量把元素往下面插,如果满了,拆分,把这个超负荷节点的第(Math.ceil(m / 2))个节点往后的所有节点不动,动它的前一个节点,往上放,组成新的树。
只能在顺序存储结构中进行的查找方法是(B
A)A. 顺序查找法
B. 折半查找法
C. 树形查找法
D. 散列查找法
PS: 顺序查找在链式结构上也可以,树形查找在顺序结构和树形结构都可以,散列查找解决冲突的方式,利用了顺序结构,使用拉链法的时候也会用到链表。
使用开放定址法散列到同一个地址后引起堆积问题由于(C
A)引起的A. 同义词之间发送冲突
B. 非同义词之间发送冲突
C. 同义词或非同义词之间发送冲突
D. 散列表溢出
PS: 同义词堆积这个很好解释,多个元素使用定址函数之后,得到的值是一样的,非同义词堆积是在一个元素原本的映射地址被别的非同义词在处理冲突之后放在这个位置导致新的冲突的产生。
下列关于散列冲突的处理方法的说法中,正确的是(A
C)
- 采用再散列法处理冲突不容易产生聚集
- 采用线性探测法处理冲突时,所有同义词在散列表中一定相邻。
- 采用链地址法处理冲突时,若限定在链首插入,则插入任一元素需要的时间都是相同的
- 使用链地址法处理冲突容易引起聚集现象
A. 1 3
B. 1 2 3
C. 3 4
D. 1 4
PS: 1是对的,因为使用再散列法是跳着找地址的,避免了聚集。
4发生冲突不代表引起聚集现象
采用开放定址法解决冲突的散列查找中,发生聚集的主要原因是(D
C)A. 数据元素过多
B. 负载因子过大
C. 散列函数选择不当
D. 解决冲突的方法选择不当
PS: 首先明白一个概念,什么是聚集:
- 所谓聚集,就是非同义词之间冲突了叫聚集,那么这就和散列函数就无关了
现有长度为11,且初始为空的散列表HT,散列函数是H(key) = key % 7,采用线性探查(线性探测再散列)法解决冲突,将关键字 87 40 30 6 11 22 98 20依次插入,HT查找失败的平均查找长度为(C)
A. 4
B. 5.25
C. 6
D. 6.29
PS: 先写出插入之后的表数据
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 98| 22| 30| 87| 11| 40| 6 | 20| | | |
其他元素都是对号入座的,只有最后一个20产生了冲突,后移了一位。
然后是查找,查找失败意味着拿一个表中不存在的元素来找,如果没找到就会先默认是冲突了,开始再线性探测,直到探测到第8个位置之后,还没找到,宣告查找失败。
然后这个随机数(非表中数)经过散列函数映射之后到了表中0—6的位置,分别需要 9 8 7 6 5 4 3 次查找才会宣告失败,所以,最后平均就是6次。
对同一待排序序列分别进行折半插入排序和直接插入排序,两者之间可能的不同之处是(D)
A. 排序总趟数
B. 元素移动次数
C. 使用辅助空间的数量
D. 元素之间的比较次数
PS: 虽然我写对了,但是感觉这是一道易错题,A选项排序总趟数都是一样的,都是n,由最外层的for循环决定。B选项两个排序其实是一样的,都是找到一个位置然后插入,不同的是比较次数,直接插入比较次数在n–n^2次,折半查找是稳定保持在log2(n)次
在下列算法中()算法可能出现以下情况—在最后一趟开始之前,所有元素都不在最终位置
A. 堆排序
B. 冒泡排序
C. 直接插入排序
D. 快速排序
PS: A堆排序不用说,每次取最大值放到最后,冒泡排序则是每次取到最小的,放到最前面,快排每次都会把中间元素的位置确定,直接排序是不对的,举个例子,下面的数组是直接插入排序在最后一趟排序开始之前的样子
[2, 3, 5, 7, 9, 4, 1]
排完序之后是这样的
[1, 2, 3, 5, 7, 9, 4]
这就导致了后面所有数的位置都发生变动
折半插入排序的时间复杂度(C)
A. O(N)
B. O(Nlog2(N))
C. O(N^2)
D. O(N^3)
PS: 时间复杂度任然是O(N^2),因为这个排序只是改变了比较次数,移动的次数没有发生变化
为实现快速排序算法,待排序序列宜采用的存储方式为(A)
A. 顺序存储
B. 散列存储
C. 链式存储
D. 基数存储
PS: 这题比较概念,就拿出来了,绝大多数的排序只适合内部排序,快排需要频繁地交换前后数据,所以适合顺序存储。
PS: 基数存储根据ascii码对字符串排序的一种方法。
下列序列可能是执行第一趟快排后的结果是(C
D)I. {68,11,18,69,23,93,73}
II.{68,11,69,23,18,93,73}
I1I. {93,73,68,11,69,23,18}
IV. {68,11,69,23,18,73,93}A. 1 4
B. 2 3
C. 3 4
D. 4
PS: 这种题目只要看某个数的左边的数是否都小于这个数,右边的数是否都大于这个数或者左边的数是否都大于这个数,右边的数是否都小于这个数,也需要考虑从大到小排序的可能。C选项是易错点,我们看73,它的左边只有93大于它,右边的所有数都小于它,那么就符合。
不可能是排序第二趟的结果的是(D
A)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,60PS: 和上一题不一样的是,这一题需要找两个key,符合分堆条件。(没什么知识点,仔细即可,一个一个数字看过去~!!)
设线性表中每个元素有两个数据项k1和k2,现对线性表按以下规则进行排序:先看数据项k1,k1值小的元素在前,大的元素在后;在k1值相同的情况下,再看k2,k2值小的在前,大的元素在后。满足这种要求的排序方法是(D
C)。A. 先对k1插排,再对k2选排
B. 先对k2插排,再对k1选排
C. 先对k1选排,再对k2插排
D. 先对k2选排,再对k1插排
PS: 这就是某种意义上的基数排序,先排个位数,再排十位数,所以先确定先是对k2排序,再是对k1排序,然后再选择排序方法,选项中只有选排和插排,选排是不稳定的,插排是稳定的,所以在第二次排序的时候切勿不可打乱第一次排序的顺序,所以第一次选择选排,第二次选择插排。
向有n个节点的堆中插入一个新元素的时间复杂度是(C
D),删除一个元素的时间复杂度是(CD)A. O(n)
B. O(n^2)
C. O(log2(n))
D. O(nlog2(n))
PS: 插入一个新元素的时候采用向上比较法,最多的比较次数是Math.ceil(log2(n + 1) - 1),所以,时间复杂度是O(log2(n))
删除一个元素的时候,要把堆中最后一个元素塞到这个被删除的位置,然后开始向下调整,调整一次,所以时间复杂度是O(log2(n))
记录n个记录的初始堆,时间复杂度为(A
D),对n个记录进行堆排序,最坏情况下的时间复杂度(D)A. O(n)
B. O(n^2)
C. O(log2(n))
D. O(nlog2(n))
PS: 在建堆过程中需向下调整,最上层一个元素,调整log2(n + 1)次,第二层有两个元素调整log2(n + 1) - 1次…依次类推,最后,累加,得到结果s = 2n - 2 - log2(n),所以时间复杂度为O(n)。
已知小根堆{8, 15, 10, 21, 34, 16, 12},删除关键字8之后重建堆,在此过程中,关键字比较次数(C
B)A. 1
B. 2
C. 3
D. 4
PS: 删除8之后,把数组最后一位拿过来替到8的位置,开始向下调整,第一次,先比较8的孩子15 10,发现10更小,第二次再拿10和12比较发现10更小,12和10交换位置,继续深入孩子比较然后发现12只有左孩子16,第三次12和16比较,发现12更小,不调整,比较结束,一共比较3次。
下列排序不需要对关键字进行排序的是(C)
A. 快排
B. 归并排序
C. 基数排序
D. 堆排序
PS: 其他的排序都要拿排序项的key进行比较,而基数排序是拿关键字的各位的大小进行比较。
对10TB文件进行排序,应该使用(D
C)排序A. 希尔排序
B. 堆排序
C. 快排
D. 归并排序
PS: 外部排序是在内存一次性放不下的时候用的,10TB很大,所以适用外部排序,所以 选D。
一组经过第一趟二路排序后的数组记录的关键字为{25 50 15 35 80 85 20 40 36 70},其中包含5个长度为2的有序表,用二路归并进行第二趟排序后的结果是(B)
A. 15,25,35,50,80,20,85,40,70,36
B. 15,25,35,50,20, 40,80,85,36,70
c.15.25.50.35,80,85,20,36,40,70
D.15,25,35,50,80,20,36,40,70,85PS: 二路归并回溯的时候两个两个合并,如果碰到最后一个数组多余的话就放着不管,那么上面的第二次分组是{25 50 15 35} {80 85 20 40} {36 70}
若要求排序是稳定的,且关键字是实数,则在下列排序方法中应选(A)
A. 直接插入排序
B. 选择排序
C. 基数排序
D. 快速排序
PS: 先排除不稳定的算法BD,然后再看AC,由于基数排序无法应付double类型和float类型的数据,所以不可以使用基数排序
时间复杂度可以达到线性时间的是(冒泡排序,直接插入排序)
PS: 解释一下概念----线性时间复杂度,就是时间复杂度为线性阶O(n)。
一般情况下,以下查找效率最低的数据结构是(C)
A. 有序顺序表
B. 二叉排序树
C. 堆
D. 平衡二叉树
PS: 堆是用于排序的,但查找起来是无序的,很难找到规律以至于需要每个元素遍历过去。
如果把顺序存储改成链式存储,排序算法时间效率会降低的是(D)
- 插排
- 选排
- 冒泡排序
- 希尔排序
- 堆排
A. 1 2
B. 2 3
C. 3 4
D. 4 5
PS: 1 2 3都是顺序进行的时间复杂度都是O(n^2),只需要用for循环一个一个元素有序地查看即可完成,这样的操作在链表中使用next指针,再加上temp指针保存临时位置信息一样可以完成,无需多余的操作。
而4,5利用了顺序存储的随机访问的特性,这样在链表中还会增加前进后退的操作,排序算法时间效率会降低。
排序的趟数和原始状态有关的排序排序方法是(C)
A. 插入
B. 选择
C. 冒泡
D. 基数
PS: 插排,选择排序不管数据怎么样,都要走n - 1趟,基数排序不管数据状态怎么样,该分堆的还是得分堆,冒泡排序在数据基本有序的时候几乎不用跑趟(可以设置判断项,如果走的某一趟下来是有序的,那么结束排序),如果是逆序的(冒泡排序最差情况)那么就要排n-1趟。
比较次数 与序列初态 无关 的算法是:二路归并排序、简单选择排序、基数排序
比较次数 与序列初态 有关 的算法是:快速排序、直接插入排序、冒泡排序、堆排序、希尔排序排序趟数 与序列初态 无关 的算法是:直接插入排序、折半插入排序、希尔排序、简单选择排序、归并排序、基数排序
排序趟数 与序列初态 有关 的算法是:冒泡排序、快速排序
对于大部分已经有序的数组排序时,直接插入比简单选择排序效率更高是因为(A)
- 直接插排的比较次数更少
- 直接插排需要的辅助空间更小
- 直接插排的元素移动次数更少。
A. 1
B. 3
C. 1 2
D. 1 2 3
PS: 2是错的,因为它们的使用辅助空间都是1,都是拿来保存临时数据的。3是错的,简单选择的元素移动次数永远小于等于插排,因为在选排每一次找到一个最小元素的时候只需要移动一次,而插排需要移动不止一次。
举个例子
[1, 2, 3, 4, 7, 5, 6, 8]
这样的数组如果使用直接选择排序的话,只需要在第五次遍历的时候把7和5对调一下就可以了,而插排会在第6,7,8次遍历的时候分别让7和5,6对调,一共交换2次,所以3不成立