数据结构与算法期末复习解析

目录

前言

 一.单项选择题

1.以下代码片段的时间复杂度为:

2.关于线性表,下列描述错误的是( )。

3.以下链表的优点的是( )。

4.网络服务器响应客户端的请求,需要用到以下数据结构中的( )。

5.一个栈的入栈序列为{a,b,c,d,e},则栈的出栈序列不可能是( )。

6.两个字符串相等的条件是( )。

7.以下不属于特殊矩阵的是( )。

8.一棵树的度为5,指的是( )。

9.对一棵完全二叉树,其中编号为7的结点,如果它有右孩子,那它的右孩子的编号为 ( )。

10.线索二叉树中,如果某个结点的rtag为1,那么它的右孩子指针域指向它的( )。

11.一棵二叉树,如果其中度为2的结点数量为9,那么这棵二叉树叶子结点有( )个。

12.一个有n个顶点的无向图,如果它是连通的,那么它至少有( )条边。

13.若从无向图的任意一个顶点出发进行一次深度优先搜索可以访问图中所有的顶点, 则该图一定是( )图。

14.二分查找要求查找表是( )的。

15.设有15个数据元素构成查找表,采用顺序查找的方式,则平均查找长度为( )。

16.以下排序方法属于稳定排序的是( )。

17.如果有8个数据元素进行排序,那么至少需要比较( )次。

18.如果对一个序列进行升序排序,使用直接插入排序方法,在这个序列( )情况下, 比较和移动次数最少。

19.图的深度优先遍历是应用( )算法。

20.以下使用到贪心算法的是( )。

二.判断题

1.请简述一个完整算法必须具有的要素。

2.设主串“institute”,请写出其中字符串长度为5的所有子串,并写出他们在主串中的 位置(从1开始)

3.一个矩阵A[12][15]以行为主序进行存储,其首元素A[0][0]的物理地址为360,每个 数据元素所占的存储空间为3,求A[6][5]的地址。要求写出计算过程

四.应用题

1.请写出下图所示的二叉树先序.中序和后序遍历的结果。

2. 假定用于通信的电文由8个字符A、B、C、D、E、F、G组成,各字母在电文中出现 概率为22%、24%、14%、7%、18%、3%、12%。现在把字符出现概率扩大100倍后, 作为这8个字母对应的权值(22,24,14,7,18,3,12)。请回答以下问题:。

(1)画出以这些权值构成的哈夫曼树。

(2)参考哈夫曼树,请给出字符A、B、C、D、E、F、G的哈夫曼编码

3.如下图所示无向图,从顶点a开始遍历

(1)请写出一种深度优先搜索遍历的遍历序列

(2)请写出一种深度优先搜索遍历的遍历序列

4.有关键字序列{4,9,15,16,33,46,65,78},请回答以下问题:

(1)画出该序列的二叉比较树;

(2)通过二分查找,查找关键字15,写出需要比较的关键字序列;

(3)通过二分查找,查找关键字56,写出需要比较的关键字序列。

5.已知关键字序列{29,11,75,17,43,39,60},请使用简单选择进行升序排序,并写出每 一趟排序结果。

6.有带权无向图如下所示,构造出该图的最小生成树。

 五、编程题

1.请根据提示,完成下面顺序栈入栈操作算法

3.请根据提示,完成下面直接插入排序的操作算法 //直接插入排序 

4.已知顺序表,其数据元素类型为整型,编写程序实现如下操作:


前言

只是作为应试考试的复习题,本身含金量其实并不高,比较基础,而且重心偏数据结构上

 一.单项选择题

1.以下代码片段的时间复杂度为:

for(int i=0;i<n;i++){
 for(int j=i;j<n;j++){
 doSomeThing();
 }
 }

A.O(1) B.O(n) C.O(n2) D.O(log2 n)

选C

解析:直接看双层循环就是很常规的大O(N^2)了。

2.关于线性表,下列描述错误的是( )。

A.顺序表和链表都是随机存储的结构

