一、选择题(本大题共 10 小题,每小题2分,共20分)
1、算法的计算量的大小称为计算的( )。
A.效率 B.复杂度 C.现实性 D.难度
2、为解决计算机与打印机之间速度不匹配的问题,通常设置一个打印数据缓冲区,主机将要输出的数据依次写入该缓冲区,而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是( )。
A.栈 B.队列 C.树 D.图
就是简单的先进先出——队列
3、若让元素1,2,3,4依次进栈,则出栈次序不可能出现( )的 情况。
A.3,2,1,4 B.2,1,4,3 C.4,3,2,1 D.1,4,2,3.
4、设有一个二维数组 A[m][n],假设 A[0][0]存放位置在 644(10),A[2][2] 存放位置在 676(10) , 每 个 元 素 占 一 个 空 间 , 问A[3][3](10)存放在( )位置?脚注(10)表示用 10 进制表示。
A.688 B.678 C.692 D.696
A[2][2]比A[0][0]多两行两列,多了676-644=32,而A[3][3]比A[2][2]多了一行一列,它就比A[2][2]多16,所以它的位置是676+16=692
5、已知一棵完全二叉树的第 6 层(设根为第 1 层)有 8 个叶结点,则完全二叉树的结点个数最多是( )。
A.39 B.52 C.111 D.119
6、若数据元素序列 11,12,13,7,8,9,23,4,5 是采用下列排序方法之一得到的第二趟排序后的结果,则该排序算法只能是( )。
A.起泡排序 B.直接插入排序 C.选择排序 D 二路归并排序
冒泡排序——每一趟都会把最大的移到序列末尾or把最小的移到序列前端
选择排序——每次选出最小的依次排在前面
二路归并排序——第一趟排序结束都可以得到若干个有序子序列,而此时的序列中并没有两两元素有序排列
直接插入排序——从a[i](i=2,3,4……)开始通过比较大小插入到a[1]---a[i-1]中,题目给出的序列前三个元素是有序的,所以该题选B 直接插入排序
7、在一棵度为 4 的树 T 中,若有 20 个度为 4 的结点,10 个度为 3 的结点,1 个度为 2 的结 点,10 个度为 1 的结点,则树 T 的叶节点个数是( )。
A.41 B.82 C.113 D.122
在2021的试卷中也出现了这道题
记住这个公式即可——总度和=总结点数-1
设叶子结点为D0
该题有 20*4+10*3+1*2+10*1=20+10+1+10+D0-1
得 D0=82
8、若无向图 G(V,E)中含 7 个顶点,则保证图 G 在任何情况下都是连通的,则需要的边数最少是( )。
A.6 B.15 C.16 D.21
这道题我错选了A.6
这道题说的是任何情况下都是连通的
显然,这不连通,就不满足“任何情况”这个条件了。
有7个顶点,我们可以先让6个顶点完全连通,根据无向完全连通图的边的公式n*(n-1)/2,要想让6个顶点完全连通,需要6*(6-1)/2=15条边,然后在随便拉条边连上第7个顶点即可
已知一个长度为 16 的顺序表 L,其元素按关键字有序排列,若采用折半查找法查找一个不存在的元素,则比较次数最多是( )。
A.4 B.5 C.6 D.7
折半查找法&二叉排序树
16个元素构成的二叉排序树有5层,查找次数最多即查到最后一层,也就是查了5次
10、在一个算法中的语句频度之和为T(n)=3720n+4nlogn,则算法的时间复杂度为( )。
A.n B.n+4nlogn C.nlogn D.3720n
二、应用题(本大题共 6 小题,每小题5分,共30分,要求写出解题过程)
1、设有如下连通图,按克鲁斯卡尔(Kruskal)算法求其最小生成树,请写出生成过程。
克鲁斯卡尔算法——每次选择权值最小的边,直至所有顶点都在同一连通分量上
答案:
2、已知电文内容为: ACACBACDAACDBAACADAA ,字符集为A,B,C,D,设计一套二进制编码,使得上述电文的编码最短。
可知A、B、C、D出现的次数分别为10、2、5、3
在2021数据结构卷上有讲过
答案:
3、给定关键字序列(11, 80, 65, 33, 34, 89, 56, 51, 28 ,97),散列函数为H(k)=k%7.散列表标长为13,用开放定址法的线性探测再散列处理冲突,试画出散列表,并求出等概率下查找成功的平均查找长度。
这个在2021的试卷上也讲过,但是没讲等概率下查找成功的平均查找长度
答案:
4、对以下序列进行堆排序,使之按关键字递增排序。首先判断应该使用大根堆排序还是小根堆排序,再次判断以下序列是否是堆,不是则把它调整为堆。请写出排序过程中得到的初始堆和一趟堆排序后的序列。(12 ,70,33,65,24,56,48,92,86,34)
答案:
5、已知一关键字序列为(46,15,20,35,28,58,18,50,54),试生成一棵平衡的二叉排序树(请写出生成过程),再从生成的平衡的二叉排序树中删除关键字50,再画出删除之后的平衡二叉树。【这题比较难啊啊啊啊】
答案:
不懂的话可以看看我画的步骤(自认为对的差不多TUT)
更正一下!!第4步应该是LL型!!
此时的46为最低不平衡结点,所以是LL型。
不知道最低不平衡结点是什么没关系!我教你!
首先,平衡因子绝对值大于1的结点为不平衡结点(平衡因子=左子树高度-右子树高度);
然后,离根结点最远的不平衡结点为最低不平衡结点
6、已知一个顺序存储的有序表为(15,26,34,39,45,56,58,63,74),试画出对应的折半查找判定树。【这个也很难啊啊】
答案:
三、程序填空题(本大题共 5 小题,共15个空白处,每空2分,共30分,注意:每空只填一个语句)
1、实现对单链表实现就地逆置。
// 带头结点的单链表的逆置
Status ListOppose_L(LinkList &L)
{ LinkList p,q;
p=L;
p=p->next;
(1) ;
while(p)
{
q=p;
p=p->next;
(2) ;
(3) ;
}
return OK;
}
2、假设称正读和反读都相同的字符序列为“回文”,例如,‘abba’和‘abcba’是回文,‘abcde’和‘ababab’则不是回文。试写一个算法,调用栈和队列相关算法判别读入的一个以‘@’为结束符的字符序列是否是“回文”。
Status SymmetryString(char* p)
{
Queue q;
Stack s;
ElemType e1,e2;
if(!InitQueue(q)) return 0;
InitStack(s); // 初始化空栈
while(*p!=’@’)
{
(4) ;
(5) ;
p++;
}
while(!StackEmpty(s))
{
(6) ;
(7) ;
if(e1!=e2) return FALSE;
}
return OK;
}
3、按先序交换二叉树的左右子树。
Status ExchangeBiTree(BiTree& T)
{
BiTree p;
if(T){
p=T->lchild;
(8) ;
T->rchild=p;
(9) ;
(10) ;
}
return OK;
}
4、希尔排序
void ShellInsert(SqList &L,int dk)
{
//对顺序表L做一趟增量是dk的希尔插入排序
int i,j;
for(i=dk+1;i<=L.length;++i)
if(L.r[i].key<L.r[i-dk].key)
{ //需将L.r[i]插入有序增量子表
L.r[0]=L.r[i]; //暂存在L.r[0]
for(j=i-dk; j>0&& L.r[0].key<L.r[j].key;(11) ; )
(12) ;
(13) ;
}
}
5、按广度优先非递归遍历连通图G
void BFS (Graph G, int v){
sqQueue Q;
ArcType u;
ArcType w;
cout << G.vexs[v] << " ";
visited[v] = true; //访问第v个顶点,并置访问标志数组相应分量值为true
InitQueue(Q);
(14)—————————— ;
while(!QueueEmpty(Q))//队列非空
{
DeQueue(Q, u);
for(w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w))
{
//依次检查u的所有邻接点w ,FirstAdjVex(G, u)表示u的第一个邻接点
//NextAdjVex(G, u, w)表示u相对于w的下一个邻接点,w≥0表示存在邻接点
if(!visited[w])
{ //w为u的尚未访问的邻接顶点
cout << G.vexs[w] << " ";
visited[w] = true;
//访问w,并置访问标志数组相应分量值为true
(15) ————————————;
}
}
}
}//BFS
答案:
(1) L->next=NULL;
(2) q->next=L->next;
(3) L->next=q;
(4) Push(s,*p);
(5) EnQueue(q,*p); //(4)和(5)语句可以交换
(6) Pop(s,e1);
(7) DeQueue(q,e2); //(6)和(7)语句可以交换
(8) T->lchild=T->rchild;
(9) ExchangeBiTree(T->lchild);
(10) ExchangeBiTree(T->rchild);
(11) j-=dk
(12) L.r[j+dk]=L.r[j];
(13) L.r[j+dk]=L.r[0];
(14) EnQueue(Q, v);
(15) EnQueue(Q, w);
四、算法设计题(本大题共 2小题,每小题10分,共20分)
注意:请先用文字简要说明算法思想,然后写出算法的C或C++语言源代码。
1.设计算法判断带头节点的单链表L是否是递增的单链表,单链表的存储结构如下。
typedef struct LNode
{
ElemType data;
LNode *next;
}LNode, *LinkList;
2.用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目,可以调用教材上实现的队列和栈等数据结构的相关算法,二叉树采用二叉链表存储,存储结构如下。
typedef struct BiTNode {
TElemType data;
struct BiTNode * lchild,* rchild;
} BiTNode,*BiTree;
1、参考答案:
int isriselk(LinkList &L)
{
LNode *p = L->next, *q;
if(p != NULL)
{
while(p->next != NULL)
{
q = p->next; //q是p的后继
if (q->data > p->data) //只要是递增的,就继续考察其后继
p = q;
else
return false; //只要有一个不是后继大于前驱,便不是递增
}
2、参考答案
int Level(BiTree bt) //层次遍历二叉树,并统计度为1的结点的个数
{
SqQueue Q;
int num=0; //num统计度为1的结点的个数
if(bt)
{ InitQueue (Q);
EnQueue (Q,bt);
//Q是以二叉树结点指针为元素的队列
while(!QueueEmpty(Q))
{
p=DeQueue(Q); cout<<p->data; //出队,访问结点
if(p->lchild && !p->rchild ||!p->lchild && p->rchild) num++;
//度为1的结点
if(p->lchild)
EnQueue(Q,p->lchild); //非空左子女入队
if(p->rchild)
EnQueueIn(Q,p->rchild); //非空右子女入队
} // while(!QueueEmpty(Q))
}//if(bt)
return(num);
}//返回度为1的结点的个数