数据结构期末自测题


数据结构自测题

1.简述数据结构的概念。(4个点)
数据结构是计算机存储,组织数据的方式,是指相互之间存在一种或多种特定关系的数据的集合。
存储:值存储在数据中,值按照性质归类于数据项,按照个体归类于数据元素,数据项与数据元素的特定组合构成数据结构,整体统称为数据对象。

2.G={<k1,k3>,<k1,k8>,<k2,k3>,<k2,k4>,<k2,k5>,<k3,k9>,<k5,k6>,<k8,k9>,<k9,k7>,<k4,k7>,<k4,k6>}, <a,b>表示一条边的起点与终点,求该图的开始起点与结束终点。
画图求解
开始起点:1, 2
结束终点:6, 7

3.简述空间复杂度概念。
程序在运行过程中临时变量占用空间的大小。

4.根据表格整理出链表数据的正确顺序。
image

Ren->Zhi->Chu->Xing->Ben->Shan

5.说明循环单链表与单链表,循环双链表与双链表的区别。
单链表的尾结点没有后继结点(后继结点为空),头结点没有前驱节点,而循环单链表尾结点的后继结点为头结点(这里指实际头结点),头结点的前驱节点为尾结点; 双链表同单链表。

6.带虚拟头结点的单链表和不带虚拟头结点的单链表的优势体现在哪里?如何区分头结点与虚拟头结点?
和不带虚拟头结点的单链表相比,带虚拟头结点的单链表不仅统一了第一个结点及其后继结点的处理过程,还统一了空表和非空表的处理过程。自己要学会结合语境判断,题目中说的头结点是虚拟头结点还是实际的头结点。
[203. 移除链表元素]
https://leetcode-cn.com/problems/remove-linked-list-elements/

7.对单链表,哪边是头,哪边是尾?插入时,(A)与(B)能否交换,为什么?
q = ListNode(13)
q.next = head.next ---- (A)
head.next = q ---- (B)
(注意:这里由于有时候会有人弄不清楚头结点与虚拟头结点的区别,所以经常会取head这样**的名字,考生自己要清楚,别被带到沟里去了)
对于单链表,最前面的元素就是头结点(如果这个元素在之后不被替代),最后的元素就是尾结点。(A)与(B)不能交换,若两者交换,head.next已经更新为q, q就无法定位到原来头结点所在的位置上了。
[61. 旋转链表]
https://leetcode-cn.com/problems/rotate-list/

8.叙述栈顶指针, (虚拟)队头指针,队尾指针的概念。
注意:为保证队列元素操作的一致性,类似于虚拟头指针的概念,建立虚拟队尾指针,指向队尾元素的下一个元素
栈顶指针指向栈最顶部的元素,队头指针指向队列中先插入的元素,队尾指针指向最后一个插入元素的后面一个元素。

9.“秋江楚雁宿沙洲,雁宿沙洲浅水流。流水浅洲沙宿雁,洲沙宿雁楚江秋。”请使用栈的基本操作来判断一个单词是否为回文单词。(只允许使用一个栈)
[剑指 Offer II 018. 有效的回文]
https://leetcode-cn.com/problems/XltzEq/
[234. 回文链表]
https://leetcode-cn.com/problems/palindrome-linked-list/
字符串中每个字符逐一入栈,逐一出栈,与原字符串比较

  1. 简述如何检验括号有效性。
    [20. 有效的括号]
    https://leetcode-cn.com/problems/valid-parentheses/
    遇见‘(’则将‘)’入栈,遇见‘)’将栈顶元素与之比较。

  2. 在玩游戏的时候,一般会标记重生点,角色快死了可以回到重生点复活继续游戏,请从数据结构角度简单分析其基本原理。
    重生点用栈存储了玩家在到达重生点时的信息,复活时,将这些信息出栈覆盖濒死玩家的数据信息。