B.顺序表不需要存储指针,其存储密度比链表高

C.链表的插入和删除操作比顺序表方便

D.构成线性表的数据元素必须类型相同

选A

解析:A、循序表是随机存取,但链表是顺序存取的(也就是遍历的时候必须按顺序一个一个来),所以A很明显

B、存储密度高那就说明存的东西多;

C、链表插入和删除只需动两个指针就行,而顺序表需要进行很多元素的位移

D、这个就没话说了,不然为什么你定义数组的时候要指定数据类型呢

3.以下链表的优点的是( )。

A.存储密度大

B.扩展方便

C.进行随机访问方便

D.结构简单,实现容易

选B

解析:A、上面那题才说了多存一个指针导致密度不高

C、前面也提到了没办法随机访问的

D、链表的结构实际并不简单,起码你是需要结构体(C)来模拟的

4.网络服务器响应客户端的请求,需要用到以下数据结构中的( )。

A.顺序表

B.栈

C.队列

D.矩阵

选C

解析:这个其实算个常识,队列的用途就是这方面用的多

5.一个栈的入栈序列为{a,b,c,d,e},则栈的出栈序列不可能是( )。

A.a,b,c,d,e

B.d,b,c,a,e

C.a,c,d,b,e

D.e,d,c,b,a

选B

解析:这种题最好的办法是模拟一遍

6.两个字符串相等的条件是( )。

A.两个字符串的长度相等

B.两个字符串都不包含空格

C.两个字符串中所有相同位置的字符相等

D.两个字符串的长度相等并且两个字符串中所有相同位置的字符相等

选D

解析:把四个选项对比一下,你就发现ABC明显是那种条件不足的选项

7.以下不属于特殊矩阵的是( )。

A.对称矩阵

B.三角矩阵

C.对角矩阵

D.稀疏矩阵

选D

解析:实际就是D作为矩阵是没啥特殊减少存储的机制在里面,但是其他有,比如对称矩阵按照对称点存

8.一棵树的度为5,指的是( )。

A.这棵树中结点的度的最大值为5

B.这棵树有5个结点

C.这棵树中有5个叶子结点

D.这棵树中除了叶子结点,每个结点都有5棵子树

选A

解析:定义问题,树的度就是树里面度数最大的节点的度数

9.对一棵完全二叉树,其中编号为7的结点,如果它有右孩子,那它的右孩子的编号为 ( )。

A.3 B.8 C.14 D.15

选D

解析:考的时候一般都会说是完全二叉树,那节点i的左孩子就是2*i,右孩子就是2*i+1

10.线索二叉树中,如果某个结点的rtag为1,那么它的右孩子指针域指向它的( )。

A.双亲结点B.遍历序列中的前驱C.遍历序列中的后继D.右孩子

选C

解析:关于线索二叉树的常规定义,可以去站内的一些大佬的博客看线索二叉树(图解+完整代码)-CSDN博客

那直接看定义的话,那就是

  • ltag==0,指向左孩子;ltag==1,指向前驱结点
  • rtag==0,指向右孩子;rtag==1,指向后继结点

11.一棵二叉树,如果其中度为2的结点数量为9,那么这棵二叉树叶子结点有( )个。

A.7 B.8 C.9 D.10

选D

解析:要理解其实不难,根据二叉树的一个性质:若在任意一棵二叉树中,有n个叶子节点,有n₂个度为2的节点,则必有n₀=n₂+1,最简单就是你自己再画一个二叉树,包简单的

12.一个有n个顶点的无向图,如果它是连通的,那么它至少有( )条边。

A.n/2

B.n-1

C.n

D.n(n-1)/2

选B

解析:还是个定义题,要想连通那就是保证每个节点不是被阻断的就行了。顺带一提,完全二叉树的时候问你多少条边才是D(一开始做错了)

13.若从无向图的任意一个顶点出发进行一次深度优先搜索可以访问图中所有的顶点, 则该图一定是( )图。

A.非连通

B.连通

C.强连通

D.有向

