【数据结构】数据结构纠错本
标签(空格分隔):【考研纠错本】
对数据序列(8,9,10,4,5,6,20,1,2)采用(由后向前次序的)冒泡排序,需要进行的趟数(遍数)至少是()
A.3
B.4
C.5
D.8
答案: C C C
冒泡排序:它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序错误就把他们交换过来。
第一趟之后的序列: 1 8 9 10 4 5 6 20 2
第二趟之后的序列: 1 2 8 9 10 4 5 6 20
第三趟之后的序列: 1 2 4 8 9 10 5 6 20
第四趟之后的序列: 1 2 4 5 8 9 10 6 20
第五趟之后的序列: 1 2 4 5 6 8 9 10 20
此时已经排好顺序,因此答案为 至少 5 趟。
以下哪个数据结构不是多型数据类型()
A.栈
B.广义表
C.有向图
D.字符串
答案: D D D
多型数据类型就是数据元素的类型不确定。字符串中每个元素始终是字符,不会是别的类型。
设线性表非空,采用下列__________所描述的链表可以在 O ( 1 ) O(1) O(1)时间内在表尾插入一个新结点。
A. 带表头结点的单链表,一个链表指针指向表头结点
B. 带表头结点的单循环链表,一个链表指针指向表头结点
C. 不带表头结点的单链表,一个链表指针指向标的第一个结点
D. 不带表头结点的单循环链表,一个链表指针指向表的第一个节点
答案: B B B
在表尾插入一个结点,现在表头后添加一个新表头,再把原表头转换为一个新的结点。
假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,则可共享相同的后缀存储空间。
例如,“loading”和“being”的存储映像如下图所示。
设str1和str2分别指向两个单词所在单链表的头结点,链表结点结构为。
请设计一个时间上尽可能高效的算法,找出由str1和str2所指的两个链表共同后缀的起始位置(如图中字符i所在结点的位置p)。
要求: (1)给出算法的基本设计思想。 (2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。 (3)说明你所设计算法的时间复杂度。
解答:
基本思想:1> 分别求出 str1 和 str2 所指的两个链表的长度 l1 和 l2. 2> 将两个链表表尾对齐:令指针 p, q 分别指向 str1 和 str2 的头节点。如果 l1 > l2 ,那么令 p 指向链表中的第 l1 - l2 + 1 个结点;如果 l1 < l2,那么令 q 指向链表中的第 l2 - l1 + 1 个结点;如果 l1 == l2 那么 p和 q 所指的结点到尾部的长度相等。 3> 反复将 p 和 q 进行比较,如果不相等则同时后移,当 p 和 q 指向同一个结点时,该结点便是共同后缀的起始位置。
typedef struct Node{
char data;
struct Node *next;
}SNode;
SNode *FindSame(SNode *str1, SNode *str2){
int l1, l2;
SNode *p,*q;
p = str1->next; q = str2->next;
int l1,l2; l1 = l2 = 0;
while( p){
l1++;p=p->next;
}
while( q){
l2++;q=q->next;
}
p = str1->next; q = str2->next;
if( l1 > l2)
for( int i = 0; i < l1 - l2; i++)
p = p->next;
else if( l1 < l2)
for( int i = 0; i < l2 - l1; i++)
q = q->next;
//compare
while( p && p->data != q->data){
p = p->next;
q = q->next;
}
return p;
}
时间复杂度: O ( m + n ) O(m+n) O(m+n)
在顺序表的动态存储定义中需要包含的数据成员是()
I. 数组指针 ~~~~~~~~~~~~~~~ II. 表中元素个数n
III. 表的大小maxSize ~~~~~~ IV. 数组基址base
A. I 、II
B. I 、II、IV
C. I 、II、III
D. 全部
答案: C C C
在顺序表的动态定义中,存储空间通过执行 malloc 或者 new 动态分配,所以不需要数组基址。
若一个栈的输入序列为1,2,3,…,n,输出序列的第一个元素是i,则第j个输出元素是______。
A.i-j-1
B.i-j
C.j-i+1
D.不确定
答案: D D D
i出栈时,1,2…i-1 都在栈内,但是不排除 i + 1之后的元素进栈。因此不确定。
对于链式队列,在执行入队操作时()
A. 仅需修改头指针
B. 仅需修改尾指针
C. 头、尾指针都需要修改
D. 头、尾指针可能都要修改
答案: D D D
对于链式队列,一般而言只需要修改尾指针。但是当向 空队列 入队时,队头指针和队尾指针均需要修改。
最适合用做链式队列的链表是______。
A.带有队头指针和队尾指针的循环单链表
B.带有队头指针和队尾指针的非循环单链表
C.只带队头指针的循环单链表
D.只带队头指针的非循环单链表
答案: B B B
由于队列需要在双端进行操作,所以只有 队首指针 不合适。A,循环链表有些多余。
是否可以用两个栈模拟一个队列?反之,是否可以用两个队列模拟一个栈?
答案:两个栈可以模拟一个队列,但是两个队列不能模拟一个栈。
栈是一种先进后出的数据结构,可以使用一个栈把一个输入序列逆转,然后使用另外一个栈把逆转后的序列再逆转回来。
但是两个队列不能模拟一个栈。(存疑?)
判断:链式栈的栈顶指针一定指向栈的栈尾。
答案: 错 误 错误 错误
链式栈一般采用单链表,栈顶指针为头指针。进栈出栈均在链头进行。
已知循环队列存储在一维数组A[0.n-1]中,且队列非空时front和rear分别指向队头元素和队尾元素。若初始时队列为空,且要求第1个进入队列的元素存储在A[0]处,则初始时front和rear的值分别是()
A.0, 0
B.0, n-1
C.n-1,0
D.n-1,n-1
答案: B B B
在循环队列中,进队操作是队尾指针rear +1 ,并在该位置放置进队的元素,而队首指针不变。
在本题中,要求第一个进队元素放在A[0]处,队列非空时front 和 rear 分别指向队头和队尾元素,此时要求fornt和rear均为0。因此,初始时候rear应该为n-1,而front 应该为0.
队列出队时,当队列中多余一个节点时,仅仅需要修改队头指针。但如果队列中只剩下一个节点时,此时出队,队首、队尾指针都需要修改为NULL.
用十字链表表示一个稀疏矩阵,每个非零元一般用一个含有 ( ) 个域的结点表示。
A.2
B.3
C.4
D.5
答案: D D D
存储稀疏句真的十字链表节点包含 5 个域:该非零元的行下标,该非零元的列下标,该非零元所在行表的后继链域,该非零元所在列表的后继链域。
已知三叉树T中6个叶结点的权分别是2,3,4,5,6,7,T的带权(外部)路径长度最小是()
A.27
B.46
C.54
D.56
答案: B B B
这道题考察哈夫曼树的构造。
已知一棵完全二叉树的第 6 层(设根为第 1 层)有 8 个叶结点,则完全二叉树的结点个数最多是 ()。
A. 39
B. 52
C. 111
D. 119
答案: C C C
第六层有 8个叶节点,则该完全二叉树最多有 7 层,依照这个思路计算即可。
若一棵完全二叉树有768个结点,则该二叉树中叶结点的个数是()
A.257
B.258
C.384
D.385
答案: C C C
$n0+n1+n2+n3 = 768, ~~ 0 * n0 + 1 * n1 + 2* n2 +1 = 768 $
完全二叉树一个特点:当结点总数为奇数时,n1 = 0;当结点总数为偶数时,n1 = 1.
对于题目中的二叉树,n1=1,n0=384.
已知一棵有2011个结点的树,其叶结点个数为116,该树对应的二叉树无右孩子的结点个数为()
A. 115
B. 116
C. 1895
D. 1896
答案: D D D
按照二叉树的定义,具有三个结点的二叉树有()种形态。
A. 6
B. 5
C. 4
D. 3
答案: B B B
两层有一种情况,三层有 4种情况,无需考虑data.
当一棵有n个结点的二叉树按层次从上到下,同层次从左到右将数据存放在一维数组 A[l…n]中时,数组中第i个结点的左孩子为( )
A. A[2i](2i=
C. A[i/2]
D. 无法确定
答案: D D D
只有 完全二叉树才可以可以确定左右孩子结点的位置。
利用二叉链表存储树,则根结点的右指针是()
A. 指向最左孩子
B. 指向最右孩子
C. 空
D. 非空
答案: C C C
二叉链表存储树,首先需要将树转换为二叉树。根据孩子兄弟表示法,由于树的根结点一定没有右兄弟,因此根节点一定没有右孩子。即根节点的右指针为空。
二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和。给定一棵二叉树T,采用二叉链表存储,结点结构为:
其中叶结点的weight域保存该结点的非负权值。设root为指向T的根结点的指针,请设计求T的WPL的算法。
要求:
(1)给出算法的基本设计思想;
(2)使用C或C++语言,给出二叉树结点的数据类型定义;
(3)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
答案:1. 算法设计思想:递归遍历二叉树,利用同一个参数对深度进行记数。
叶节点的WPL = 该结点的weight * 深度。
二叉树的WPL = 树中全部 叶节点 的带权路径长度之和 = 根节点左子树全部叶节点的带权路径之和 + 根节点右子树全部叶节点的带权路径之和。
typedef struct BTnode{
unsigned int weight;
struct BTnode *lchild, *lchild;
}BTnode;
int main(){
return WPL( root, 0);
}
int WPL( BTnode *root, int d){
if( root->lchild == NULL && root->rchild == NULL)
return (root->weight *d);
else
return WPL(root->lchild, d+1) + WPL(root->rchild, d+1);
}
对于二叉树的两个结点X和Y,应该选择( ) 两个序列来判断X是否为Y的祖先。
A.先序和后序
B.先序和中序
C.中序和后序
D.任意两个序列都行
答案: D D D
任意两个排序都可以判断 X 是不是 Y 的祖先。
但是,先序和后序无法得到二叉树的结构,但是可以判断祖先。
若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置,利用()遍历方法最合适。
A.前序
B.中序
C.后序
D.按层次
答案: C C C
如果交换所有分支结点左右子树,可以递归地操作:先交换左子数中所有分支结点,再递归交换右子树中所有分支结点。最后对根节点交换其子树位置。如此先左后右再根节点的方式为 后序遍历。
将一棵二叉树转化成森林,可按如下步骤进行:
① 抹线:将二叉树根结点与其右孩子之间的连线,以及沿着此右孩子的右链连续不继搜索到的右孩子间的连线抹掉。这样就得到了若干棵根结点没有右子树的二叉树。
② 将得到的这些二叉树用前述方法分别转化成一般树。
能唯一确定原二叉树的遍历方式组合为:前序 + 中序,或者 后序 + 中序,注意,前序遍历加后序遍历不可以唯一确定二叉树。
二叉树在线索化后,仍不能有效求解的问题是()
A. 前序线索二叉树中求前序后继
B. 中序线索二叉树中求中序后继
C. 中序线索二叉树中求中序前驱
D. 后序线索二叉树中求后序后继
答案: D D D
中序线索二叉树 无论是求 中序后继 还是求 中序前驱店铺可以较好解决。
先序线索二叉树中查找结点的 后继 比较容易,但是查找结点的前去要知道其双亲的信息,要使用栈,因此说先序线索二叉树是不完善的。
后序线索二叉树查找结点的 前驱 比较容易,但是查找结点的后继需要知道其双亲结点的信息,要 使用栈 ,因此说后序线索二叉树是不完善的。
在线索二叉树中,下面说法不正确的是( )
A. 在中序线索树中,若某结点有右孩子,则其后继结点是它的右子树的左支末端结点。
B.线索二叉树是利用二叉树的n+1 个空指针来存放结点前驱和后继信息的。
C.每个结点通过线索都可以直接找到它的前驱和后继
D.在中序线索树中,若某结点有左孩子,则其前驱结点是它的左子树的右支末端结点。
答案: c c c
并不是每个结点都可以通过线索来直接找到它的前驱和后去。
树的遍历 和 森林的遍历 与 二叉树遍历的对应关系
|树|森林|二叉树|
|-----|
|先根遍历|先序遍历|先序遍历
|后根遍历|中序遍历|中序遍历
将森林F转换为对应的二叉树T,F中叶结点的个数等于 ()
A. T中叶结点的个数
B. T中度为1的结点个数
C. T中左孩子指针为空的结点个数
D. T中右孩子指针为空的结点个数
答案: C C C
森林F 中的叶子结点对应二叉树T中,没有左孩子的结点。
若平衡二叉树的高度为6,且所有非叶结点的平衡因子均为 1,则该平衡二叉树的结点总数为( )。
A. 12
B. 20
C. 32
D. 33
答案: B B B
平衡二叉树中,假设用 N h N_h Nh表示深度为h的平衡树中含有的 最少 节点数,则满足, N h = N h − 1 + N h − 2 + 1 N_h = N_{h-1}+N_{h-2} + 1 Nh=Nh−1+Nh−2+1, N 0 = 0 , N 1 = 1 , N 2 = 2 N_0=0,N_1=1,N_2=2 N0=0,N1=1,N2=2.
还可以证明,含有n个节点的平衡二叉树的最大深度为 O ( l o g 2 n ) O(log_2n) O(log2n)
对二叉排序树进行_________遍历可以得到结点的排序序列。
A.前序
B.中序
C.后序
D.层次
答案: B B B
折半搜索与二叉排序树的时间性能( )。
A.相同
B.完全不同
C.有时不相同
D.数量级都是O(log2n)
答案: C C C
查找效率最高的二叉排序树是______。
A.所有结点的左子树都为空的二叉排序树
B.所有结点的右子树都为空的二叉排序树
C.平衡二叉树
D.没有左子树的二叉排序树
答案: C C C
设有6个结点的无向图,该图至少应有()条边,才能确保是一个连通图?
A. 8
B. 11
C. 6
D. 5
答案: B B B
注意题目中 “确保” 的含义,它意味着 无论六个顶点如何连接,都找不出非连通的情况。
5 个顶点的完全图需要10条边,再加入一个顶点,第六个顶点无论怎么连接都是连通的。共需11条边。
以下关于图的叙述中,正确的是()
A.强连通有向图的任何顶点到其他所有顶点都有弧
B.图的任意顶点的入度等于出度
C.有向完全图一定是强连通有向图
D.有向图的边集的子集和顶点集的子集可构成原有向图的子图
答案: C C C
D,假如选择了某个边,但是没有选择该边的两个顶点,便无法构成图。
要连通具有n个顶点的有向图,至少需要()条边
A. n-1
B. n
C. n+1
D. 2n
答案: B B B
构成一个环即可。
G是一个非连通无向图,共有28条边,则该图至少有() 个顶点。
A. 8
B. 9
C. 10
D. 11
答案: B B B
8 个顶点连通图无向图最多有 28 个边,若需要保持非连通,则需要 9 个顶点。
对邻接表的叙述中,()是正确的。
A.无向图的邻接表中,第i个顶点的度为第i个链表中结点数的两倍
B.邻接表比邻接矩阵的操作更简便
C.邻接矩阵比邻接表的操作更简便
D.求有向图结点的度,必须遍历整个邻接表
答案: D D D
A,无向图的邻接表,第 i 个顶点的度为第 i 个链表中结点数的一倍。
B,C,好比“线性表中链式存储和顺序存储的优劣”一样。
若邻接表中有奇数个边表结点,则一定是()
A.图中有奇数个结点
B.图中有偶数个结点
C.图为无向图
D.图为有向图
答案: D D D
无向图的邻接表中结点数为边数的两倍。
深度优先搜索可以利用递归的方法,使用堆栈作为辅助空间。
广度优先搜索利用队列作为辅助空间。
一个 n 个结点和 e 条边的图。
|存储结构| 遍历方式|时间复杂度|空间复杂度|
|----|-----|----|
|邻接表 |深度优先遍历| O ( n + e ) O(n+e) O(n+e)| O ( n ) O(n) O(n)
|邻接矩阵 |深度优先遍历| O ( n 2 ) O(n^2) O(n2)| O ( n ) O(n) O(n)
|邻接表 |广度优先遍历| O ( n + e ) O(n+e) O(n+e)| O ( n ) O(n) O(n)
|邻接矩阵 |广度优先遍历| O ( n 2 ) O(n^2) O(n2)| O ( n ) O(n) O(n)
下面算法中可以判断出一个有向图是否有环的是:()
A. 求最短路径
B. 深度优先遍历
C. 广度优先遍历
D. 拓扑排序
答案: B D BD BD
深度优先遍历,对每一个点标记,如果访问到已经标记的点则说明存在回路。
拓扑排序,对于入度为0的结点使之让入队,然后让该点所有相连接的点入度减1,重复n-1次后,如果还有点没有进入输出队列,则这些点在环上。
图的BFS生成树的树高比DFS生成树的树高()
A. 小或相等
B. 小
C. 大或相等
D. 大
若一个有向图具有有序的拓扑排序序列,那么它的邻接矩阵必定为()。
A.对称矩阵
B.稀疏矩阵
C.三角矩阵
D.一般矩阵
答案: D D D
一个有向图具有拓扑排序序列,说明它是一个有向无环图(DAG),但是DAG图在邻接矩阵上没有直接的表示。为一般矩阵。
一个 n 个结点和 e 条边的图。
功能 | 算法 | 时间复杂度 |
---|---|---|
最小生成树 | Prim普里姆 | O ( n 2 ) O(n^2) O(n2) |
最小生成树 | Kruskal克鲁斯卡尔 | O ( e l o g e ) O(eloge) O(eloge) |
最短路径(所有结点) | Dijkstra | O ( n 3 ) O(n^3) O(n3) |
最短路径 | Floyd | O ( n 3 ) O(n^3) O(n3) |
拓扑排序 | O ( n + e ) O(n+e) O(n+e) |
假定查找成功与不成功的可能性相同,在查找成功的情况下每个记录的查找概率相同,则顺序查找的平均查找长度为( )
A.0.5(n+1)
B.0.25(n+1)
C.0.5(n-1)
D.0.75n+0.25
答案: D D D
查找成功的平均查找长度为0.5(n+1) ,查找不成功的查找长度为 n,因此平均查找长度为 0.75n+0.25.
静态查找表与动态查找表二者的根本差别在于()
A.它们的逻辑结构不一样
B.施加在其上的操作不同
C.所包含的数据元素的类型不一样
D.存储实现不一样
答案: B B B
对有3600个记录的索引顺序表进行查找,最理想的块长是 ( )
A.1800
B.60
C.1200
D.1000
答案: B B B
分块查找(块间有序,块内无序)的平均长度为 索引查找 的平均长度 加 块内查找的平均长度。将长度为 n 的查找表均匀地分为 b 块,每块有 s(s = n/b) 个记录。
下列关于二分查找的叙述中,正确的是()
A.表必须有序,表可以顺序方式存储,也可以链表方式存储
B.表必须有序且表中数据必须是整型,实型或字符型
C.表必须有序,而且只能从小到大排列
D.表必须有序,且表只能以顺序方式存储
答案: D D D
二分查找又称为折半查找,要求:1. 顺序存储结构 2. 有序。
折半查找过程所对应的判定树是一棵()
A.最小生成树
B.平衡二叉树
C.完全二叉树
D.哈夫曼树
答案: B B B
举例验证即可。
在下列查找方法中,平均查找速度最快的是 ( )
A.顺序查找
B.折半查找
C.分块查找
D.二叉排序树查找
答案: B B B
二叉排序树的时间复杂度可能退化到 O ( n ) O(n) O(n).而折半查找时间复杂度一直为 O ( l o g n ) O(logn) O(logn).
分块查找介于折半查找和顺序查找之间。
下列叙述中,不符合m阶B树定义要求的是______。
A.根结点最多有m棵子树
B.所有叶结点都在同一层上
C.各结点内关键字均为升序或降序排列
D.叶结点之间通过指针连接
答案: D D D
m阶B树:1. 若根节点不是终端节点,则根至少有两个子女。2. 根节点以外的所有非叶结点至少有 m/2向上取整 个 子女(即最少 m/2向上取整 -1 个关键字)3. 所有叶节点在同一层并不带有任何信息。4. 树中非叶结点至多有m棵子树(即最少 m-1个关键字) 5. 各结点内关键字均有序排列。
采用开放定址法解决冲突的哈希查找中,发生集聚的原因主要是()
A. 数据元素过多
B. 负载因子过大
C. 哈希函数选择不当
D. 解决冲突的算法选择不好
答案: D D D
开放定址法包括:线性探测法、平方探测法、再散列法、伪随机序列法。
算法稳定性。
在下列算法中,______算法可能出现下列情况:在最后一趟开始之前,所有的元素都不在其最终的位置上。
A.堆排序
B.冒泡排序
C.插入排序
D.快速排序
答案: C C C
经过一趟排序,能够保证一个元素达到最终位置的算法有:选择类:简单选择和堆排序、交换类:冒泡排序和快速排序。
在最好的情况下,对n个记录的顺序表做()排序,其时间复杂度为 O ( n ) O(n) O(n)
A. 冒泡
B. 快速
C. 堆
D. 折半插入
答案: A A A
冒泡排序和直接插入排序最好情况下时间复杂度都为 O ( n ) O(n) O(n)
当待排序记录已经从小到大排序或者已经从大到小排序时,快速排序的执行时间与()排序相同。
A. 选择
B. 基数
C. 归并
D. 希尔
答案: A A A
快速排序在待排序列有序时,时间复杂度为 O ( n 2 ) O(n^2) O(n2).
采用递归方式对顺序表进行快速排序,下列关于递归次数的叙述中,正确的是()
A. 递归次数与初始数据的排列次序无关
B. 每次划分后,先处理较长的分区可以减少递归次数
C. 每次划分后,先处理较短的分区可以减少递归次数
D. 递归次数与每次划分后得到的分区处理顺序无关
答案: D D D
如果只想得到1000个元素组成的序列中第5个最小元素之前的部分排序的序列,用()方法最快。
A.起泡排序
B.快速排列
C.Shell排序
D.堆排序
E.简单选择排序
答案: D D D
堆排序使用的场景是元素很多的情况。如果元素较少则不提倡。
同时,构建堆的时间为线性时间。
不稳定:快选堆希(快速排序、选择排序、堆排序、希尔排序)。“心情不稳定, 希 望 快 选 堆 朋友来玩”
稳定:插冒归计基(简单插入排序、冒泡排序、归并排序、计数排序、基数排序)
关于移动次数和关键字顺序无关的排序:
顺口溜:一堆(堆排序)海龟(归并排序)选(选择排序)基(基数排序)友。
以下与数据的存储结构无关的术语是()。
A. 循环队列
B. 链表
C. 哈希表
D. 栈
答案: C C C
循环队列是用 顺序表 来表示队列。
下列数据中,()是非线性数据结构。
A. 栈
B. 队列
C. 完全二叉树
D. 堆
答案: C C C
D,堆是元素的序列,存在一维数组中,可以看成是线性结构。
C,完全二叉树是非线性结构。但是因为双亲和子女之间的编号存在特定关系,用一维数组存储更好。
算法不一定有输入,但一定有输出。
线性表的顺序存储结构是一种()存储结构。
A. 随机存取
B. 顺序存取
C. 索引存取
D. 散列存取
答案: A A A
误选B,顺序存取是一种读写方式,不是存储方式。
设线性表有n个元素,严格说来,以下操作中,()在顺序表上实现要比链表上实现的效率高。
I,输出第i个元素值
II,交换第3个元素与第4个元素的值
III,顺序输出这n个元素的值
A.I
B.I、Ⅲ
C.I、II
D.II、Ⅲ
答案: C C C
II 存疑。
长度为n的顺序表L,编写一个时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)的算法,该算法删除线性表中所有值为X的元素。
算法思想:用 numberX 统计顺序表中等于 X 的元素的个数。边统计边扫描L,并将不等于 X 的元素前移 numberX 个位置。
关于线性表的顺序存储结构和链式存储结构的描述正确的是()。
I,线性表的顺序存储结构优于其链式存储结构
II,链式存储结构比顺序存储结构能更方便地表示各种逻辑结构
III,如频繁使用插入和删除结点操作,顺序存储结构更优于链式存储结构
Ⅳ,顺序存储结构和链式存储结构都可以进行顺序存取
A.I、II、III
B.II、Ⅳ
C.II、III
D.III、Ⅳ
答案: B B B
II,链式存储结构使用指针表示逻辑结构,而指针的设置是任意的,因此可以很方便的表示逻辑结构;顺序存储只能使用物理上的邻接关系表示逻辑结构。
给定有n个元素的一维数组,建立一个有序单链表的最少时间复杂度是()。
A.O(1)
B.O(n)
C.O(n 2 ^2 2)
D.O(nlog 2 _2 2n)
答案: D D D
数组排序的时间复杂度最少为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n), 建立单链表的时间复杂度为 O ( n ) O(n) O(n).
带头结点的双循环链表L为空表的条件是:()
A. L->prior == L && L->next == NULL
B. L->prior == NULL && L->next == NULL
C. L->prior == NULL && L->next == L
D. L->prior == L && L->next == L
答案: D D D
循环双链表判空的条件为 头结点(头指针)的 prior 和 next域 都指向自身。
设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点。
void Del_X_3(LinkList &L,ElemType x)
{
LNode *p;
if(L==NULL)
return ;
if(L->data==x)
{
p=L;
L=L->next;
free(p);
Del_X_3(L,x);//位置1
}else
{
Del_X_3(L->next,x);//位置2
}
}
疑点是递归操作中好像只进行了删除操作,而没有改变被删除结点的前驱,使其指向被删除结点的下一个结点。
例如p指向要删除的结点,q为该结点的前驱,那么要实现删除结点,代码为:q->next=p->next;
理解说明:函数的递归调用时,总会再调用前将现有函数中的变量压入堆栈进行保存。
栈和队列具有相同的()。
A.抽象数据类型
B.逻辑结构
C.存储结构
D.运算
答案: B B B
二者都是线性结构。
向一个栈顶指针为Top的链栈中插入一个s所指结点时,其操作步骤为()
A.Top—>next=s;
B.s—>next=Top—>next;Top—>next=s;
C.s—>next=Top;Top=s;
D.s—>next=Top;Top=Top—>next;
答案: C C C
单链表表示栈时,只能适用表头作为栈顶!
一个栈的入栈序列为1,2,3,…,n,其出栈序列是p1,p2,p3… ,pn。若p2=3,则p3可能取值的个数是()
A.n-3
B.n-2
C.n-1
D.无法确定
答案: C C C
除了 3 之外的任何数字都能取到。
循环队列存储在数组A [0…m]中,则入队时的操作为( )。
A.rear=rear+1
B.rear=(rear+1)%(m一1)
C.rear=(rear+1)%m
D.rear=(rear+1)%(m+1)
答案: D D D
注意数组的容量为 m+1 .
已知有一维数组A[0… m * n-1],若要对应为 m 行、n 列的矩阵,则下面的对应关系()可将元素Ak表示成矩阵的第 i 行、第j列的元素(0≤i
B. i=k/m,j=k%m
C. i=k/n,j=k%n
D. i=k/m,j=k%n
答案: C C C
n 个入栈元素可以得到 ( 2 n ) ! n ! ( n + 1 ) ! \frac{(2n)!}{n! (n+1)!} n!(n+1)!(2n)! 种出栈序列。
栈的应用不包括()。
A.递归
B.进制转换
C.迷宫求解
D.缓冲区
答案: D D D
缓冲区使用队列实现。
利用栈实现以下递归函数的非递归算法:
f n ( x ) = 1 ( n = 0 ) f_n(x) = 1 (n=0) fn(x)=1(n=0)
$f_n(x) = 2x (n=1) $
$f_n(x) = 2xf_{n-1}(x)-2(n-1)f_{n-2}(x) ( n>1) $
思想:设置一个栈用于保存n和对应的 f n ( x ) f_n(x) fn(x)的值,栈中相邻元素依据题目中所给关系。然后边出栈边计算。
double f( int n, double x){
struct stack{
int n;
double val;
}st[MaxSize];
int top = -1, i;
double fv1 = 1, fv2 = 2 * x;
for( int i = n; i >= 2;i--){
top++;
st[top].n = i;
}
while(top>=0){
st[top].val = 2 * x * fv2 - 2*(st[top].n - 1) * fv1;
fv1 = fv2;
fv2 = st[top].val;
top--;
}
if(n==0)
return fv1;
return fv2;
}
树的路径长度是从树根到每一结点的路径长度的()。
A.总和
B.最小值
C.最大值
D.平均值
答案: A A A
树的路径长度是所有路径长度的总和。
树根到每一结点的路径的最大值应该是树的高度减1.
Huffman树的带权路径长度:
树的结点与度之间的关系:
总 结 点 数 = n 0 + n 1 + . . . + n m 总结点数 = n_0 + n_1 +...+ n_m 总结点数=n0+n1+...+nm
总 分 支 数 = 0 ∗ n 0 + 1 ∗ n 1 + . . . + m ∗ n m 总分支数 = 0 * n_0 + 1 * n_1 +...+ m * n_m 总分支数=0∗n0+1∗n1+...+m∗nm
总 结 点 数 = 总 分 支 数 + 1 总结点数 = 总分支数 + 1 总结点数=总分支数+1(1指的是根节点)
判断正误:度为2的有序树为二叉树。
答案:错误
二叉树是有序树,在二叉树中,如果某一个结点只有一个孩子结点,这个孩子结点的左右次序就是确定的。但是在度为2的有序数中,如果某一个结点只有一个孩子系欸但,那么这个孩子节点就无需区分左右次序,因此度为2的有序树不是二叉树。
一棵有124个叶节点的完全二叉树,最多有( )个节点。
A. 247
B. 248
C. 249
D. 250
答案: B B B
由完全二叉树总结点数的奇偶性可以确定N1的值,在完全二叉树中N1不是0就是1,这里取N1=1.
N个结点的完全二叉树的高度为 ⌊ l o g 2 N ⌋ \lfloor log_2N \rfloor ⌊log2N⌋ + 1 或者 ⌈ l o g 2 ( N + 1 ) ⌉ \lceil log_2(N+1) \rceil ⌈log2(N+1)⌉
设n、m为一棵二叉树上的两个结点,在后序遍历时,n在m前的条件是()。
A.n在m右方
B.n是m祖先
C.n在m左方
D.n是m子孙
答案: D D D
C,需要加上条件“两个结点位于同一层”
有疑问。
在二叉树中有两个结点m和n,如果m是n的祖先,可以找到从m到n的路径的遍历方式是______。
A.先序遍历
B.中序遍历
C.后序遍历
D.从根开始按层次遍历
答案: C C C
使用后序遍历退回到根节点时,就可以自下而上把从n到m的路径上的结点输出。
一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足()
A. 所有的结点均无左孩子
B. 所有的结点均无右孩子
C. 只有一个叶子结点
D. 是一棵满二叉树
答案: C C C
一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,因此,树只有根节点,或者根节点只有左子树或者右子树。依次推类,其子树有相同的性质。
要使一棵非空二叉树的先序序列与中序序列相同,其所有非叶结点须满足的条件是( )。
A. 只有左子树
B. 只有右子树
C. 结点的度均为1
D. 结点的度均为2
答案: B B B
aaaa,失误了。。。
引入线索二叉树的目的是()
A.加快查找结点的前驱或后继结点的速度
B.为了能在二叉树中方便插入和删除
C.为了能方便找到双亲
D.使二叉树的遍历结果唯一
答案: A A A
线索二叉树是一种( )结构。
A.物理
B.逻辑
C.存储
D.线性
答案: A A A
二叉树是一种逻辑结构,但是线索二叉树 是加上线索之后的链表结构,即线索二叉树是二叉树在计算机内部的一种存储结构,是一种物理结构。
n个结点的线索二叉树上含有的线索数为()
A. 2n
B. n-1
C. n+1
D. n
答案: C C C
n个结点一共有链域指针2n个,其中,除了根节点之外,每一个节点都被一个指针指向。剩余的链域建立线索,一共 2n-(n-1) = n + 1 个线索。
若X是二叉树中序线索树中一个有左孩子的结点,且X不为根,则X的前驱为()
A. X的双亲
B. X的右子树中最左的结点
C. X的左子树中最右结点
D. X的左子树中最右叶结点
答案: C C C
注意,并不一定是最右叶结点,画图即可知晓。
假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度。
int bedepth(BinTree T){
if( !T)
return 0;
ldep = Btdepth(T->lchild);
rdep = Btdepth(T->rchild);
if( ldep > rdep)
return ldep + 1;
else
return rdep + 1;
}
设一棵二叉树中各结点的值互不相同,其前序序列和中序序列分别存于两个一维数组A[1…n]和B[1…n]中,试遍写算法建立该二叉树的二叉链表。
BinTree PreInCreat( ElemType *A, ElemType *B, int l1, int h1, int l2, int h2){
l1 = l2 = 1;
h1 = h2 = n;
root = (BinTNode *)malloc(sizeof(BinTNode));
root->data = A[l1];
for( int i = l2; B[i] != root->data; i++)
;
int llen = i - l2; int rlen = h2 - i;
if(llen)
root->lchild = PreInCreat(A,B,l1+1,l1+llen,l2,l2+llen-1);
else
root->lchild = NULL;
if(rlen)
root->lchild = PreInCreat(A,B,h1-rlen+1,h1,h2-rlen+1,h2);
else
root->rchild = NULL;
return root;
}
假定二叉树采用二叉链表存储结构,设计一个算法,计算一棵给定二叉树的所有双分支节点个数。
int DoubleSondes( BinTree B){
if( B == NULL)
return 0;
else if( B->lchild && B->rchild);
return DoubleSondes(B+lchild) + DoubleSondes(B->rchild) + 1;
else
return DoubleSondes(B+lchild) + DoubleSondes(B->rchild);
}
假定二叉树采用二叉链表存储结构,设计一个算法,求其先序遍历中第k个(1<=k<=二叉树节点个数)个结点的值。
```
int i = 1;
ElemType PreNode(BiTree b, int k){
if( b == NULL)
return '#'; //空结点返回特殊字符;
if( i == k)
return b->data;
i++;
ch = PreNode(b->lchild, k);
if( ch != '#')
return ch;
ch = PreNode(b->rchild, k);
return ch;
}
```
设有一颗满二叉树(所有节点值均不同),已知其先序序列pre,设计一个算法求其后序序列post.
void Pre2Post( ElemType pre[], int l1, int h1, elemType post[], int l2, int h2){
int half;
if(h1 >= l1){
post[h2] = pre[l1];
half = (h1 - l1) / 2;
Pre2Post(pre, l1+1, l1+half, post, l2, l2+half-1);
Pre2Post(pre, l1+half+1, h1, post, l2+half, l2-1);
}
}
若森林F有15条边、25个结点,则F包含树的个数是()
A. 8
B. 9
C. 10
D. 11
答案: C C C
利用树的性质:任何一棵树的结点数 = 树的边数 + 1.
编程求 以孩子兄弟表示法 存储的森林的叶子的结点数。
typedef struct node{
ElementType data;
struct node *fch, *nsib; //fch 表示孩子,nsib 表示兄弟
}*Tree;
int Leaves( Tree T){
if( T == NULL)
return 0;
if( T->fch == NULL)
return 1 + Leaves(T->nsib);
else
return Leaves(T->fch) + Leaves(T->nsib);
}
以 孩子兄弟链表 为存储结构,设计递归算法计算树的深度。
//高度为第一子女树高度+1 和 兄弟子树高度的 大者
int Height( CSTree BT){
int hc, hs;
if( BT == NULL)
return 0;
else{
hc = Height(bt->firstchild);
hs = eight(bt->nextsibling);
if( hc + 1 > hs)
return hc + 1;
else
return hs;
}
}
对二叉排序树插入新节点不会引起树的分裂组合。
平衡二叉树中,假设用 N h N_h Nh表示深度为h的平衡树中含有的 最少 节点数,则满足, N h = N h − 1 + N h − 2 + 1 N_h = N_{h-1}+N_{h-2} + 1 Nh=Nh−1+Nh−2+1, N 0 = 0 , N 1 = 1 , N 2 = 2 N_0=0,N_1=1,N_2=2 N0=0,N1=1,N2=2.
还可以证明,含有n个节点的平衡二叉树的最大深度为 O ( l o g 2 n ) O(log_2n) O(log2n)
给定一个关键码集合{25,18,34,9,14,27,42,51,38},假定检索各关键码的概率相等,请画出其最佳二叉排序树。
答案:最佳二叉树,即高度最低的二叉树。可以先对原集合排序,选择中间一个结点作为根。亦或者构造AVL树。
以下关于图的叙述中,正确的是()
A.图与树的区别在于图的边数大于或等于顶点数
B.假设有图G={V,{E}},顶点集V’∈V,E’∈E,则V’和{E’}构成G的子图
C.无向图的连通分量指无向图中的极大连通子图
D.图的遍历就是从图中某一顶点出发访遍图中其余顶点
答案: C C C
D,说法不准确,图的遍历要求每个结点只能被访问一次,如果图非连通,从某顶点出发,无法访问到其他全部顶点。
设有无向图G=(V,E)和G’=(V’,E’),如果G’是G的生成树,则下列不正确的是()。
I, G’为G的连通分量
II, G’为G的无环子图
III, G’为G的极小连通子图且V’=V
A.I、II
B.只有III
C.II、III
D.只有I
答案: D D D
无向图中的极大连通子图称为连通分量,G’连通但不是连通分量。
补充:极大连通子图:如果图本来就不是连通的,那么每一个字部份如果包含它本身的所有顶点和边,那么它就是极大连通子图。
如何对无环有向图的顶点号重新安排可以使得该图的邻接矩阵中所有的 1 都集中到对角线以上?
答案:方法一:按照各顶点的 出度 进行排序。n各顶点的有向图,其顶点最大的出度为n-1,最小的出度为0。排序之后,出度最大的顶点编号为1,出度最小的顶点编号为n,之后进行调整,只要存在弧,则不管顶点j的出度是否是否大于顶点i的出度,都应该把i编号放在顶点j之间,因为只有i>=j,弧对应的1才能出现在林解决真的上三角。
方法二:拓扑排序。
如果一个有向图的邻接矩阵对角线以下元素为0,则该图的拓扑序列一定存在。
以下关于图的存储结构的叙述中正确的是()。
A.一个图的邻接矩阵表示唯一,邻接表表示唯一
B.一个图的邻接矩阵表示唯一,邻接表表示不唯一
C.一个图的邻接矩阵表示不唯一,邻接表表示唯一
D.一个图的邻接矩阵表示不唯一,邻接表表示不唯一
答案: B B B
邻接矩阵表示唯一,因为图中的边的信息在矩阵中有确定的位置。
邻接表表示不唯一,因为邻接表的建立取决于读入边的顺序和边表中的插入算法。
假设一个由n个顶点和e条边的有向图用邻接表表示,则删除与某个顶点vi相关的所有边的时间复杂度是 ( ) 。
A.O(n)
B.O(e)
C.O(n+e)
D.O(ne)
答案: C C C
十字链表 是 有向图 的存储结构。
邻接多重表 是 无向图 的存储结构。
写出从 图的邻接表 表示法转换成 邻接矩阵表示法 的算法。
void Convert( AlGraph &G, int arcs[M][N]){
for( int i = 0; i < n; i++){
p = (G->v[i]).firstarc;
while( p!=NULL){
arcs[i][p->data] = 1;
p = p->nextarc;
}
}
}
图采用 邻接表 表示时:
|算法|时间复杂度|空间复杂度|
|—|---|
|DFS| O ( n + e ) O(n+e) O(n+e)| O ( n ) O(n) O(n)|
|BFS| O ( n + e ) O(n+e) O(n+e)| O ( n ) O(n) O(n)|
图采用 邻接矩阵 表示时:
算法 | 时间复杂度 |
---|---|
DFS | O ( n 2 ) O(n^2) O(n2) |
BFS | O ( n 2 ) O(n^2) O(n2) |
判断 有向图 是否存在回路,除了可以利用拓扑排序方法外,还可以利用______。
A.求关键路径的方法
B.求最短路径的Dijkstra方法
C.深度优先遍历算法
D.广度优先遍历算法
答案: C C C
判断 有向图 是否存在回路的方法:深度优先遍历算法DFS、拓扑排序、求关键路径(基础是拓扑排序)
设无向图 G=(V,E) 和 G’=(V’,E’) ,如果 G’ 是 G 的 生成树,则下面说法中错误的是()
A.G’是G的子图
B.G’是G的连通分量
C.G’是G的极小连通子图且V=V’
D.G’是G的一个无环子图
答案: B B B
连通分量是无向图的极大连通子图,其中 极大 的含义 指 将依附于连通分量中顶点的所有边都加上,所以连通分量(极大连通子图)可能存在回路,存在回路shi不是生成树。
图的 广度优先生成树 的 树高 小于或者等于 深度优先生成树 的 树高。
用Prim算法和Kruskal算法构造图的最小生成树,所得到的最小生成树是否相同?
答案:可能相同,也可能不同。
不同算法的最小生成树不唯一(因为无向连通图的最小生成树不唯一)。但是 代价是唯一的。
当无向连通图的生成树唯一时,不同算法的最小生成树必定相同。
以下叙述正确的是()。
A.最短路径一定是简单路径
B.Diikstra算法不适合求有回路的带权图的最短路径
C.Diikstra算法不适合求任意两个顶点的最短路径
D.Floyd算法求两个项点的最短路径时, p a t h k − 1 path_{k-1} pathk−1一定是 p a t h k path_k pathk的子集
答案: A A A
Dijkstra算法适合求解有回路的带权图的最短路径。不适合求 带负权值的最短路径问题。
以下关于拓扑排序的说法中 错误 的是()。
I,如果某有向图存在环路,则该有向图一定不存在拓扑排序
II,在拓扑排序算法中,为暂存入度为零的顶点可以使用栈,也可以使用队列
III,若有向图的拓扑有序序列唯一,则图中每个顶点的入度和出度最多为1
A.I、III
B.II、III
C.II
D.III
答案: D D D
有向无环图的拓扑排序唯一 不能 唯一确定该图。
一个连通无向图,边为非负值,问:用Dijkstra最短路径算法能否给出一棵生成树,该生成树为最小生成树?
答案:不一定。
“破圈法” 找出 最小生成树 是 正确的。
(相对地,Prim 和 Kruskal算法 属于 避圈法。)
折半查找过程所对应的判定树是一棵()。
A.最小生成树
B.平衡二叉树
C.完全二叉树
D.满二叉树
答案: B B B
m阶B树的特点:1> 树中每一个结点至多由m棵子树(即至多含有 m-1 个关键字);2> 如果根节点不是终端节点,则至少含有两颗子树;3> 除了根节点之外的所有非叶结点至少有 ⌈ m / 2 ⌉ \lceil m/2 \rceil ⌈m/2⌉棵子树(即至少有 ⌈ m / 2 ⌉ − 1 \lceil m/2 \rceil - 1 ⌈m/2⌉−1 个关键字);4> 所有非叶节点都出现在同一层次上,且不带信息。
含有 n 个非叶结点的 m 阶B树种至少包含 ( n − 1 ) ( ⌈ m / 2 ⌉ − 1 ) + 1 (n-1)(\lceil m/2 \rceil - 1) + 1 (n−1)(⌈m/2⌉−1)+1 个关键字。
B+树是应 数据库需求 而出现的B树的变形。它支持顺序查找(B树不支持)。
采用开放定址法解决冲突的哈希查找中,发生集聚的原因主要是()
A. 数据元素过多
B. 负载因子过大
C. 哈希函数选择不当
D. 解决冲突的算法选择不好
答案: D D D
冲突(碰撞)是不可避免的,与装填因子无关。
用哈希(散列)方法处理冲突(碰撞)时可能出现堆积(聚集)现象,下列选项中,会受堆积现象直接影响的是 ()
A. 存储效率
B. 数列函数
C. 装填(装载)因子
D. 平均查找长度
答案: D D D
ABC,堆积对这些没有影响。
散列表的平均查找长度依赖于装填因子,而不依赖于其他。
对任意7个关键字进行基于比较排序,至少要进行()次关键字之间的两两比较。
A.13
B.14
C.15
D.6
答案: A A A
对任意序列进行基于比较的排序,求最少的比较次数,n个关键字排序的比较次数至少为 ⌈ l o g 2 ( n ! ) ⌉ \lceil log_2(n!) \rceil ⌈log2(n!)⌉.
下列排序算法中,()算法可能会出现“在最后一趟开始之前,所有元素都不在其最终位置上”的情况。
A.堆排序
B.冒泡排序
C.快速排序
D.插入排序
答案: D D D
有些排序算法在每趟排序过程中,都会有一个元素被放置到其最终位置上,下列算法不会出现此种情况的是()。
A.希尔排序
B.堆排序
C.冒泡排序
D.快速排序
答案: A A A
因为希尔排序是基于插入排序的。
快速排序算法在()情况下最不利于发挥其长处。
A.要排序的数据量太大
B.要排序的数据中含有多个相同值
C.要排序的数据个数为奇数
D.要排序的数据已基本有序
答案: D D D
当待排序数组基本有序时,每次选区第n个元素为基准时,会导致划分区间不均匀不利于发挥快排的优势。
采用递归方式对顺序表进行快速排序,下列关于递归次数的叙述中,正确的是( )
A.递归次数与初始数据的排列次序无关
B.每次划分后,先处理较长的分区可以减少递归次数
C.每次划分后,先处理较短的分区可以减少递归次数
D.递归次数与每次划分后得到的分区处理顺序无关
答案: D D D
注意是快速排序。
A,如果每次划分后分区均衡,则递归次数少。
对n个关键字进行快速排序,最大递归深度为(),最小递归深度为()。
A.1
B.n
C. l o g 2 n log_2n log2n
D. n l o g 2 n nlog_2n nlog2n
答案: B 、 C B、C B、C
快速排序过程构成一个递归树,递归深度即递归树的高度。
每次枢纽值将子表等分时,此时递归树的高度为 l o g 2 n log_2n log2n.
当枢纽值每次都是最大值或最小值时,此时递归树高度为n。
采用简单选择排序,比较次数与移动次数分别为()
A. O(n),O(logn)
B. O(logn),O(nn)
C. O(nn),O(n)
D. O(nlogn),O(n)
答案: C C C
构建n个记录的初始堆,其时间复杂度为();对n个记录进行堆排序,最坏情况下其时间复杂度为()。
A.O(n)
B.O( n 2 n^2 n2)
C.O(log2n)
D.O( n l o g 2 n nlog_2n nlog2n)
答案: A 、 D A、D A、D
删除堆顶元素时,先将堆顶元素和最后一个元素交换,再筛选(因此可能多一个比较次数)
如果只想得到一个序列中第k个最小元素之前的部分排序,最好需要什么排序方法?
答案:冒泡排序、堆排序和简单选择排序。
注意:插入排序、快速排序和归并排序,都是将元素全部排序完毕之后,才能得到前k个最小/最大元素。
以下排序算法中,()不需要进行关键字的比较。
A.快速排序
B.归并排序
C.基数排序
D.堆排序
答案: C C C
平均情况下空间复杂度为 O ( n ) O(n) O(n)的算法:归并排序。
最快情况下空间复杂度为 O ( n ) O(n) O(n)的算法是:快速排序、归并排序。
堆排序的空间复杂度为 O ( 1 ) O(1) O(1)
注意:快速排序的空间复杂度平均情况下为 O ( l o g 2 n ) O(log_2n) O(log2n)
归并排序是排序算法中占用辅助空间最多的算法。
在最好的情况下,冒泡排序 和 插入排序 的时间复杂度可以达到 线性。
非空的单循环链表L(带头节点)的终端节点(由P指向)满足()
A. P->nextNULL
B. PL
C. P->nextL
D. P->nextL && P!=L
答案: D D D
注意 非空 的条件。
单循环链表 中设置 尾指针 比设置 头指针 更合适。 因为这使得 查找链表的头指针和尾指针更方便。
有一个顺序表L,其元素为整型数据,设计一个算法,将L中所有小于表头元素的整数放在前半部分,大于表头元素的整数放在后半部分。
答案:这道算法设计题是 快速排序 的关键步骤。
void move( SqList &L){
int temp, i = 0, j = L.length - 1;
temp = L.data[i];
while( i < j){
while( j > i && L.data[j] > temp)
j--;
if( i < j){
L.data[i] = L.data[j];
i++;
}
while( i < j && L.data[i] < temp)
i++;
if( i < j){
L.data[j] = L.data[i];
j--;
}
}
L.data[i] = temp;
}
循环队列中 1. 队空状态: queue.rear == queue.front; 2. 队满状态:(queue.rear + 1) % MaxSize = queue.front;
编号为1,2,3…N 依次进栈,则可能的不同的出栈顺序有 1 n + 1 C 2 n n \frac{1}{n+1}C_{2n}^{n} n+11C2nn 个
设计一个递归算法,求n个不同字符的所有全排序列。
答案:设str是含有n个不同字符的字符串,perm(str,k-1,n)为str[0]str[k-1]的所有字符的全排列,perm(str,k,n)为str[0]str[k]的全排列。则perm(str,k-1,n)比perm(str,k,n)处理的字符少一个。
假设perm(str,k-1,n)可求,对于str[k]位置,可以取str[0]~str[k]范围内的任何值,再组合perm(str,k-1,n),则可以得到perm(str,k,n).
void perm2( char str[], int k, int n){
int i, j;
char temp;
if(k==1){
for( j = 0; j <= n-1; j++){
cout<
树的后序遍历序列等同于该树对应的二叉树的______。
A.先序序列
B.中序序列
C.后序序列
D.不确定
答案: B B B
树的先序遍历对应于二叉树的先序遍历;树的后序遍历对应二叉树的中序遍历。
森林的先序遍历对应二叉树的先序遍历;森林的后序遍历对应于二叉树的中序遍历。
若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置,利用()遍历方法最合适。
A.前序
B.中序
C.后序
D.按层次
答案: C C C
要实现交换所有分支节点的左右子树的位置,可以递归地进行如下操作:先递归交换左子树中的所有分支节点,再递归交换右子树中的所有分支节点,最后对根节点交换其所有子树位置。这就对应了先遍历左子树,再遍历右子树,最后访问根节点的方式,即后序遍历。
假设二叉树采用二叉链存储结构,设计一个算法,计算一棵给定二叉树的所有结点数。
int n = 0;
void count( BTNode *p){
if( p != NULL){
n++;
count( p->lchild);
count( p->rchild);
}
}
扩展:假设二叉树采用二叉链存储结构,设计一个算法,计算一棵给定二叉树的所有叶子结点数。
什么样的图其最小生成树是唯一的?
答案:所有权值均不相等。或者,有权值相等的边,但是在构造其最小生成树的过程中权值相等的边都被并入生成树。以上两种情况,图的最小生成树唯一。
AOV网 (Activity On Vertex network) ,一种以顶点表示活动、以边表示活动的先后次序且没有回路的有向图,其中边无权值。
AOE网(Activity On Edge network),边表示活动,且边有权值,其权值代表活动的持续时间;顶点表示事件,事件是图中新活动开始或者旧活动结束结束的标志。
AOV网 和 AOE 网都是 有向无环图。
一个工程的完成仅仅需要执行关键活动吗?还是说,关键活动完成的同时其他活动也已经完成了呢?
答案:图中所表示的所有活动都要执行,只不过关键路径执行所需要的事件就是整个图中所有活动所完成的时间。
用有向无环图描述表达式(A+B)*((A+B)/A),至少需要顶点的数目为()
A. 8
B. 5
C. 6
D. 9
正确答案: B B B
用图来表示表达式,图中顶点表示参与运算的一种操作数和运算符(注意,是一种而不是一个),用边来确定各种运算以及运算优先顺序。
若一个有向图的邻接矩阵中,主对角线以下的元素均为零,则该图的拓扑有序序列()
A. 一定存在
B. 不一定不存在
C. 不存在
答案: A A A
拓扑排序序列存在的条件是AOV网中不存在环(注意,即使有多个 连通分量 也无所谓)
一个有向图的邻接矩阵中,主对角线以下的元素均为零,代表图中只存在由编号小的顶点指向编号大的顶点的边。
通过本题可以联想到在 操作系统中,给资源编号,按需分配,可以破坏循环等待条件,不会产生死锁)
1.对于含有n个顶点的带权连通图,它的最小生成树是指图中任意一个____
A. 由n-1条权值最小的边构成的子图
B. 由n-1条权值之和最小的边构成的子图
C. 由n-1条权值之和最小的边构成的连通子图
D. 由n个顶点构成的边的权值之和最小的连通子图
答案: D D D
一个连通图的最小生成树一定包含图中的n个顶点。ABC选项不一定包含n个顶点。
若一个有向图中的顶点不能排成一个拓扑序列,则可断定
A.含有多个出度为0的顶点
B.是个强连通图
C.含有多个入度为0的顶点
D.含有顶点数目大于1的强连通分量
答案: D D D
一个有向图中的顶点不能排成一个拓扑序列,则该有向图中一定有环。顶点数目大于1的强连通分量一定含有环。
下列排序算法中,()在某趟排序结束后不一定能选出一个元素放到其最终位置上。
A. 选择排序
B. 冒泡排序
C. 归并排序
D. 堆排序
答案: C C C
交换类和选择类 的排序每趟结束之后都有一个关键字到位。
排序趟数与序列的原始状态有关的排序方法是( )
A.插入排序法
B.选择排序法
C.冒泡排序法
D.基数排序法
答案: C C C
交换类的排序,其趟数和原始状态有关。
直接插入排序在最好情况下的时间复杂度为_______,在最坏情况下的时间复杂度为_______。
答案: O ( n ) , O ( n 2 ) O(n),O(n^2) O(n),O(n2)
注意:对于直接插入排序,原始序列越接近 有序, 则比较的次数越好
采用递归方式对顺序表进行快速排序,下列关于递归次数的叙述中,正确的是()
A. 递归次数与初始数据的排列次序无关
B. 每次划分后,先处理较长的分区可以减少递归次数
C. 每次划分后,先处理较短的分区可以减少递归次数
D. 递归次数与每次划分后得到的分区处理顺序无关
答案: D D D
快速排序的递归次数由 low 和 high决定(low 和 high 决定了要处理问题的规模)。
将快速排序的递归次数设为 F( low, high).
则可知 递归次数 F( low, high)= F( low, i-1) + F( i+1, high)
交换次序有,F( low, high)= F( i+1, high) + F( low, i-1)
可见两式相等,因此递归次数与每次划分后得到的分区处理顺序无关。
下面关于m阶B树说法正确的是()
①每个结点至少有两棵非空子树
②树中每个结点至多有m-1个关键字
③所有叶子在同一层上
④当插入一个数据项引起B树结点分裂后,树长高一层
A. ①②③
B. ②③
C. ②③④
D. ③
答案: B B B
①中,m阶B-树的根节点至少有两棵子树,并且这两棵子树可以非空,其余结点至少有 ⌈ m / 2 ⌉ \lceil m/2 \rceil ⌈m/2⌉个分支,即 ⌈ m / 2 ⌉ \lceil m/2 \rceil ⌈m/2⌉个子树。
Hash查找中 链地址法 不会解决堆积现象。因为多个同义词只会占用表中的同一个地址。
假设有k个关键字互为同义词,若用线性探查法把这k个关键字存入,至少要进行的探查次数是( )。
A.k-1
B.k
C.k+1
D.k(k+1)/2
答案: D D D
k个同义词,第一个关键字需要探查一次,第二个关键字需要探查两次,第三个关键字需要探查三次,依次推类。
设有n个关键字,Hash查找法的时间复杂度为()
A. O ( 1 ) O(1) O(1)
B. O ( n ) O(n) O(n)
C. O ( l o g 2 n ) O(log_2n) O(log2n)
D. O ( n 2 ) O(n^2) O(n2)
答案: A A A
Hash查找法是由关键字结合Hash函数和冲突处理方法直接算出关键字在表中的位置,与表长无关。
扩展:散列表的平均查找长度与关键字个数无关,只与 装填因子α有关。装填因子是关键字个数和表长度的比值
二叉排序树平均查找长度,查找失败时,比较次数并不是 到 所查找关键字所在的路径长度, 而是 所能找到的关键字的路径长度。
为提高散列(Hash)表的查找效率,可以采取的正确措施是()。
Ⅰ.增大装填因子
Ⅱ.设计冲突少的散列函数
Ⅲ.处理冲突时避免产生聚集(堆积)现象
A.仅Ⅰ
B.仅Ⅱ
C.仅Ⅰ、Ⅱ
D.仅Ⅱ、Ⅲ
答案: B B B
Ⅲ,堆积是不可避免的。
一棵有n个结点的树的所有结点的度数之和为______。
A. n-1
B. n
C. n+1
D. 2n
答案: A A A
错误原因:想成 图 了。
线索二叉树是一种( )结构。
A.逻辑和存储
B.逻辑
C.存储
D.线性
答案: C C C
线索二叉树特指二叉树的二叉链表存储结构的基础上构造的一种新的 存储 结构。
扩展:对二叉树进行线索化 后,后序线索二叉树中求后序后继结点仍然比较麻烦。因为它首先要找到这个结点的父结点,再到其父结点的右子树上找到后序下的第一个结点。
在二叉树的二叉链表中,空指针个数等于非空指针个数加().
A. 2
B. 1
C. 0
D. -1
答案: A A A
对于有n个结点的二叉树,使用二叉链表存储,其中二叉链表一共有2n个指针,其中n-1个指针指向二叉树的结点。剩下n+1个指针为空。
在二叉树的顺序存储中,每个结点的存储位置与其父结点、左右子树结点的位置都存在一个简单的映射关系,因此可与三叉链表对应。若某二叉树共有n个结点,采用三叉链表存储时,每个结点的数据域需要d个字节,每个指针域占用4个字节,若采用顺序存储,则最后一个结点的下标为k(起始下标为1),那么()时采用顺序存储更节省空间。
A. d < 12 n k − n d < \frac{12n}{k-n} d<k−n12n
B. d > 12 n k − n d > \frac{12n}{k-n} d>k−n12n
C. d < 12 n k + n d < \frac{12n}{k+n} d<k+n12n
D. d > 12 n k + n d > \frac{12n}{k+n} d>k+n12n
答案: A A A
在三叉链表中,每一个结点占用的字节数为 d + 4 * 3 = d + 12. 若二叉树有n个结点,则三叉链表需要(d+12) * n 个字节。
相应的,在顺序存储情况下,若最后一个结点的下标为k(起始下标为1),则需要dk个字节。
当 dk <(d+12) *n 时,使用顺序存储更省空间。
一个连通图的生成树是含有该连通图的全部顶点的______。
A. 极小连通子图
B. 极小子图
C. 极大连通子图
D. 极大子图
答案: A A A
一个连通图的生成树是具有为保证连通性的 边最少 的树,是图的极小连通子图。
若一个有向图中的部分顶点不能通过拓扑排序排到一个拓扑有序序列里,则可断定该图是______。
A. 有根有向图(如果G中顶点a到G中每个结点都有路径可以到达,则称结点a为G的根)
B. 强连通图
C. 含有多个入度为0的顶点的图
D. 含有顶点数大于1的强连通分量
答案: D D D
如果 全部顶点 不能通过拓扑排序排到一个拓扑有序序列里,说明该图是一个强连通图,所有顶点构成一个有向环。
如果 部分定点 不能通过拓扑排序排序到一个拓扑有序序列里,说明该图中存在回路,该回路构成一个强连通分量。
图的简单路径是指______不重复的路径。
A. 权值
B. 顶点
C. 边
D. 边与顶点均
答案: B B B
简单路径中,边可以重复也可以不重复。简单路径是指没有重复顶点的路径。
下列关于连通图的BFS和DFS生成树的高度论述正确的是______。
A. BFS生成树的高度小于DFS生成树的高度
B. BFS生成树的高度小于或等于DFS生成树的高度
C. BFS生成树的高度大于DFS生成树的高度
D. BFS生成树的高度大于或等于DFS生成树的高度
答案: B B B
错误原因:看错BFS和DFS了… -_-||
折半查找和二叉排序树的时间性能______。
A. 相同
B. 有时不相同
C. 完全不同
D. 不定
答案: B B B
折半查找的平均查找长度和最大查找长度均为 O ( l o g 2 n ) O(log_2n) O(log2n).
二叉排序树的查找性能与数据的输入顺序有关,最好情况下与折半查找相同,最坏情况下退化为顺序查找。
散列表的平均查找长度与 处理冲突的方法、装填因子α有关。与表长无关。
设定二维整数数组B[0…m][0…n]的数据在行,列方向上都按从小到大的顺序排序,且整型变量k中的数据在B中存在。设计一个算法,找出一对满足B[i][j]=x的i,j值,要求比较次数不超过m+n.
答案:
void findk( int k){
int i = 0, j = n;
while( B[i][j] != k)
if( B[i][j] < k)
i++;
else
j--;
cout<
计算出的地址分布最均匀的散列函数是______。
A. 数字分析法
B. 除留余数法
C. 平方取中法
D. 折叠法
答案: B B B
除留余数法转换后的散列表在表的装填因子不断趋向于1的过程中,查找性能退化速度最慢,说明它产生的冲突最少,散列地址均匀分布在地址空间各处。
在用开放定址法造出的散列表中,散列到同一个地址而引起的“堆积”问题是由于______引起的。
A. 同义词之间发生冲突
B. 非同义词之间发生冲突
C. 同义词之间或非同义词之间发生冲突
D. 散列表“溢出”
答案: C C C
算法可以没有输入,但是必须有输出。
数据结构是一门研究什么内容的学科?
答案:数据结构是一门研究非数值计算的程序设计问题中,计算机的操作对象及对象间关系和施加于对象的操作等的学科。
在给定逻辑结构以及其存储表示上可以定义不同的运算集合,从而得到不同的数据结构。例如:栈和队列。
斐波那契数列的递归算法时间复杂度为 O ( n ) O(n) O(n).
(多选)在下列叙述中,()是错误的。
A.线性表的逻辑顺序与物理顺序总是一致的
B.二叉树的顺序存储结构比链式存储结构节省存储空间
C.二叉树的度小于等于2
D.每种数据结构都具有两种基本运算(操作):插入、删除元素(结点)
答案: A B D ABD ABD
A,链表的逻辑顺序与物理顺序可以不一致。
B,顺序存储需要预先指定空间,可能浪费。(问题:链表中指针不是会占用存储空间吗)
线性表(a1,a2,…,an)以链接方式存储时,访问第i位置元素的时间复杂性为()。
A. O(i)
B. O(1)
C. O(n)
D. O(i-1)
答案: C C C
没有AD那样形式的表述。
线性表的链式存储中,若链表有头结点,则链表的头指针指向头结点。
若在单链表中某个已知结点p 之前 插入一个结点,可以通过交换数据的方式得到。
根据指针的连接方式,可以分为动态链表和静态链表。
循环单链表的最大优点:从任何结点出发都可以访问到链表中的每一个元素。