12.如何解决队列假溢出问题?如何在循环队列中区分队空与队满?
[622. 设计循环队列]
https://leetcode-cn.com/problems/design-circular-queue/
解决队列假溢出的方法有两种,一种是只用一个队尾指针,将元素始终存储在0-(队尾指针-1)的范围之内;另外一种是建立循环队列。在循环队列中,区分队空与堆满也有两种方法,一种是在结构体中加入tag进行标识,另外一种是预留出一个空位,具体操作是,K个元素,存储在0-K-1这K个位置当中,设置队列长度为K+1,当rear==head时为队空,当(head-rear)%(K+1) == 1时为队满。(head-rear)%(K+1)的值的变化:0, K,K-1,...2,[1]

  1. 请分别使用循环顺序队列的基本操作和递归来计算某个月的斐波那契的兔子总数。两种做法在时间复杂度与空间复杂度上有什么不同?这样的做法在n>=47时应当注意什么?
    [剑指 Offer 10- I. 斐波那契数列]
    https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/comments/
    [斐波那契数列两种算法的时间复杂度]
    https://www.cnblogs.com/abyss1114/p/7272657.html
    时间复杂度上,递归的方法为2的n次幂,非递归为n,空间复杂度上,递归为n,非递归为1, 当n>=47时,最好在每一步除以一个极限数,防止结果超出整数int的数据范围。

14.如何用递归解决汉诺塔问题?如何解释程序的运行过程?
[面试题 08.06. 汉诺塔问题]
https://leetcode-cn.com/problems/hanota-lcci/
先把1: A->B,再n-1:A->C, 1:B->C

  1. 如何用栈实现队列,又如何用队列实现栈(角色互换法)?基于此,请说说你是如何认识栈与队列的时间本质的?
    两个栈,一个入,一个出,出的空找入要,倒两下,正过来了
    两个队列,强行实现,注意交换身份
    栈是时间的倒放,队列是时间的顺序执行

  2. 简单字符串匹配算法的劣势体现在哪儿?如何改进?改进后的kmp算法的next数组是如何求的?求出next数组后又怎么办?如何求next数组!!!!
    因为 KMP 利用已匹配部分中相同的「前缀」和「后缀」来加速下一次的匹配。
    因为 KMP 的原串指针不会进行回溯(没有朴素匹配中回到下一个「发起点」的过程)。

第一点很直观,也很好理解。
我们可以把重点放在第二点上,原串不回溯至「发起点」意味着什么?
其实是意味着:随着匹配过程的进行,原串指针的不断右移,我们本质上是在不断地在否决一些「不可能」的方案。
当我们的原串指针从 i 位置后移到 j 位置,不仅仅代表着「原串」下标范围为 [i,j)[i,j) 的字符与「匹配串」匹配或者不匹配,更是在否决那些以「原串」下标范围为 [i,j)[i,j) 为「匹配发起点」的子集。
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

KMP个人感悟:就像打游戏,打的赢就打,打不赢就跑,免得每次打死了要回原地复活

[28. 实现 strStr()]
https://leetcode-cn.com/problems/implement-strstr/
参考题解:
https://leetcode-cn.com/problems/implement-strstr/solution/shua-chuan-lc-shuang-bai-po-su-jie-fa-km-tb86/

子串为aaabab, 求next数组 012010

17.在用数组存储矩阵的时候,如何避免元素重复存储(对称矩阵->三角矩阵),如何处理零元素大量规律存在(三角矩阵),以及大量不规律存在(稀疏矩阵(三元组表法,十字链表法))的问题?
利用公式来将二维数组压缩到一维的层面上去,大量不规则存在的矩阵,可采用三元组表法,十字链表法存储之。

18.应当如何定义叶子结点?由此看出树与图具有怎样的关系?
(结点的度,叶子结点,分支结点,树的度)
结点的度为0的结点就是叶子结点,其中,结点的度是指树中结点的出度,叶子结点即结点的度为0的结点,分支结点即结点的度不为0的结点,树的度是指树内所有结点度的最大值。
由此看出,树不过是一种特殊的图结构,适用于图的方法,一样适用于树(如DFS,BFS)

19.如何用非技术人员也能听懂的语言描述树的结构?(联系家系图)
(孩子结点,双亲结点,兄弟结点,祖先结点,子孙结点,结点的层次(类似辈分),堂兄弟结点(有病吧),树的深度,有序树,无序树)
自己脑子里想一下

20.如何用树的性质进行数学运算?(难/麻烦)
(1)树的结点数目=所有结点的度的总和+1
(2)度为k的树第i层最多有k的(i-1)次方个结点
(3)深度为h的k叉树最多有(k的h次方-1)/k-1
(4)具有n个结点的k叉树的最小深度为logk[n(k-1)+1]取整