选B

解析:跟前面的的考点是差不多的

14.二分查找要求查找表是( )的。

A.顺序存储的B.已排序的C.顺序存储且已排序的D.都可以

选C

解析:对比四个选项,会发现AB就是缺条件,D直接不管

15.设有15个数据元素构成查找表,采用顺序查找的方式,则平均查找长度为( )。

A.4 B.8 C.9 D.15

选B

解析:查第一个要查1次,查第15个要查15次,那平均就是(1+15)/2=8

16.以下排序方法属于稳定排序的是( )。

A.直接插入排序B.快速排序C.希尔排序D.直接选择排序

选A

解析:因为直接插入排序它足够费时间,所以它稳定

17.如果有8个数据元素进行排序,那么至少需要比较( )次。

A.4 B.6.C.7 D.8

选C

解析:从第一个比到第七个后,第八个不比也知道答案了

18.如果对一个序列进行升序排序,使用直接插入排序方法,在这个序列( )情况下, 比较和移动次数最少。

A.元素按关键字从大到小排列B.元素按关键字从小到大排列 C.完全无序D.基本有序

选B

解析:只要它原本序列就是升序的,那就费时最少

19.图的深度优先遍历是应用( )算法。

A.分治法B.动态规划法C.贪心法D.回溯法

选D

解析:定义题,选其他都不合适的

20.以下使用到贪心算法的是( )。

A.构造网的最小生成树B.AOE网的关键路径 C.网中两个顶点间的最短路径D.快速排序

选A

解析:也是定义题

二.判断题

1.数据的逻辑结构,不仅需要考虑数据元素之间的逻辑关系,还需要考虑它们在计算机 内部的表示。( )

答案:×

解析:死记,因为不一定要考虑它们在计算机内部的表示

2.循环链表中的特点是可以从链表中任意结点开始遍历整个链表。( )

答案:√

解析:这道题其实我觉得是有歧义,但是答案说对(还是存疑),那只能顺从了

3.循环队列有效利用了数据元素出队后留下的存储空间,所以不会造成“溢出”的问题。 ( )

答案:×

解析:当队尾追上队头的时候还是叫溢出的

4.空串的长度为0,并且是任意字符串的子串。( )

答案:√

解析:就是空串的定义

5.广义表并不是一种线性表的特例。( )

答案:√

解析:5.广义表并不是一种线性表的特例。( )

6.二叉树是一种特殊的度为2的树。( )

答案:×

解析:是最多度为2

7.哈夫曼树中不存在度为1的结点。( )

答案:√

解析:定义题

8.无论是有向图还是无向图,所有顶点的度之和都等于图中边的数量的2倍。( )

答案:√

解析:定义题

9.使用二分查找进行查找数据元素,查找次数一定比顺序查找少。( )

答案:×

解析:太绝对了,很难说是正确的

10.快速排序和直接选择排序算法在每一趟排序中都能找到一个元素放在其最终位置上 ( )

答案:√

解析:快排每次找到的标准就是放到最终位置的,而直接排序每次都是排在前一个元素的旁边,后续也不会动了

三.简答题

1.请简述一个完整算法必须具有的要素。

有穷性:算法要求在有限的操作后完成,每个操作所执行的时间是有限性的

确定性:算法要求在任何条件下都只有一条执行路径

可行性:构建算法的操作必须都是可行的

输入:算法的加工对象

输出:算法对输入加工后得到的结果

2.设主串“institute”,请写出其中字符串长度为5的所有子串,并写出他们在主串中的 位置(从1开始)

答案:

位置1:insti

位置2:nstit

位置3:stitu

位置4:titut

位置5:itute

3.一个矩阵A[12][15]以行为主序进行存储,其首元素A[0][0]的物理地址为360,每个 数据元素所占的存储空间为3,求A[6][5]的地址。要求写出计算过程

答案:

