一、绪论
1.1 数据结构的基本概念
D
因为抽象数据类型(ADT)描述了数据的逻辑结构和抽象运算,通常用(数据对象,数据对象,基本操作集)这样的三元组来表示,从而可构成一个完整的数据结构定义。
而数据结构又是指相互之间存在一种或多种特定关系的数据元素的集合。那么我们就可以用抽象数据类型来定义一个完整的数据结构。
A
数据的逻辑结构是从面向实际问题的角度出发的,只采用抽象表达方式,独立于存储结构,数据的存储方式有多种不同的选择;
而数据的存储结构是逻辑结构在计算机上的映射,它不能独立于逻辑结构而存在。
数据结构包括三个要素(逻辑结构、数据存储结构和数据的运算),缺一不可。
1.2 算法和算法评价
C
时间复杂度是为O(n^2),说明算法的时间复杂度T(n)满足T(n)<=c*n^2(其中c为比例常数),即T(n)=O(n^2),时间复杂度T(n)是问题规模n的函数,其问题规模仍然是n而不是n^2。
A
B
B
C
B
假设第k次循环终止,则第k次执行时,(x+1)^2>n,x的初始值为0,第k次判断时,x=k-1,即k^2>n,k>根号下n,故答案选B
本章的重点就是分析程序的时间复杂度(步骤和方法)。
二、线性表
2.1 线性表的定义和基本操作
allright
2.2 线性表的顺序表示
线性表的顺序存储结构是一种()。
A. 随机存储的存储结构
B. 顺序存储的存储结构
C. 索引存储的存储结构
D. 散列存储的存储结构
A
线性表的顺序存储结构的特点是:
- 逻辑顺序与物理顺序相同。
- 随机访问,即可通过首地址和元素序号可以在在O(1) 时间内找到第 i 个元素。
- 存储密度高,每个节点只存储数据元素。
- 顺序存储分配需要一段连续的存储空间,不够灵活。
- 元素的插入和删除需要移动大量的元素,插入操作平均需要移动n/2个元素,删除操作平均需要移动(n-1)/2个元素。
若线性表最常用的操作是存取第i个元素以及前驱和后继元素的值,为了提高效率,应该采用()的存储方式。
A. 单链表
B. 双向链表
C. 单循环链表
D. 顺序表
D
题干上实际是要求最快存取第i-1、i和i+1个元素。
一个线性表最常用的操作时存取任意一个指定序号的元素并在最后进行插入、删除操作,则利用()存储方式可以节省时间
A. 顺序表
B. 单循环链表
C. 双链表
D. 带头结点的双循环链表
A
只有顺序表可以按序号随机存取,且在最后进行插入和删除操作时不需要移动任何元素。
存取!存取!!存取!!!
C
对于2.顺序表只需要3次交换操作;而链表需要分表找到两个结点前驱,第4个结点断链后再插入到第2个结点后,效率极低。
顺序表的插入算法中,当n个空间已满时,可再申请增加分配m个空间,若申请失败,则说明系统没有()可分配的存储空间。
A. m个
B. m个连续
C. n+m个
D. n+m个连续
D
因为!!!原本的还要复制(再粘贴到后来申请的新空间中),然后顺序存储所需要的是连续的空间
2.3 线性表的链式表示
链式存储设计时,结点内的存储单元地址()。
A. 一定连续
B. 一定不连续
C. 不一定连续
D. 部分连续,部分不连续
A
结点内的存储单元地址一定连续,不同结点之间不一定连续。(爱考的小陷阱)
D
如果先建立链表,然后依次插入建立有序表,则每插入一个新元素就需要遍历链表寻找位置。即直接插入排序,时间复杂度为O(n^2)。
但是但是,如果我们先将数据排序(二分)再建立链表,那我们的时间复杂度就被优化到O(nlog2n)啦。
D
如果单单说只是将长度为n的单链表插入的话,那确实时间复杂度只要O(n),
但是呀,有一个步骤十分的关键,那就是我们需要先遍历出长度为m的单链表的尾结点之后,才能进行插入操作。
D
长度为1的话就指回头结点了,为0则是转了两圈指回去。
在线性表a0,a1,...,a100中,删除元素a50需要移动()个元素。
A. 0
B. 50
C. 51
D. 0或50
D
不可以想当然认为就是顺序存储结构啊,如果是顺序表的话就是50个,但要是链表的话是不需要移动元素的。
小tips(移动次数):删除:(n-1)/2 添加:n/2
A
在链表的末尾插入和删除一个结点时,需要修改其相邻结点的指针域。而寻找尾结点以及尾结点的前驱结点时,只有带头结点的双循环链表所需时间最少。
C
对于A,删除尾结点*p时,需要找到*p的前一个结点,时间复杂度为O(n)。
对于B,删除首结点*p时,需要找到*p结点,这里没有直接给出头结点指针,而通过尾结点的prior指针找到*p的时间复杂度为O(n)。
对于D,删除尾结点*p时,需要找到*p的前一个结点,时间复杂度为O(n)。
设有一个长度为n的单循环链表,若从表中删除首元结点的时间复杂度为O(n),则此时采用的循环单链表结构可能是()。
A. 只有表头指针,没有头结点
B. 只有表尾指针,没有头结点
C. 只有表尾指针,有头结点
D. 只有表头指针,有头结点
A
在循环单链表中,删除首元结点后,要保持链表的循环性,需要先找到首元结点的前驱。
当有头结点时,其前驱就是头结点,因此不论是表头指针还是表尾指针,删除首元结点的时间都为O(1),当没有头结点时,其前驱就是尾结点,因此,若有表尾指针,O(1);
若是只有表头指针则需要遍历整个链表去寻找尾结点,故而时间复杂度为O(n)。
对于一个带头结点的循环单链表L,判断该表为空表的条件是()。
A. 头结点的指针域为空
B. L的值为NULL
C. 头结点的指针域与L的值相等
D. 头结点的指针域与L的地址相等
C
L->next==L 不要妄自菲薄认为这个是地址!!就是相等就完事了
已知头指针h指向一个带头结点的非空单循环链表,结点结构为
其中next是指向直接后继结点的指针,p是尾指针,q是临时指针。现要删除该链表的第一个元素,正确的语句序列是( )。
A. h-> next= h-> next -> next;q= h-> next; free(q);
B. q=h-> next;h-> next= h-> next -> next; free(q);
C. q=h-> next; h-> next=q -> next; if(p != q)p = h; free(q);
D. q=h-> next; h-> next=q -> next; if(p == q)p= h; free(q);
D
陷阱就是在万一若待刪结点是链表的尾结点,即循环单链表中只有一个元素(p 和q指向同一个结点),则在删除后要将尾指针指向头结点,即if(p==q) p=h;最后释放q结点即可,答案选D。
三、栈、队列和数组
3.1 栈
向一个栈顶指针为(top)的链栈(不带头结点)中插入一个x结点,则执行()。
A. top->next=x
B. x->next=top->next;top->next=x
C. x->next=top;top=x
D. x->next=top;top=top->next
C
注意审题!!!是不带头结点
该选项的意思是先将x指向旧栈顶,再将x作为新的栈顶
3个不同元素依次进栈,能得到()不同的出栈序列。
A. 4
B. 5
C. 6
D. 7
B
进栈顺序 abc
出栈顺序 abc acb bca bac cba
上面是直接无脑枚举哦
但其实是有公式的,如下
n个不同元素进栈,出栈元素不同排列的个数为:
这个公式叫做卡特兰数(其实在后面计算树的棵树时也会用到,还是有必要记一下)
有4个元素的进栈次序依次为a b c d则以c d开头的出栈序列的个数为()
A. 1
B. 2
C. 3
D. 4
A
cdba 很显然就只有一个(关键是审题)
【2013 统考真题】一个栈的入栈序列为1,2,3,...,n,出栈序列是P1,P2,P3,...,Pn。若P2=3,则P3可能取值的个数是()。
A. n-3
B. n-2
C. n-1
D. 无法确定
C
bia一个大佬写的觉得超赞,this
3.2 队列
循环队列存储在数组A[0..n]中,则入队时的操作为()
A. rear=rear+1
B. rear=(rear+1) mod (n-1)
C. rear=(rear+1) mod n
D. rear=(rear+1) mod (n+1)
D
循环队列的入队操作是rear=(rear+1) mod MaxSize,而该题的最大尺寸是n+1
与顺序队列相比,链式队列()
A. 优点是队列的长度不受限制
B. 优点是进队和出队时间效率更高
C. 缺点是不能进行顺序访问
D. 缺点是不能根据队首指针和队尾指针计算队列的长度
D
尽管链队总是采用动态分配方式,其长度也受内存大小的限制,也不可能实现无限长队列。
顺序队和链队的进队和出队操作时间均为0(1)。
顺序队和链队都可以进行顺序访问。
在顺序队中可以通过队头和队尾指针计算队中元素个数,而链队不能。
最不适合作链式队列的链表是()
A. 只带队首指针的非循环双链表
B. 只带队首指针的循环双链表
C. 只带队尾指针的循环双链表
D. 只带队尾指针的循环单链表
A
只有A选项查找队尾时间复杂度最长O(n),其他都只需要O(1)
那为什么要查找队尾呢?是因为队列是一种受限的线性表,而一般是选定队尾作为允许插入的一端,所以需要先查找队尾,再进行插入操作。
用链式存储方式的队列进行删除操作时需要()
A. 仅修改头指针
B. 仅修改尾指针
C. 头尾指针都要修改
D. 头尾指针可能都要修改
D
考虑问题不能太片面了。(以后就看选项想特例)
在有头结点的链队列的出队操作中,一般只需修改队头指针,但当原队列中只有一个结点时,该结点既是队头也是队尾,故删去此结点时亦需修改队尾指针,使其指向头结点,且删去此结点后队列变空。
在一个链队列中,假设队头指针为front,队尾指针为rear, x所指向的元素需要入队,则需要执行的操作为( )。
A. front=x,front= front->next
B. x->next=front->next, front=x
C. rear->next=x, rear=x
D. rear->next=x, x->next=null, rear=x
D
A、B错误的太明显了就不说了,现在看回C、D,C相较于D不够严谨
【2011统考真题】已知循环队列存储在一维数组A[0…n-1]中,且队列非空时front和rear分别指向队头元素和队尾元素。若初始时队列为空,且要求第一个进入队列的元素存储在A[0]处,则初始时front和rear的值分别是( )。
A. 0,0
B. 0,n-1
C. n-1, 0
D. n-1,n-1
B
首先“队列非空时front和rear分别指向队头元素和队尾元素。”意思就是说当队列中有一个元素时,front与rear都需要指向A[0]。那我们又知道在循环队列中添加一个元素的操作是(rear+1)%MaxSize,所以这时候rear的位置为0。那我们逆思考下在队列为空的时候,是不是rear的位置应该是为n-1(数据的最后一位嘛)。再考虑front指针,如果只有入队操作的话是不是位置不会改变。
故,该题选0,n-1
【2014统考真题】循环队列放在一维数组A[0...M-1]中,end1指向队头元素,end2指向队尾元素的后一个位置。假设队列两端均可进行入队和出队操作,队列中最多能容纳M-1个元素。初始时为空。下列判断队空和队满的条件中,正确的是( )。
A. 队空:end1==end2;队满:end1==(end2+1)mod M
B. 队空:end1==end2;队满:end2==(end1+1)mod (M-1)
C. 队空:end2==(end1+1) mod M;队满:end1==(end2+1) mod M
D. 队空:end1==(end2+1) mod M;队满:end2==(end1+1) mod (M-1)
A
队头指针在队尾指针的下一位置时,队满。
Q.front == (Q.rear + 1) % MAXSIZE 因为队头指针可能又重新从0位置开始,而此时队尾指针是MAXSIZE - 1,所以需要求余。
当队头和队尾指针在同一位置时,队空。Q.front == Q.rear;
3.3 栈和队列的应用
【2017年统考真题】下列关于栈的描述中,错误的是()。
Ⅰ.采用非递归方式重写递归程序时必须使用栈
Ⅱ.函数调用时,系统要用栈保存必要的信息
Ⅲ.只要确定了入桟次序,即可确定出栈次序
Ⅳ.栈是一种受限的线性表,允许在其两端进行操作
A. 仅Ⅰ
B. 仅Ⅰ、Ⅱ、Ⅲ
C. 仅Ⅰ、Ⅱ、Ⅲ
D. 仅Ⅱ、Ⅲ、Ⅳ
C
睁眼瞎,呜呜呜。
首先采用非递归方式重写递归程序时必须使用栈这是不一定的啊,就比如斐波拉契数列迭代实现就只要一个循环即可。
然后我们接着看3,怎么可能!!确定了入栈次序,就会知道出栈次序了,乱来啊这个是。
最后一个的错误就是栈是一种受限的线性表,只允许在其一端进行操作。
A
使用栈确实可以模拟递归的过程,以此用来消除递归,但对于单向递归和尾递归而言,可以用迭代的方式来消除递归。
3.4 数组和特殊矩阵
B
因为是三对角矩阵故我们可以直接套公式(行优先):k=2i+j-3
可以很快得出答案,but一般人到后期就忘记了。我觉得可以灵活点直接算,毕竟数值不是很大,
那其实我们不难发现就是第一行有两个元素,剩下的在元素 m[30][30] 所在行之前的28行,然后每行三个元素,最后在 m[30][30] 之前还会有一个元素,那就可以计算了2+28*3+1=87
B
稀疏矩阵采用压缩存储后的缺点主要是()。
A. 无法判断矩阵有多少行多少列
B. 丧失了随机存储的特性
C. 无法根据行列号计算矩阵元素的存储地址
D. 使矩阵元素之间的逻辑关系更加复杂
B
稀疏矩阵通常采用三元组来压缩存储,存储矩阵元素的行列下标和相应的值,因此不能根据矩阵元素的行列下标来快速定位矩阵元素,失去了随机存储的特性。
若采用三元组表存储结构存储系数矩阵M。则除三元组外,下列数据中还需要保存的是()。
Ⅰ. M的行数 Ⅱ. M中包含非零元素的行数
Ⅲ. M的列数 Ⅳ. M中包含非零元素的列数
A. 仅I、III
B. 仅I、II
C. 仅III、IV
D. I、II、III、IV
A
三元组存储的是矩阵的行、列及值,但从三元组并不能推断原稀疏矩阵的大小。要完整表示稀疏矩阵还需要知道矩阵的行数和列数。
四、串
*4.1 串的定义和实现
4.2 串的匹配模式
B
五、树
5.1 树的基本概念
B
设一棵度为3的树,其中度为3的结点n3=2,度为2的结点数n2=1,叶结点数n0=6,则该树的结点总数为()。
A. 12 B. 9 C. 10 D. >=9的任意整数
D
若森林F有15条边、25个结点,则F包含树的个数是()。
A. 8 B. 9 C. 10 D. 11
C
此森林由最原始的一棵树转化而来,在这个过程中总结点数是不会变的,变的只是边数。最原始的边数为25-1=24,而每多生成一棵树就会少一条边。所以公少了24-15=9条边,所以共分了9次。所以现在树的个数为9+1=10。
5.2 二叉树的概念
C
注:哇~这题真的超级容易上当,注意关键字第6层有8个叶结点,意思只是说在这层有8个叶结点,没说就只有6层啊。
如上图就是一个第3层有3个叶结点的完全二叉树。(题目中也是一样的,只是我懒的画)
所以我们直接计算首先前5层肯定是满的,先有31个。由于是完全二叉树且求结点个数最多的情况于是,第六层也应该是满的。关键在于第7层,因为第6层有8个叶子结点也就是说第7层会少16个(离满的情况下)
C
注:首先看题意最多有多少结点,那就是求完全二叉树的在第7层有多少个结点,那其实就是
B
注:关键知识点判断n1是否为1(在完全二叉树中最多只会有一个度为1的结点)
设有n(n>=1)个结点的二叉树采用三叉链表表示,其中每个结点包含三个指针,分别指向其左孩子,右孩子及双亲(若不存在,则置为空)则下列说法正确的是()。
1、树中空指针的数量为n+2
2、所有度为2的结点均被三个指针指向
3、每个叶结点均被一个指针所指向
A. 1 B. 1、2 C. 1、3 D. 2、3
A
注:二叉链表表示的二叉树中空指针的数量为n+1,三叉链表表示的二叉树多了一个根节点指向双亲的空指针,所以树中的空指针数量为n+2,1正确。若根结点的度为2,则只有左、右两个孩子指向它,2错误。若整棵树只有一个根结点,则没有指针指向它,3错误。
三叉链表中,n个结点有多少个空域?
三叉链表每个节点有三个指针域(左、亲、右),共3n个指针。
其中非空指针=亲(n-1个,因为根节点没有双亲)+左右(n-1,因为n个节点的二叉树有n-1条边)=2n-2;
所以空指针=3n-(2n-2)=n+2。
大佬解释
如果一棵非空 k(k≥2)叉树 T 中每个非叶结点都有 k 个子,则称 T 为正则 k 叉树。请回答下列问题并给出推导过程。
(1)若 T 有 m 个非叶结点,则 T 中的叶结点有多少个?
(2)若 T 的高度为 h(单结点的树 h=1),则 T 的结点数最多为多少个?最少为多少个?
5.3 二叉树的遍历和线索二叉树
设n,m为一颗二叉树上的两个结点,在后序遍历时,n在m前的充分条件是()。
A.n在m右方
B.n是m祖先
C.n在m左方
D.n是m子孙
D
注:充分充分!!意思是什么条件能够推出来 n在m前
C
注:在后续遍历退回时访问根节点,就可以从下到上把从n到m的路径上的点输出,若采用非递归的算法,当后序遍历访问到n时,栈中把从根到n的父指针的路径上的结点都记忆下来。
C
注:二叉树一种逻辑结构,但线索二叉树是加上线索后的链表结构,即它是二叉树在计算机内部的一种存储结构,所以是一种物理结构。
1)表达式树的中序序列加上必要的括号即为等价的中缀表达式。可以基于二叉树的中序遍历策略得到所需要的表达式。表达式树中分支结点所对应的子表达式的计算次序,由该分支结点所处的位置决定。为得到正确的中缀表达式,需要在生成遍历序列的同时,在适当位置增加必要的括号。显然,表达式的最外层(对应根结点)和操作数(对应叶结点)不需要添加括号。
2)算法实现
将二叉树的中序遍历递归算法稍加改造即可得到本题的答案。除根结点和叶结点外,遍历到其他结点时在遍历器左子树之前加上左括号,遍历完右子树后加上右括号。
typedef struct node{
char data[10];
struct node *left,*right;
}BTree;
void BtreeToE(BTree *root){
BtreeToExp(root,1); //根的高度为1
}
void BtreeToExp(Btree *T,int deep){
if(T==NULL)
return; //空结点返回
else if(T->left==NULL&&T->right==NULL) //若为叶结点
printf("%s",T->data); //输出操作数,不加括号
else{
if(deep>1) //若有子表示式则加1层括号
printf("(");
BtreeToExp(T->left,deep+1);
printf("%s",T->data); //输出操作符
BtreeToExp(T->right,deep+1);
if(deep>1) //若有子表示式则加1层括号
printf(")");
}
}
5.4 树、森林
D
若只有一颗树的情况下,的确为空,但一颗以上时,指向的应该是第二棵树的根节点才对。
C
还是一样的,老是被文字陷阱呢?
非终端!
D
树转为二叉树时,树的每个分支结点的所有子结点中的最右子结点无右孩子,根节点转换后也没有右孩子,所以,该题中所问二叉树中无右孩子的结点个数应该=分支结点数+1
5.5 树与二叉树的应用
若度为m的哈夫曼树中,其叶结点个数为n,求解非叶结点的个数
叶结点即度为0的结点有n个;
假设度为m的结点个数为x,则x+n=mx+1(也就是x=n-1/m-1)
若n-1不能被整除,即所给数据不能直接构造最优m叉树,这时需要加一些不影响建树的数据,可以添0;添加的个数为(m-1)-((n-1)%(m-1))。所以最终x应该为⌈n-1/m-1⌉ 。
六、图
6.1 图的基本概念
B
首先,强连通图是有向图故先排除; 而对连通图做一次深度优先搜索确实是可以访问所有结点的(若图G中任意两个顶点都是连通的,则称图G为连通图,否则称为非连通图。),然后有回路的无向图可不一定是连通图,不一定能够访问所有结点。连通图可能是一棵树,但其也有可能存在环。
C
图的遍历要求每个结点只能被访问一次。
B
环的边数等于顶点数啊,每一条边断开都是一棵新的生成树。
B
无向图边数的2倍=各顶点度数之和。要求的是最少的定点数,故使每个顶底的度取最大,设为2(均小于3)接下来列个方程:4*3+3*4+2*x=16*2,最后算出来x=4,所以至少包括4+4+3=11个顶点。
6.2 图的存储及基本操作
D
因为如果无向图采用邻接表时,每条边需要存储两次,所以其边表结点肯定为偶数。
C
邻接表:反映的是顶点出度的情况。
逆邻接表:反映的是顶点的入度情况。
B
每张无向图最多有n(n-1)/2条边,每条边在邻接表中存储两次。
C
首先是有向图,与顶点有关的边包括,出边和入边,对于出边,只需遍历v的顶点表结点和其指向的边表就好;但是在邻接表中,想要删除入边,则需要遍历整个边表。
B
6.3 图的遍历
下列关于图的说法中,错误的是()。
1.对一个无向图进行深度优先遍历时,得到的深度优先遍历序列是唯一的。
2.若有向图不存在回路,即使不用访问标志位,同一结点也不会被访问两次。
3.采用深度优先遍历或topo排序算法可以判断一个有向图是否有环(回路)
4.对任何非强连通图必须2次或以上调用广度优先遍历算法才可以访问所有的顶点。
A. 1、2、3
B. 2、3
C. 1、2
D. 1、2、4
D
图的深度优先遍历是不唯一的;
即使图中不存在回路,不设置访问标志位的话就是会重复访问;
不一定说非得非强连通图必须2次或以上调用广度优先遍历算法才可以访问所有的顶点。比方说是是一直溜的图形呢。
D
显而易见有aebfdc、aefdbc
B
这种题目首先可以先分为两类,D对A肯定对,而BC是对立的,那我们很简单就可以知道生成树就是一个无环子图,且是极小连通子图,直接选出答案。
D
我们可以很容易画出相对应的图像吼,然后直接暴力枚举就完事了。
0132、0231、0213、0321、0312
6.4 图的应用
用Dijkstra算法求得一个带权有向图从顶点0出发的最短路径,在算法执行的某个时刻,已求得的最短路径的顶点集合S={0,2,3,4},下一个选取的目标顶点是顶点1,则可能修改的最短路径是()。
A. 从顶点0到顶点3的最短路径
B. 从顶点0到顶点2的最短路径
C. 从顶点2到顶点4的最短路径
D. 从顶点0到顶点1的最短路径
D
在Dijkstra算法的执行过程中,只可能修改从源点0到集合V-S中某个顶点的最短路径。
C
最简单的做法还是直接全部排列出来。
ABCFDFG、ABCDFEG、ABCDEFG、ABDCFEG、ABDCFEG和ABDCEFG。
C
审题!!有序的拓朴排序序列。
C
有向图邻接矩阵的第V行中1的个数是顶点V的出度,而有向图中的顶点的度为入度和出度之和;
无向图的邻接矩阵一定是对称矩阵,但在有向图中,如果是强连通图的话也会是对称矩阵。
而有向无环图的topo序列唯一并不能唯一确定该图。
C
一个事件的最迟发生时间是min{以该事件为尾的弧的活动的最迟开始时间,以该事件为尾的弧所指事件的最迟发生时间与该弧的活动的持续时间之差}
C
七、查找
7.1 查找的基本概念
7.2 顺序查找和折半查找
下列关于查找的说法中正确的是()。(注,涉及下节内容)
A. 若数据元素保持有序,则查找时就可以采用折半查找。
B. 折半查找与二叉查找树的时间性能在最坏情况下是相同的。
C. 折半查找的平均查找长度一定小于顺序查找法。
D. 折半查找法查找一个元素大约需要O(log2n)次关键字比较。
D
折半查找虽然是要求数据元素有序,但还有很重要的一点是要顺序存储。
折半查找最坏情况下的时间复杂度应该是O(log2n),而二叉查找树在最坏情况下应该是O(n)(一棵单边树)
这不一定哦,就比如要查找的元素在第一位呢?
7.3 树形查找
五个不同结点构造的二叉查找树的形态共有()种?
A. 20
B. 30
C. 32
D. 42
D
五个不同结点构造的二叉查找树,其中中序序列是唯一确定的。先序序列的个数为n=5的卡特兰数。中序序列和先序序列能够唯一确定一棵二叉树,因此二叉排序树的形态一共有Catalan(5)=42
具有5层结点的平衡二叉树至少有()个结点。
A. 10
B. 12
C. 15
D. 17
B
这种题最简单也是最直接的方法当然就是画出来,在保证平衡的情况下,结点数量尽可能的少就好。
含有20个结点的平衡二叉树的最大深度为()。
A. 4
B. 5
C. 6
D. 7
C
当然还是先画为敬,不过平衡二叉树结点数其实是有一个递推公式的
n0=0,n1=1,n2=2,nh=1+n(h-1)+n(h-2)
关于红黑树和AVL树,以下哪种说法不正确?()
A. 两者都属于自平衡的二叉树
B. 两者插入、删除、查找的时间复杂度都相同
C. 红黑树的插入和删除过程中至多有两次旋转操作
D. 红黑树的任意一个结点的左右子树高度(含叶子结点)之比不超过2
C
A显然是对的,红黑树的本质就是二叉排序树
B他俩这些操作的时间复杂度都是O(log2n)
C在红黑树的删除过程中可能不止需要两次的旋转操作
D根据红黑树性质之一“黑路同”其实就可以很简单推出来这个选项是正确的。
若平衡二叉树的高度为6,且所有非叶结点的平衡因子均为1,则该平衡二叉树的结点总数()。
A. 12
B. 20
C. 32
D. 33
B
所有非叶结点的平衡因子均为1即该平衡二叉树满足平衡的最少结点情况,那我们可以直接套公式啊(n0=0,n1=1,n2=2,nh=1+n(h-1)+n(h-2))
7.4 B树和B+树
下图所示是一棵()
A. 4阶B树
B. 3阶B树
C. 4阶B+树
D. 无法确定
D
这题的陷阱意味就太明显了,考察我们是否了解B树和B+树的定义。
首先关键字数比子树数目少1,首先可以先排除B+树。再看图15 19 22有三个关键字数,因此B可以排除,但我们无法确定该棵树到底是4阶、5阶还是6阶B树。
A D
直接套公式即可。
A
与上题相似,可以直接套公式。
【2014统考真题】在一棵高度为3的3阶B树中,根为第1层,若第2层中有4个关键字,则该树的结点数最多是()。
A. 11
B. 10
C. 9
D. 8
A
最土的方法就是最厉害的方法,动动发财的小手直接画出答案即可。
(当然你得知道b树的基本性质)
7.5 Hash表
A
这题很容易被 这些个名词吓到啊。
首先聚集是什么呢?是指非同义词之间的冲突,所以同义词之间的冲突并不能算是聚集。
当用线性探测再散列法解决冲突时,计算出的一系列“下一个空位”的要求是()。
A. 必须大于或等于原散列地址
B. 必须小于或等于原散列地址
C. 可以大于或小于但不等于原散列地址
D. 对地址在何处没有限制
C
C
说真的很讨厌这个类型的题目,就是很容易自己把自己绕进去。逻辑!!
不确定和任可能会该怎么选呢?我们反着想散列表不能绝对地避免冲突对吧,那根本上就是说还是有可能会产生的。
D
堆积现象因为冲突而产生,它对存储效率、散列函数和装填因子均不会有影响,而平均查找长度会因为堆积现象而增大。
八、排序
8.1 排序的基本概念
allright
8.2 插入排序
若序列{15,9,7,8,20,-1,4}经一趟排序后变为{15,-1,4,8,20,9,7},则采用的是()方法。
A. 选择排序
B. 快速排序
C. 直接插入排序
D. 冒泡排序
C
首先可以先排除快速排序和冒泡排序,那选择排序应该会先挑出来一个最大或者最小的数据元素才对,所以也可以排除。
对序列{E,A,S,Y,Q,U,E,S,T,I,O,N}按照字典序排序,采用增量d=6,3,1的希尔排序算法,则前两趟排序后,关键字的总比较次数为()。
A. 15
B. 17
C. 16
D. 18
B
(小tips:在每个分组内执行的是直接插入排序。)
8.3 交换排序
C
D
快速排序的递归次数与元素的初始排列有关。若每次划分后分区比较平衡,则递归次数少;若划分后分区不平衡,则递归次数多。递归次数与分区处理顺序无关。
8.4 选择排序
已知大根堆{62,34,53,12,8,46,22},删除堆顶元素后需要重新调整堆,则在此过程中关键字的比较次数为()。
A. 2
B. 3
C. 4
D. 5
B
A
8.5 归并排序、基数排序和计数排序
D C
归并排序在平均情况和最坏情况下的时间复杂度都是O(n),快速排序只在最坏情况下才是O(n),平均情况是O(log2n)。
A B
当一个表中的最小元素比另一个表中的最大元素还大时,比较的次数是最少的,仅仅需要n次;而最坏的情况就是两个表中的元素需要依次间隔地比较,需要2n-1次
设线性表中每个元素有两个数据项k1和k2,现对线性表按一下规则进行排序:先看数据项k1,k1值小的元素在前,大的在后;在k1值相同的情况下,再看k2,k2值小的在前,大的在后。满足这种要求的排序方法是( )
A.先按k1进行直接插入排序,再按k2进行简单选择排序
B.先按k2进行直接插入排序,再按k1进行简单选择排序
C.先按k1进行简单选择排序,再按k2进行直接插入排序
D.先按k2进行简单选择排序,再按k1进行直接插入排序
D
首先得先明白题意啊,这里的排序应该是对整体进行排序吧,不是说先来比k1之后再去比k2,也有可能我是比较特殊的笨蛋。再看题目先比k1,也就是k1的优先级是大于k2的(这就是之前我一直没有想明白的地方,所以我们应该先排k2因为这样不会打乱k1的排序结果)第2个困难点就是明面上看k1,k2都是小的在前大的在后(是不是直接插入和简单选择都可以),可我们在对k2进行排序时不需要考虑算法的稳定性,而对于k1来说,必须得是稳定的否者可能会改变其相对次序。所以答案选D
有n个十进制整数进行基数排序,其中最大的整数为5位,则基数排序过程中临时建立的队数个数是( )。
A. 5
B. 10
C. n
D. 2
B
不要被骗啊,基数排序的话就是几进制就需要几个队列
已知两个长度分别为m 和 n 的升序链表,合并降序链表,求时间复杂度?
O(max(m,n))
考虑两个升序链表合并,两两比较表中元素,每比较一次,确定一个元素的链接位置(取较小元素,头插法)。当一个链表比较结束之后,将另一个链表的剩余元素直接插入即可。最坏的情况就是两个链表中的元素依次比较。又因为2max(m,n)>=m+n,所以时间复杂度为O(max(m,n))。
下列各种排序算法中,()需要的附加存储空间最大。
A. 快速排序
B. 堆排序
C. 归并排序
D. 插入排序
C
8.6 各种内部排序算法的比较及应用
C
堆是用于排序的,说明在查找时它是无序的,所以效率自然没有其他查找结构高,不要妄自菲薄把堆想成排序树噢。
对于同等大小的不同初始序列,总比较次数一定的是()。
A. 插入折半排序和简单选择排序
B. 基数排序和归并排序
C. 冒泡排序和快速排序
D. 堆排序
A
简单选择排序的总比较次数显然是确定的。折半插入排序每趟的比较次数都是O(log2m)(m为当前已经排好序的子序列的长度),因此它的总比较次数也是一定的。
D
因为堆排序和希尔排序都利用了顺序存储的随机访问特性,如果改为链式存储,就不支持这种性质了,所以时间复杂度会增加。
如果一台计算机具有多个可并行运行的CPU,就可以同时执行相互独立的任务。归并排序的各个归并段的归并也可并行执行,因此称归并排序是可并行执行的。那么以下的排序方法不可以并行执行的有( )。
Ⅰ.基数排序 Ⅱ.快速排序 Ⅲ.冒泡排序 Ⅳ.堆排序
A. 仅Ⅰ、Ⅲ
B. 仅Ⅰ、Ⅱ
C. 仅Ⅰ、Ⅲ、Ⅳ
D. 仅Ⅱ、Ⅳ
A
基数排序每趟需要利用前一趟已经排好序的序列,故无法并行执行。
快速排序每趟划分的子序列倒是互补影响,所以可以并行执行。
冒泡排序每趟需要对未排序的所有元素进行一趟处理,故无法并行执行。
堆排序是可以并行的,因为根结点的左右子树构成的子堆在执行过程中是互不影响的。
8.7 外部排序
allright