21.请先回答问题先序遍历之先是什么先?先序遍历,后序遍历,层次遍历与前序遍历,中序遍历,后序遍历,层次遍历的关系是什么?再写出下面这个树的先序遍历,后序遍历,层次遍历的节点顺序。(不要背,递归看即可)
先序遍历先的是树根,先序遍历,后序遍历,层次遍历指的是树的遍历,前序遍历,中序遍历,后序遍历,层次遍历指的是二叉树的遍历,

image

先序遍历:A B E K L F C G D H M I J
后序遍历:K L E F B G C M H I J D A
层次遍历:A B C D E F G H I J K L M
树的定义与树的遍历可以说是完全统一在递归之下的。

22.简述树与二叉树的区别
恋拽FHB 2017-04-24 23:22树可以为空,叫空树(严蔚敏《数据结构(C语言版)》第118页明确定义:树是n(n>=0)个结点的有限集)。他们之间的差别主要在于实现方式的不同。二叉树是二叉链表(有左右子树的指针),树通常是兄弟孩子链表(有孩子指针,兄弟指针,两个指针)。二叉树区分左右,非有序树不区分左右。

23.满二叉树与完全二叉树的区别是什么?(满二叉树是完全二叉树的一种特例)
满二叉树最下面一层排满,完全二叉树只要没有不排满的就行。

24.试证明:对任何非空二叉树 T,若其叶结点个数为 n0,度数为 2 的结点个数为 n2,则n0 = n2 + 1
结点数 = n0 + n1 + n2 = 所有结点的度数 + 1 = n1 + 2*n2 + 1
n0 = n2 + 1

25.试比较二叉树的顺序存储与链式存储,说明其在不同应用场景下的优缺点
二叉树顺序存储操作简单,但增删难度大,且对非完全二叉树而言,比较浪费空间。

26.请先回答问题前序遍历之前是什么前?再写出下面这个树的前序遍历,中序遍历,后序遍历,层次遍历的节点顺序。(不要背,递归看即可)
image

前序遍历之前是树根在前,
前序遍历:ABCDEFGHK
中序遍历:BDCAEHGKF
后序遍历:DCBHKGFEA
层次遍历:ABECFDGHK

27.请用python写出二叉树的先序遍历,中序遍历,后序遍历的递归算法。
[144. 二叉树的前序遍历]
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/submissions/

点击查看代码
def preorder(self,root:TreeNode):
        if(root==None):
            return
        self.ls.append(root.val)
        self.preorder(root.left)
        self.preorder(root.right)

[94. 二叉树的中序遍历]
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

点击查看代码
def inorder(self,root:TreeNode):
	if(root==None):
    	return
    self.inorder(root.left)
    self.ls.append(root.val)
    self.inorder(root.right)

[145. 二叉树的后序遍历]
https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

点击查看代码
def postorder(self,root:TreeNode):
        if(root==None):
            return
        self.postorder(root.left)
        self.postorder(root.right)
        self.ls.append(root.val)

28.(必考&&重要2)请用python写出二叉树的先序遍历,中序遍历,后序遍历(SL),层次遍历的非递归算法。
[144. 二叉树的前序遍历]
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/submissions/

点击查看代码
def preorderTraversal(self, root: TreeNode) -> List[int]:
        res, stack = [], []
        node = root
        while(stack or node):
            while(node):
                res.append(node.val)
                stack.append(node)
                node = node.left
            node = stack[-1]
            stack.pop()
            node = node.right
        return res

[94. 二叉树的中序遍历]
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

点击查看代码
def inorderTraversal(self, root: TreeNode) -> List[int]:
        res, stack = [], []
        node = root
        while(stack or node):
            while(node):
                stack.append(node)
                node = node.left
            node = stack[-1]
            stack.pop()
            res.append(node.val)
            node = node.right
        return res

[145. 二叉树的后序遍历](SL)
https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

点击查看代码
def postorderTraversal(self, root: TreeNode) -> List[int]:
        res, stack = [], []
        node, p = root, None
        while(stack or node):
            while(node):
                stack.append(node)
                node = node.left
            node = stack[-1]
            if(node.right==None or node.right==p):
                res.append(node.val)
                stack.pop()
                p = node
                node = None
            else:
                node = node.right
        return res