在行主序存储中,矩阵元素按行优先的顺序依次存储在内存中。假设矩阵的第 i 行和第 j列元素为 A[i][j]:

  1. 矩阵元素存储的线性地址计算公式

    Address(A[i][j])=BaseAddress+(i×NumberOfColumns+j)×ElementSize

    其中:

    • BaseAddress\text{BaseAddress}BaseAddress 是矩阵首元素 A[0][0] 的地址。
    • i 是元素的行索引。
    • NumberOfColumns 是矩阵的列数。
    • j 是元素的列索引。
    • ElementSize 是每个元素占用的存储空间。
  2. 已知数据

    • BaseAddress=360
    • NumberOfColumns=15
    • i=6
    • j=5
    • ElementSize=3
  3. 将数据代入公式

    Address(A[6][5])=360+(6×15+5)×3
  4. 计算索引乘积和偏移量

    6×15=906          90+5=95                   95×3=285
  5. 计算最终地址

    Address(A[6][5])=360+285=645

四.应用题

1.请写出下图所示的二叉树先序.中序和后序遍历的结果。

答案:

先序:A->B->D->C->E->F->G

中序:B->D->A->E->C->G->F

后序:D->B->E->G->F->C->A

2. 假定用于通信的电文由8个字符A、B、C、D、E、F、G组成,各字母在电文中出现 概率为22%、24%、14%、7%、18%、3%、12%。现在把字符出现概率扩大100倍后, 作为这8个字母对应的权值(22,24,14,7,18,3,12)。请回答以下问题:。

(1)画出以这些权值构成的哈夫曼树。

画的时候看看最后的和是不是等于100(100%)的来纠错

(2)参考哈夫曼树,请给出字符A、B、C、D、E、F、G的哈夫曼编码

答案:A:01 B:10 C:110 D:0001 E:111 F:0000 G:001

3.如下图所示无向图,从顶点a开始遍历

(1)请写出一种深度优先搜索遍历的遍历序列

答案:a、b、e、g、d、f、c

(2)请写出一种深度优先搜索遍历的遍历序列

答案:a、b、c、e、d、g、f

解析:这里注意谁先进队列,那后面跟的就得是和当前元素连接的元素

4.有关键字序列{4,9,15,16,33,46,65,78},请回答以下问题:

(1)画出该序列的二叉比较树;

答案:

 解析:最终结果记得对于每个节点,比它小的在左,大的在右

(2)通过二分查找,查找关键字15,写出需要比较的关键字序列;

答案:参考二叉树,每次比较父节点

16,9,15

(3)通过二分查找,查找关键字56,写出需要比较的关键字序列。

答案:注意这里56并没有出现,但是还是要正常走一遍流程,直到不能比较

16,46,65

5.已知关键字序列{29,11,75,17,43,39,60},请使用简单选择进行升序排序,并写出每 一趟排序结果。

答案:

第一趟:11,29,75,17,43,39,60

第二趟:11,17,75,29,43,39,60

第三趟:11,17,29,75,43,39,60

第四趟:11,17,29,39,43,75,60

第五趟:11,17,29,39,43,75,60

第六趟:11,17,29,39,43,60,75

解析:解题的时候尽量按这种格式来,每次从里面找出最小的,然后排到上一个元素的后面(针对升序排序)

6.有带权无向图如下所示,构造出该图的最小生成树。

 答案:常规的生成树做法就两种,详细点的知识点也可以参考站内博客图论必备算法之一:最小生成树 (易懂至极)_最小生成树算法 只能用于无向图吗?-CSDN博客

 五、编程题

1.请根据提示,完成下面顺序栈入栈操作算法

//顺序栈数据定义
typedefstructSQStack{
 //连续存储空间
ElementTypedata[MAXSIZE];
 //栈顶指针,初始化时为-1
 inttop;
 }SQStack;
 //入栈
intpush(SQStack*stack,ElementTypeelem){
 //判断栈是否为满
if(stack->top>=MAXSIZE-1){
 printf("stackisfull!\n");
 return0;
 }
 //修改栈顶指针
__________________(1);
//放入新元素到栈顶
___________________(2)
 return1;
 }

答案:(1)stack->top++或++stack->top或stack->top=stack->top+1

解析:要注意栈顶指针是先自增还是先赋值,不过这里题目直接给顺序了

(2)stack->data[stack->top]=elem

2.请根据提示,完成下面的循环队列的入队操作算法 


//循环队列出队
#define MAXSIZE 32
 typedefstruct{
 ElementTypedata[MAXSIZE];
 intfront;
 intrear;
 }CircleQueue;
 ElementType*deQueue(CircleQueue*queue){
 ElementType*elem=NULL;
 //判断队列是否为空
if((1) ){ (2分)
 printf("queueisempty!\n");
 return elem;
 }
 //获取队头的数据元素
elem= &queue->data[queue->front];
 //移动队头指针
queue->front=(2) ;(2分)
 returnelem;
 }

答案:

(1)queue->rear==queue->front

解析:判断队列是否为空的操作其实这里我觉得应该写 (queue->rear+1)%MAXSIZE==queue->front才对

(2) (queue->front+1)%MAXSIZE

3.请根据提示,完成下面直接插入排序的操作算法 //直接插入排序 

//直接插入排序
voidinsertSort(ElementType data[],int len){
 int temp=-1;
 for(int i=0;i<len-1;i++){
//记录需要比较和插入的数据元素
(1) ;(2分)
 int j=i;
 //数据元素移动的条件
while(j>=0&&temp<data[j])
 {
 //数据元素向后移动一个位置
data[j+1]=data[j];
 j--;
 }
 //数据元素插入到指定位置
(2) ;(2分)
 }
 }

答案:

(1)temp=data[i+1]

解析:这里就是在寻找要插入的地方,你现在的操作就是一直跟后面的元素比较

(2)data[j+1]=temp

整道题的算法其实逻辑还可以优化,比如循环变量应该从1开始

4.已知顺序表,其数据元素类型为整型,编写程序实现如下操作:

(1)编写插入数据元素的算法;

bool insertElement(SeqList &list, int position, ElementType element) {
    if (position < 1 || position > list.length + 1) {
        std::cout << "Invalid position!" << std::endl;
        return false;
    }
    if (list.length >= MAX_SIZE) {
        std::cout << "List is full!" << std::endl;
        return false;
    }
    for (int i = list.length; i >= position; i--) {
        list.data[i] = list.data[i - 1];
    }
    list.data[position - 1] = element;
    list.length++;
    return true;
}

(2)初始化顺序表,使其初始的数据元素为{15,27,10,16,35,42,21},在主函数中 调用插入算法,在顺序表中第4个数据元素之前插入新元素60,然后打印整个顺序 表。

#include <iostream>
#define MAX_SIZE 100

typedef int ElementType;

struct SeqList {
    ElementType data[MAX_SIZE];
    int length;
};

void initSeqList(SeqList &list) {
    list.length = 0;
}

void printSeqList(const SeqList &list) {
    for (int i = 0; i < list.length; i++) {
        std::cout << list.data[i] << " ";
    }
    std::cout << std::endl;
}

int main() {
    SeqList list;
    initSeqList(list);
    
    // 初始化顺序表
    ElementType initData[] = {15, 27, 10, 16, 35, 42, 21};
    int initSize = sizeof(initData) / sizeof(initData[0]);
    for (int i = 0; i < initSize; i++) {
        list.data[i] = initData[i];
    }
    list.length = initSize;
    
    std::cout << "Initial sequence list: ";
    printSeqList(list);
    
    // 在第4个数据元素之前插入新元素60
    int position = 4;
    ElementType newElement = 60;
    if (insertElement(list, position, newElement)) {
        std::cout << "After inserting 60 at position " << position << ": ";
        printSeqList(list);
    } else {
        std::cout << "Insertion failed." << std::endl;
    }
    
    return 0;
}

最后想说的是手敲代码和手写代码还真是不能比呀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

比烧腊饭还烧

谢谢谢谢谢谢谢谢谢谢谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值