[102. 二叉树的层序遍历]
https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

点击查看代码
def levelOrder(self, root: TreeNode) -> List[List[int]]:
        res, queue = [], []
        if(root==None):
            return res
        queue.append(root)
        while(queue):
            ans = []
            sz = len(queue)
            while(sz>0):
                t = queue[0]
                ans.append(t.val)
                if(t.left):
                    queue.append(t.left)
                if(t.right):
                    queue.append(t.right)
                queue.pop(0)
                sz = sz-1
            res.append(ans)
        return res

29.请用python写出N叉树的先序遍历,后序遍历,层次遍历算法。

30.能否由先根遍历与中根遍历唯一的确定一棵树?试说明其确定过程,后根遍历与中根遍历呢?先根遍历与后根遍历呢?如果不能请举出反例。能否说后根遍历是先根遍历的倒序?
image

31.对一棵二叉树进行遍历时,我们以二叉链表作为存储结构,此时只能找到除根结点以外的任一结点的左、右孩子,而不能直接访问结点在遍历时所得的序列中的先驱和后继信息。如何解决这一问题呢?
[线索化的实质是当二叉树中某一结点不存在左孩子或右孩子时,将其LeftChild域或RightChild域中存入该结点的直接先驱或直接后继。通常我们在遍历二叉树时才能实现对其线索化。]

32.如何利用栈实现表达式的运算?
[剑指 Offer II 036. 后缀表达式]
https://leetcode-cn.com/problems/8Zf90G/

33.请简要说明树,二叉树,森林之间的转换过程

34.哈夫曼树的每个叶子结点的路径为什么是唯一的?如何计算哈夫曼树的路径长度?如何构建最优哈夫曼树?
https://baike.baidu.com/item/哈夫曼树/2305769?fr=aladdin
https://haokan.baidu.com/v?pd=wisenatural&vid=7342058971484704343
因为树的叶子结点的入读均为1,出度为0,所以路径就唯一确定

35.请列出下图的深度优先搜索与广度优先搜索的正确顺序,如何更好的记录已访问结点?
image

深度优先搜索:01374256
广度优先搜索:01234567

36.请简单回忆kruskal,prim,Dijkstra,flyord算法,AOV网与AOE网。
Kruskal:
image

按权值由小到大取每一条边,若构成回路就舍弃。

Prim:
image

用到已知集合最近的点更新未知集合每一个点的距离数组

Dijkstra:
image

用到源点距离最近的点更新未知集合每一个点的距离数组

Flyord
image

37.简述顺序查找中监察哨的作用。
防止比较时数组下标超出边界,同时充当临时变量的作用

38.二叉查找树中,若待删除的结点既有左子树,也有右子树,应当如何处理?
用二叉查找树中序遍历的前一个结点/后一个结点来交换之,再删除交换的结点

39.请列举两种构造哈希表的常用方法。
开放寻址法与拉链法

40.怎样的排序算法是稳定的排序算法?哪些排序算法是稳定的?哪些不是?
如果待排序的记录序列中存在多个排序码相同的记录,经过排序后,这些具有相同排序码的记录之间的相对次序保持不变,则我们认为该排序方法是稳定的;若具有相同排序码的记录之间的相对次序发生了变化,则认为该排序方法是不稳定的。
插入排序,冒泡排序与归并排序稳定,其余均不稳定(学过的排序算法中)

41.3)插入排序用移动法还是交换法?(要是非要你填移动法的代码怎么办?)
移动法,本质还是移动法
image

42.请问二分插入排序的时间复杂度是多少?学过的算法里面,有哪些平均时间复杂度不是O(n^2)? 哪些最坏时间复杂度不是O(n^2)?哪些排序是稳定的?(插入,冒泡与归并)
二分插入排序的时间复杂度仍然是O(n2)的,快排,归并,堆排序,希尔排序不是O(n2),其余均是O(n2), 插入冒泡与归并是稳定的

43.如何实现堆排序算法?
image
image

大的讲,先构造堆,再逐一缩小堆的规模,小的讲,子节点选大的交换


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM