第一章:绪论-灰灰考研汇总
1.数据:数据是信息的载体,是描述客观事物属性的数、字符以及所有能输入到计算机中并 被计算机程序处理的符号的集合。
2.数据元素:数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。
3.数据项:数据项是数据结构中讨论的最小单位。 是数据记录中基本的,不可分的数据单 位。
4.数据对象:数据对象是性质相同的数据元素的集合,是数据的一个子 集。
5.数据结构:数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。数据结构 包括3个方面的内容:逻辑结构、存储结构和对数据的运算。
6.数据的逻辑结构: 数据的逻辑结构是对数据之间关系的描述,它与数据的存储结构无关, 同一种逻辑结构可以有多种存储结构。归纳起来数据的逻辑结构主要有四大类:集合、线性 结构、树形结构、图状结构或网状结构。
7.数据的存储结构: 数据的物理结构又称为存储结构,是数据的逻辑结构在计算机中的 表示(又称映像)。它包括数据元素的表示和关系的表示。当数据元素是由若干数据项构 成的时候,数据项的表示称为数据域;比如一个链表节点,节点包含值域和指针域,这 里节点可以看做一个数据元素,其中的值域和指针域都是这个数据元素的数据域。主要
有顺序存储、链式存储、索引存储、散列存储。
8.数据的运算:施加在数据上的运算包括运算的定义和实现。定义是针对逻辑结构,指出运 算的功能。实现是针对存储结构的,指出运算的具体操作步骤。
9.算法:对特定问题求解步骤的一种描述,是指令的有限序列,其中每一条指令表示一个或 多个操作。有5个重要特性(有穷性、确定性、可行性、输入、输出)。
(1)有穷性:一个算法必须保证执行有限步之后结束。
(2)确定性: 算法的每一步骤必须有确定的定义。
(3)输入: 一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入 是指算法本身确定了初始条件。
(4)输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出 的算法是毫无意义的。
(5)可行性: 算法中的所有操作都必须可以通过已经实现的基本操作进行运算,并在 有限次内实现,而且人们用笔和纸做有限次运算后也可完成。
10.算法设计的要求:正确性、可读性、健壮性、效率与低存储量需求。
(1)正确性: 要求算法能够正确地执行预先规定的功能和性能要求。这是重要也是基本的标准。
(2)可读性: 要求算法易于人的理解。
( 3 ) 健 壮 性 :要求算法有很好的容错性,能够对不合理的数据进行检查。
(4)高效率与低存储量需求:算法的效率主要是指算法的执行时间。对于同一个问题 如果有多种算法可以求解,执行时间短的算法效率高。算法的存储量指的 是算法执行过程中所需要的大存储空间。高效率和低存储量这两者都与问题的规模有关。
11.时间复杂度:算法的时间复杂度,也就是算法的时间量度,记作:T(n)=0(f(n))。 它表 示随问题规模n 的增大,算法执行时间的增长率和f(n) 的增长率相同,称作算法的渐近时 间复杂度,简称为时间复杂度。其中f(n) 是问题规模n 的某个函数。
12.空间复杂度:算法的空间复杂度指算法在运行时所需存储空间的度量,主要考虑在算法
运行过程中临时占用的存储空间的大小(和时间复杂度一样,以数量级的形式给出)。
13. 就地算法:就 地 (In-place) 算法指的是直接修改输入数据而不是将输入数据复制一份 处理之后再覆盖回去,这个名称和时间复杂度没什么关系,纯粹是指算法处理数据的方式。 比如一个冒泡排序就是就地算法。
第二章:线性表-灰灰考研汇总
1.线性表的逻辑特性:线性表中数据元素之间的关系是一对一的关系,即除了第一个和最 后一个数据元素之外,其它数据元素都是首尾相接的,每个元素最多只能有一个前驱和一个 后继。
2.线性表的存储结构:线性表的存储结构有顺序存储结构和链式存储结构两种,前者称为 顺序表,后者称为链表,其中顺序表是保存在一片连续的存储空间中的,而链表则是通过指 针来与其他数据进行联系,每个数据元素除了存储元素本身信息,还要存储与其他数据之间 的关系。
3.单链表:包含数据域和指针域,指针域有一个指针,指针指向下一节点的地址。
4.双链表:包含数据域和指针域,指针域有两个指针,一个指针指向下一节点的地址,另一 个指针指向上一节点的地址。
5.循环单链表:在单链表基础上,最后一个节点的后继指向第一个节点
6.循环双链表:在双链表基础上,最后一个节点的后继指向第一个节点,第一个节点的前驱 指向最后一个节点。
7.静态链表:借助数组来描述线性表的链式存储结构,节点也有数据域和指针域。但指针是 节点的相对地址(数组下标,需要预先分配连续的内存空间。
第三章:栈与队列-灰灰考研汇总
1.栈:栈是一个特殊的线性表,它在操作上有一些特殊的要求和限制:栈的元素必须“后进 先出”,栈的操作只能在这个线性表的表尾进行。
2.队列:队列是一个特殊的线性表,它在操作上有一些特殊的要求和限制:队列的元素必须 “先进先出”,队列的入队操作只能在这个线性表的一端进行,出队操作只能在这个线性表 的另一端进行。进行删除操作的一端称为队头,进行插入操作的一端称为队尾。
3.假溢出:系统作为队列用的存储区还没有满,但队列却发生了溢出,我们把这种现象称为”假溢出”。
解决办法:
一是将队列元素向前“平移”(占用0rear-front-1); 二是将队列看成首尾相连,即循环队列(0..m-1)。
另一种解法是“设标记”方法,如设标记tag,tag 等于0情况下,若删除时导致front=rear 为队空;tag=1 情况下,若因插入导致front=rear 则为队满。
4.循环队列:为了克服顺序队列中假溢出,通常将一维数组Queue[0]到 Queue [MAXSIZE-1] 看成是一个首尾相连接的圆环,即Queue[0]与 Queue [MAXSIZE -1]相连接在一起,将这样 形式的队列成为循环队列。
5.递归函数:对于某一函数f(x), 其定义域是集合A, 若对于A 集合中的某一个值X0,其函数值f(x0)由 f(f(x0))决定,那么就称f(x)为递归函数。
第四章:串-灰灰考研汇总
1.串 :由零个或者多个字符组成的有限序列。串中任意个连续的字符组成的子序列称为该串 的子串。字符在序列中的序号为该字符的位置。
2.串的存储方式:可大致分为三种,定长顺序存储方式、 动态分配的堆分配存储方式以及 链式存储方式。所谓堆,即为一块内存。当程序运行时,系统自动为程序分配一块内存,这 块内存是空的。每当使用malloc 或 new 函数的时候,新声明的变量就都会被存入这片内存 中。使用完毕后,若不及时free 或 delete 之前声明的变量,堆中刚占用的内存就不会释放, 即内存泄露问题。总而言之,串的堆存储就是根据需要动态分配字符串的存储空间。
3.模式匹配:模式匹配是数据结构中字符串的一种基本运算。其是求第一个字符串(模式串) 在第二个字符串(主串)中的位置。
4.KMP: Knuth-Morris-Pratt 算 法 ( 简 称KMP), 是 由D.E.Knuth 、J.H.Morris 和 V.R.Pratt 共同提出的一个改进算法,消除了朴素的模式匹配算法中回溯问题,完成串的模式匹配。
5.BM: BM算法是一种精确字符串匹配算法(区别于模糊匹配)。采用从右向左比较的方法, 同时应用到了两种启发式规则,即坏字符规则和好后缀规则,来决定向右跳跃的距离。
第五章:树与二叉树-灰灰考研汇
1.树的定义:包 含n(n>0) 个节点的有穷集合。
(1)集合中的每一个元素都称为一个节点(Node)
(2)有一个特殊的节点称为根节点(Baot)
(3)根节点之外的节点元素被分为 m(m>=0) 个互不相交的集合,其中每一个集合本身也是一颗树,称为根节点的子树。
2.树的存储结构: 双亲表示法,孩子表示法,孩子兄弟表示法。
3.树的节点:包括一个数据元素以及若干指向其子树的分支。节点拥有的子树称为节点的度。 度为0的节点称为叶子或终端节点。树的度是树内个节点的度的最大值。节点的子树的根称 为该节点的孩 子 ,相应的该节点为孩子的双亲。同一个双亲的孩子之间互称兄弟。节点的祖 先是从根到该节点的所经分支上的所有节点。反之,以某节点为根的子树中任一节点都称为 该节点的子孙。
4.节点的层次:从树根开始定义,根节点为第1层,它的子节点为第2层,以此类推。 5.树的高度或深度: 树中节点的最大层数
6.有序树和无序树:树中节点的子树从左到右是有次序的,不能交换,叫做有序树。反之为 无序树。
7.二叉树:是另一种树形结构,每个节点至多有两棵子树,并且,二叉树的子树有左右之分, 其次序不能任意颠倒。性质1:二叉树第i 层上的节点数目最多2i-1(i≥1)。 性质2:深度为k 的二叉树至多有2k-1个节(k≥1)。性 质 3 : 包 含n 个节点的二叉树的高度至少为[Jog:(N+1)| 或者[]og:MJ+1性质4:在任意一棵二叉树中,若终端节点的个数为n0, 度为2的节点数为n2, 则 n0=n2+1。
8. 满二叉树:一 棵高度为h, 并且含有2⁸-1个节点的二叉树称为满二叉树。即每层都有最多的节点,叶子集中在二叉树的最下一层且除叶子之外的每个节点度为2.
9.完全二叉树:若设二叉树的深度为 h, 除 第 h 层外,其它各层(1~h-1) 的节点数都达 到最大个数,第 h 层所有的节点都连续集中在最左边,这就是完全二叉树。
11.森林:m(m>=0) 棵互不相交的树的集合。
12.哈夫曼树:在 含 有N 个带权叶子节点的二叉树中,其中带权路径长度(WPL) 最小的二叉 树称为哈夫曼树或最优二叉树。
13.哈夫曼编码:一种广泛应用而且非常有效的数据压缩编码。
14.路径和路径长度:树中两个节点之间的路径是由这两个节点之间所经过的节点序列构成 的。路径长度是路径上经过的边的个数。
15.树的路径长度:树根到每一个节点的路径长度之和
16.树的带权路径长度 (WPL):树中所有叶子节点的带权路径长度之和。
17.二叉树的遍历:指按某条搜索路径访问树中的每个节点,使得每个节点均被访问一次且 仅被访问一次。
18.树的先根遍历:若树非空,则先访问根节点,再按从左到右的顺序遍历根节点的每一颗 子树。其访问顺序与这棵树对应的二叉树的线序遍历顺序相同。
19.树的后根遍历:若树非空,则按从左到右的顺序遍历根节点的每一棵子树,之后再访问 根节点。其访问顺序与其对应的二叉树的中序遍历相同。
20.先序遍历森林:若森林非空,则按如下规则遍历:
· 访问森林第一棵树的根节点
· 先序遍历第一棵树中根节点的子树森林
· 先序遍历除去第一棵树之后剩余的树构成的森林
- 中序遍历森林:若森林非空,则按如下规则进行遍历:
· 中序遍历森林中第一棵树的根节点的子树森林
· 访问第一棵树的根节点
· 中序遍历除去第一棵树之后剩余的树构成的森林
22.线索二叉树: 按照某种遍所方式对二叉树进行遍历,可以把二叉树中所有节点排序为一 个线性序列。在该序列中,除第一个节点外每个节点有且仅有一个直接前驱节点;除最后一 个节点外每一个节点有且仅有一个直接后继节点。这些指向直接前驱节点和指向直接后续节 点的指针被称为线索(Thread), 加了线索的二叉树称为线索二叉树。
23. 决策树:决 策 树(Decision Tree) 是在已知各种情况发生概率的基础上,通过构成决策 树来求净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法, 是直观运用概率分析的一种图解法。由于这种决策分支画成图形很像一棵树的枝干,故称决 策树。在机器学习中,决策树是一个预测模型,他代表的是对象属性与对象值之间的一种映 射关系。Entropy = 系统的凌乱程度,使用算法ID3,C4.5和 C5.0生成树算法使用熵。这 一度量是基于信息学理论中熵的概念。决策树是一种树形结构,其中每个内部节点表示一个属性上的测试,每个分支代表一个 测试输出,每个叶节点代表一种类别。分类树(决策树)是一种十分常用的分类方法。他是一种监管学习,所谓监管学习就 是给定一堆样本,每个样本都有一组属性和一个类别,这些类别是事先确定的,那么通过学 习得到一个分类器,这个分类器能够对新出现的对象给出正确的分类。这样的机器学习就被 称之为监督学习。
24 . 随机森林: 指的是利用多棵树对样本进行训练并预测的一种分类器。
第六章:图-灰灰考研汇总
1. 图:由非空顶点集V 和边集E 组成,记作G=(V,E)。
2.图的存储结构:邻接矩阵、邻接表、十字链表、邻接多重表、边集数组。
3.有向图:E 为有向边的有限集合时,图G 为有向图
4.无向图:E 为无向边的有限集合时,图G为无向图
5.简单图:不存在重复边,不存在顶点到自身的边称图G为简单图。与多重图相对
6.完全图:在无向图中,若任意两个顶点之间都存在边,则称该图为无向完全图。具有 n*(n-1)/2 条边。有向图中,若任意两个顶点之间存在方向相反的两条弧,称为有向完全图, 含有n(n-1) 条有向边。
7.子图:如果一个图G2的所在顶点和边都是另一个图G1 的子集,则称G2是 G1的子图, 只有顶点和边的集合都是子集,才称为子图,也就是说若顶点集合是子集,而边集合不是子 集,不能称为子图。
8.连通:若从顶点v 到顶点w 存在路径,则v 和 w 是连通的。若图G中任意两个顶点都是连 通的,则称图G 为连通图,否则为非连通图。
9.连通分量:无向图中的极大连通子图称为连通分量。
10.强连通图:在有向图中,若从V到顶点W和从顶点W到顶点V都存在路径,则称两个顶 点是强连通的,若图中任一对顶点都是强连通的,则称为强连通图。
11.强连通分量:有向图中的极大强连通子图称为有向图的强连通分量。
12.生成树和生成森林:连通图的生成树是包含图中所有顶点的一个极小连通子图。若顶点 为n 则含有n-1条边。非连通图中,连通分量的生成树构成生成森林
13.最小生成树:一个带权连通无向图的生成树中边的权值之和最小的那个叫做此图的最小 生成树。
14.路径、路径长度和回路:顶 点V 到顶点Q之间的一条路径是指之间的一个顶点序列。路 径的长度是路径上边的数目。第一个顶点和最后一个顶点相同的路径称为回路或环。
15.简单路径:若一条路径上顶点不重复出现,则称这个路径为简单路径。
16.简单回路:若路径上第一个顶点和最后一个顶点相同,称为回路,或环,除了第一个顶 点和最后一个顶点相同,其余各顶点都不重复出现的回路称为简单回路。
17.最短路径:带权图中,从一个顶点VO到另一个顶点V1的一条路径上所经过边的权值之 和定义为该路径的带权路径长度,其中最短的那条称作最短路径。此路径的长度称为从 v 到u 的距离。
18.图的遍历:从图中某一顶点出发,按照某种搜索方法沿着图中的边对图中所有顶点访问 一次且仅访问一次。
19.深度优先搜索:类似于树的先序遍历,假设从图中某顶点V出发,在访问了V之后一次 从V的未被访问的邻接点出发做深度优先遍历,直到图中所有和V有路径相同的顶点都被访 问到。若图中还有顶点未访问,则另选图中一个未曾被访问的顶点作为起始点,重复上述过 程,直至图中所有顶点都被访问。
20.广度优先搜索:类似于树的层次遍历,从顶点v 出发,访问了V之后依次访问v 的各个 未被访问过的邻接顶点。再依次访问它们的邻接点,并使先被访问的顶点的的邻接点先于后 访问的顶点的邻接点。直到图中所有已被访问顶点的邻接点都被访问到。如果图中还有顶点 未被访问,则另选一个未被访问的顶点作为起始点,重复上述过程,直到图中所有顶点都被 访问。
21.AOV 网 ,用有向无环图表示一个工程,顶点表示活动,有向边<Vi,Vj> 表示Vi 必须先于 Vj进行的关系。则称为AOV网。
22.AOE 网 ,在带权有向图中,以顶点表示事件,有向边表示活动,边上的权值表示完成该 活动的开销(如时间),则称这个网络为A0E网。
23.关键路径:在 A0E 网中,路径长度最长的路径叫做关键路径,关键路径上的所有活动都 是关键活动。
24.拓扑排序: 将有向图中的顶点以线性方式进行排序,通过偏序得到图的全序。 即对于任 何连接自顶点u 到顶点v 的有向边<u,v>, 在最后的排序结果中,顶点u 总是在顶点v 的前 面。
第七章:排序-灰灰考研汇总
1.排 序 :重新排列表中的元素,使表中的元素满足按关键字递增或递减的过程。
2.算法的稳定性:假 设Ri=Rj, 且在排序之前Ri领先于Rj, 若在排序后的序列中Ri 仍然领 先于Rj, 则称所用的排序算法是稳定的,反之则称所用的算法是不稳定的。
3.内部排序:排序期间元素全部存放在内存中的排序;外部排序是指在排序期间元素无法全 部同时存放在内存中必须在排序的过程中根据要求不断的在内外存之间移动的排序。
4.监视哨:临时存储和判断数组边界。
5.插入排序:每次将一个待排序的记录,按关键字大小插入到前面已经排好序的子序列中, 直至全部记录插入完成。
6.希尔排序:又称缩小增量排序,先将整个记录序列分割成若干子序列分别进行直接插入排 序,待整个序列中记录基本有序时,再对全体进行一次直接插入排序。
7.冒泡排序:从前往后(或从后往前)两两比较相邻元素的值,若为逆序则交换,知道序列 比较完,既完成一趟冒泡排序。这一趟确定的最小元素不再参与比较,重复上述过程直到一 趟排序没有记录交换。
8.快速排序:通过一趟排序将待排记录分司成独立两部分,其中一部分的关键字均比另一部 分小,分别对两部分再进行快速排序直至整个序列有序
9.选择排序:每一趟在未排序的记录中选择最小的记录作为有序序列部分的下一个记录。
10.归并排序:将两个或两个以上的有序表组合成一个新的有序表。二路归并排序的核心操 作是将一维数组中前后相邻的两个有序序列归并为一个有序序列。
11.基数排序:采用多关键字排序思想,借助“分配/收集”两种操作对逻辑关键字进行排序。 12 . 堆排序:一种树形选择排序方法。在排序过程中把L[1...M]堪称一棵完全二叉树的顺序。存储结构,利用完全二叉树中双亲和孩子之间的关系,在当前无序区选择最大或最小的元素。
13.堆 :堆常用来实现优先队列,在这种队列中,待删除的元素为优先级最高(最低)的那 个。在任何时候,任意优先元素都是可以插入到队列中去的,是计算机科学中一类特殊的数 据结构的统称。【注意与栈的区别】
14 . 桶排序:工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再 使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归 纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(0[n)]。但 桶排序并不是比较排序,他不受到0(n log re) 下限的影响。
第八章:查找-灰灰考研汇总
- 查找:在数据集合中寻找满足某种条件的数据元素的过程称为查找。 2.查 找 表 (查找结构):用于查找的数据集合称为查找表。
3.静态查找表:如果一个查找表的操作仅涉及查询某个特定的数据元素是否在查找表中和检索满足条件的某个特定的数据元素的各种属性,则称为静态查找表。
4.动态查找表: 需要动态的插入或删除的查找表称为动态查找表。
5.关键字:数据元素中唯一标识该元素的某个数据项的值,使用基于关键字的查找,查找结 果应该是唯一的。
6. 平均查找长度 (ASL): 在查找的过程中, 一次查找的长度指需要比较的关键字次数,而平 均查找长度则是所有查找过程中进行关键字的比较次数的平均值。
7.折半查找:仅适用于有序的顺序表。将给定的值key 与表中间位置元素的关键字比较,相等则查找成功返回位置。若不等则缩小查找范围,重复查找直到找到或者确定表中没有需查找的元素。
8.二叉排序树:一棵二叉排序树或是空二叉树或是具有以下性质的二叉树:左子树上所有关 键字均小于根节点的关键字,右子树所有节点关键字大于根节点的关键字。左子树和右子树 又各是一棵二叉排序树。
9.平衡二叉树:树上任一节点的左子树和右子树的深度之差不过1. 10.平衡因子:该节点的左子树深度减去它的右子树深度。
11.判定树:树中每个节点表示表中的一个记录,节点里的值为该记录在表中的位置,通常 称这个查找过程的二叉树为判定树。
12.散列函数:一个把查找表中的关键字陵射成该关键字对应的地址的函数,
13.冲突(同义词):散列函数可能会把两下或以上的不同关键字映射到同一地址,这种情况 为冲突。
14.散列表:是根据关键字而直接进行访问的数据结构。散列表建立了关键字和存储地址指 间的一种直接映射关系。
15.开放定址法:指的是可存放新表项的空闲地址既向它的同义词表项开放,又向它的非同 义词表项开放。
16.拉链法(链地址法):把所有的同义词存储在一个线性链表中,这个线性链表由其散列地 址唯一标识。
17.装填因子:填入表中的元素个数/散列表的长度。
18.二次聚集: 指在处理冲突过程中发生的两个第一个哈希地址不同的记录争夺同一个后继 哈希地址的现象。
19.再哈希法:这种方法是同时构造多个不同的哈希函数: H₁=RH₁(key) i=1,2, … ,k。当哈希地址H₁=RH₁(key) 发生冲突时,再计算H=RH₂(key) … … , 直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。
21.胜者树与败者树: 胜者树和败者树都是完全二叉树,是树形选择排序的一种变型。每个 叶子节点相当于一个选手,每个中间节点相当于一场比赛,每一层相当于一轮比赛。不同的是,胜者树的中间节点记录的是胜者的标号;而败者树的中间节点记录的败者的标号。
第一章 绪论
一、数据结构的概念
1、数据结构是一门研究什么内容的学科?答:数据结构是一门研究在非数值计算的程序设计问题中,计算机的操作对象及对象间的关系和施加于对象的操作等的学科。
2、应从哪些方面考虑解决问题时所选择的数据结构?答:时间复杂度和空间复杂度。
3、评价各种不同数据结构的标准是什么?答:数据结构的评价标准可以从两个方面考虑,
①所选的数据结构是否准确、完整地刻画了问题的基本特征;②是否容易实现,例如逻辑结构的选择是否适合于运算的功能,是否有利于运算的实现等等。
二、数据对象
1、什么是数据对象?答:有相同性质的数据元素集合称为数据对象,它是数据的一个子集。
三、数据类型和抽象数据类型
1、数据类型是如何定义的?答:数据类型是高级程序语言中的一个基本概念,是值的集合和操作的集合。
2、数据结构和数据类型有什么区别?答:数据结构包括三个方面,分别是数据的逻辑结构、数据的存储结构以及数据的运算。而数据类型是值的集合和操作的集合,它是数据结构的一种简化情况。
3、什么是抽象数据类型,其主要特点是什么?它与数据类型有什么不同之处?答:①抽象数据类型是指一个数学模型及定义在该模型上的一组操作,包括三个部分,可概括为数据对象、数据关系和基本操作。用抽象数据类型可以定义一个完整的数据结构,其定义取决于它的逻辑特性。另外,数据结构的抽象操作的定义与具体实现无关。②抽象数据类型和数据类型实质上是一个概念,但抽象数据类型的范围更广,它不再局限于机器已定义和实现的数据类型,还包括用户在设计软件系统时自行定义的数据类型。
4、抽象数据类型与数据类型有什么不同之处?答:抽象数据类型和数据类型实质上是一个概念,但抽象数据类型的范围更广,它不再局限于机器已定义和实现的数据类型,还包括用户在设计软件系统时自行定义的数据类型。
四、逻辑结构
1、数据逻辑结构包括什么?它们各有什么特点?答:逻辑结构指的是数据元素之间在逻辑上的关系,可分为线性结构和非线性结构,线性结构是一对一的关系,而非线性结构是一对多或多对多的关系。更细分也可以说,逻辑结构包括集合、线性结构、树形结构和图形(网状)结构。
五、存储结构(物理结构)
1、什么是数据的存储结构?答:数据的逻辑结构在计算机中的表示称为存储结构,也称为物理结构,其中包括数据元素的表示和关系的表示。
2、数据存储结构包括哪几种类型?答:存储结构包括顺序存储、链式存储、索引存储和散列存储四种类型。
3、数据元素之间的关系在计算机中有几种表示方法?各有什么特点?答:①顺序存储方式。数据元素顺序存放,每个存储结点只含一个元素。该存储结构的优点是可以实现随机存取,每个元素占用最少的存储空间,顺序表的存储密度=1,而缺点是由于只能使用相邻的一整块存储单元,从而会产生较多的外部碎片,其存储密度大,但有些操作(如插入、删除) 效率较差;②链式存储方式。每个存储结点除了包含数据元素信息外还包含一组(至少一个) 指针,其存储结构一部分存放结点的值,另一部分存放表示结点间关系的指针(结点内的存储单元要求连续,而不同结点的存储空间可以不连续)。指针反映数据元素间的逻辑关系,这种方式不要求存储空间连续,便于动态操作(如插人删除等),该存储结构的优点是充分利用了所有的存储单元,不会造成碎片现象,而缺点是由于通过指针来表示逻辑关系,所以指针也要存储,从而占用额外的存储空间,但存储空间开销大,另外不能折半查找等。链表的存储密度<1,是由于结点中含有指针域。另外,链式结构只能顺序存取,不能随机存储;
③索引存储方式。在存储数据元素的同时还需要建立附加的索引表,索引表的索引项指示存储结点的存储位置。七优点是在查找数据元素时很快、容易找到,而缺点是由于附加了索引表,从而占用了额外的存储空间,同时,若需要增加和修改数据时,需修改索引表,会花费较多时间;④散列存储方式。通过利用散列函数和解决冲突的方法对数据元素的关键字直接计算其存储地址,然后将关键字散列在连续的有限的地址空间内,并将散列函数的值解释成关键字所在元素的存储地址。该存储结构的优点是在对数据元素进行增加、删除结点操作时很快,而缺点是若定义的哈希函数不能完全贴合情况,则会发生元素存储单元的冲突,而减少冲突从而会花费时间和一定的空间上的开销。
4、在数据结构课程中,逻辑结构、存储结构及数据的运算之间存在着怎样的关系?答:同一种逻辑结构可以有很多种存储结构。数据的运算是对数据定义的一组操作,运算是定义在逻辑结构上的,和存储结构无关,运算的实现依赖于存储结构。
六、算法的概念
1、什么是算法?答:通常将解决问题的确定方法和有限步骤称为算法,在计算机中,指的是对特定问题求解步骤的一种描述,是若干条指令的有穷序列。
2、算法的五个重要特征是什么?答:算法的五个重要特征:
①确定性;
②有穷性;
③可行性;
④零个或多个输入;
⑤一个至多个输出。
3、数据结构中评价算法的两个重要指标是?答:算法的时间复杂度和空间复杂度。
4、如何评价一个好的算法,是从哪几个方面来考虑的?答:评价一个好的算法有四个方面:
①算法的正确性;
②算法的易读性;
③算法的健壮性;
④算法的时空效率(时间复杂度和空间复杂度)。
- 栈、队列、串
栈与队列的区别。队列是允许在一段进行插入另一端进行删除的线性表。队列顾名思义就像排队一样,对于进入队列的元素按“先进先出”的规则处理,在表头进行删除在表尾进行插入。由于队列要进行频繁的插入和删除,一般为了高效,选择用定长数组来存储队列元素,在对队列进行操作之前要判断队列是否为空或是否已满。如果想要动态长度也可以用链表来存储队列,这时要记住队头和对位指针的地址。
栈是只能在表尾进行插入和删除操作的线性表。对于插入到栈的元素按“后进先出”的规则处理,插入和删除操作都在栈顶进行,与队列类似一般用定长数组存储栈元素。由于进栈和出栈都是在栈顶进行,因此要有一个size变量来记录当前栈的大小,当进栈时size不能超过数组长度,size+1,出栈时栈不为空,size-1。
相同点:(1)栈和队列都是线性结构,是两种特殊的线性表即受限的线性表,都对插入和删除操作加以限制;(2)栈和队列在插入时都是在表尾进行(3)都是逻辑结构的概念,,栈和队列都可以用顺序存储结构和链式存储结构(4)栈和队列插入和删除操作的时间复杂度和空间复杂度是一样的不同点:(1)栈只允许在一端进行插入和删除,因而是后进先出表;队列只允许在一端进行插入,另一端进行删除,因而是先进先出表。(2)用链表存储时可以实现多栈空间共享,队列不行
栈和队列的应用?
栈可用于函数调用和递归,括号匹配,后缀表达式求值;
队列常用于计算机各种资源的管理,消息缓冲器的管理和广度有限搜索算法等
栈在括号匹配的算法思想
遍历表达式,缝左括号就入栈,遇到右括号则检查栈是否为空,为空则表明不匹配,不为空则将左括号出栈;表达式遍历完成后栈为空则表明匹配,若栈中还有左括号表明不匹配
栈在后缀表达式求值的思想(1)是操作数则进栈(2)是运算符则将两个元素出栈并将得到的结果进栈
(3)表达式扫描完成后,栈顶元素为所求结果
栈在递归中的应用?递归是一种重要的程序设计方法。简单地说,若在一个函数、过程或数据结构的定义中又应用了它自身,则这个函数、过程或数据结构称为是递归定义的,简称递归。它通常把一个大型的复杂问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的代码就可以描述出解题过程所需要的多次重复计算,大大减少了程序的代码量。但在通常情况下,它的效率并不是太高。将递归算法转换为非递归算法,通常需要借助栈来实现这种转换。
队列在层次遍历中的作用?在信息处理中有一大类问题需要逐层或逐行处理。这类问题的解决方法往往是在处理当前层或当前行时就对下一层或下一行做预处理,把处理顺序安排好,待当前层或当前行处理完毕,就可以处理下一层或下一行。使用队列是为了保存下一步的处理顺序。下面用二叉树层次遍历的例子,说明队列的应用。
队列在计算机系统中的应用?队列在计算机系统中的应用非常广泛,以下仅从两个方面来简述队列在计算机系统中的作用:第一个方面是解决主机与外部设备之间速度不匹配的问题,第二个方面是解决由多用户引起的资源竞争问题。对于第一个方面,仅以主机和打印机之间速度不匹配的问题为例做简要说明。主机输出数据给打印机打印,输出数据的速度比打印数据的速度要快得多,由于速度不匹配,若直接把输出的数据送给打印机打印显然是不行的。解决的方法是设置一个打印数据缓冲区,主机把要打印输出的数据依次写入这个缓冲区,写满后就暂停输出,转去做其他的事情。打印机就从缓冲区中按照先进先出的原则依次取出数据并打印,打印完后再向主机发出请求。主机接到请求后再向缓冲区写入打印数据。这样做既保证了打印数据的正确,又使主机提高了效率。由此可见,打印数据缓冲区中所存储的数据就是一个队列。
对于第二个方面, CPU (即中央处理器,它包括运算器和控制器)资源的竞争就是一个典型的例子。在一个带有多终端的计算机系统上,有多个用户需要CPU 各自运行自己的程序,它们分别通过各自的终端向操作系统提出占用CPU 的请求。操作系统通常按照每个请求在时间上的先后顺序,把它们排成一个队列,每次把CPU 分配给队首请求的用户使用。当相应的程序运行结束或用完规定的时间间隔后,令其出队,再把CPU 分配给新的队首请求的用户使用。这样既能满足每个用户的请求,又使CPU 能够正常运行。
队列的溢出现象?如何解决下溢现象:队列为空时出队产生的现象;是正常现象;真上溢现象:队列满时继续往进队;建立一个足够大的存储空间来解决;假上溢现象:队列未满而无法继续进队;采用循环队列来解决;
两个栈实现一个队列:先将数据存在到第一个栈里,在将第一个栈里的元素全部出栈到第二个栈,第二个栈出栈,即可达到先进先出。
两个队列实现一个栈:先将数据存到第一个队列里面,然后数据出队一直出队到第二个队列里面,直到第一个队列里面剩余一个数据,这个时候出队,即可达到先进后出的特性。
如何区分循环队列是队空还是队满?普通情况下,循环队列队空和队满的判定条件是一样的,都是Q.front == Q.rear。队头指针指向第一个数;队尾指针指向最后一个数的下一个位置,即将要入队的位置。方法一:牺牲一个单元来区分队空和队满,这个时候(Q.rear+1)%MaxSize == Q.front才是队满标志 。方法二:类型中增设表示元素个数的数据成员。这样,队空的条件为Q.size == 0;队满的条件为Q.size == MaxSize。
二叉树与度为2树的区别?度为2的树至少有三个节点,而二叉树可以为空度为2的有序树的孩子的左右次序是相对与另一孩子而言的,若某个节点只有一个孩子,则这个孩子就无需区分左右次序,而二叉树无论其孩子数是否为2,均需要确定孩子的左右次序,即二叉树的节点次序不是相对另一节点而言的,是固定的。
一、栈
1、简述栈的特性。答:栈是被限制存取点的线性表,只允许在一端进行插入或删除操作,栈遵循的原则是先进后出(FILO),即后进的元素先被取出来。
1、栈有哪些应用场景?(试举例至少三种)答:栈有以下应用场景:①递归及函数调用;②表达式求值(例如,中后缀表达式、括号匹配等等);③进制转换(例如,十进制数转为二进制数等等);④迷宫求解;⑤缓存机制;⑥用栈对二叉树进行前、中、后序遍历;⑦用栈模拟队列。
2、栈的操作原则是什么?举出两个栈的应用例子。答:栈的操作原则是先进后出,例如用栈对二叉树进行前、中、后序遍历以及用栈模拟队列等等。
3、简述用两个栈模拟一个队列的基本思想。答:首先,定义两个栈S1和S2,将所有元素依次入栈S1,然后再依次出栈并进入栈S2,再从栈S2出栈。
1、写出顺序存储结构的顺序栈的结构体、栈空、栈满、进栈及出栈的关键代码。
答:①顺序栈的结构体:
#define MaxSize 20 //可自行设置
typedef struct {
int data[MaxSize]; //存放栈中元素 ,使用数组
int top; //栈顶指针 ,记录栈顶元素的位置
} SqStack; //顺序栈的类型定义
②判断顺序栈是否为空栈的条件是S.top==-1。
③判断顺序栈是否为满栈的条件是S.top==MaxSize-1。
④将一个元素插入顺序栈中,即进栈,
++S.top; //top指针始终指向栈顶,新的元素进栈,所以指针先加1
S.data[S.top]=x; //将进栈元素的值传入并入栈
这两行代码也可以使用一行代码:S.data[++S.top]=x直接替换。
⑤将一个元素从顺序栈中删除,即出栈,
x=S.data[S.top]; //出栈
S.top--; //指针减1
这两行代码也可以使用一行代码:x=S.data[S.top–]直接替换。
1、递归算法包括哪两个部分?简述递归的步骤。答:一个函数在结束本函数前,直接或间接湖围函数自身,称为递归。一个递归算法必须包括终止条件和递归部分,当递归的条件不满足时,此时递归结束返回,否则继续进行递归操作。
2、简述递归算法的优缺点。答:递归算法的代码简洁明确,其可读性好,但是其时间复杂度和空间复杂度较大,且在调用栈时可能会产生溢出。
1、简述栈和队列的相同点和不同点。答:①不同点:运算规则不同,栈遵循的原则是先进后出,而队列的原则是先进先出,栈只允许在一端进行插入、删除操作,而队列只允许在一端进行插入、另一端进行删除操作。另外,两个用途不同,栈由于子程序调用和保护现场,而队列用于多道作业处理、指令寄存及其他运算等等;
②相同点:都是操作受限的线性表,逻辑结构相同,且存储表示也相同(顺序存储结构和链式存储结构)。堆和栈的区别,以及为什么栈要快
堆和栈的区别① 扩展方向不同:堆是由低地址向高地址扩展;栈是由高地址向低地址扩展。② 申请方式不同:堆由程序员手动分配和管理;栈由系统自动分配和管理; ③ 效率不同:堆由程序员分配,分配效率较低,可能由于操作不当产生内存碎片;而栈由系统分配,分配效率较高,不会有内存碎片。④ 程序局部变量使用的是栈空间,new和malloc函数动态申请的内存是堆空间。
栈的效率高的原因栈是操作系统提供的数据结构,计算机底层对栈提供了一系列支持:分配专门的存储器存储栈的地址,压栈和入栈有专门的指令执行;而堆是由C和C++函数库提供的,机制复杂,需要一系列分配内存、合并内存和释放内存的算法,因此效率较低。
二、队列
1、队列的“先进先出”的特性是指什么?答:队列遵循的原则是先进先出,其特性是指最后插入队列中的元素总是最后被删除。
1、队列有哪些应用?答:队列的应用场景有以下:
(1)缓冲区(例如计算机与打印机中间的打印数据缓冲区);
(2)页面替换算法;
(3)图的广度优先搜索、树的层次遍历,都借助到了队列的基本思想。
1、怎么解决队列“假溢出”的问题?并写出相关的代码。答:将存储队列的一维数组首尾相连成环,形成循环队列,其中队头指针、队尾指针加1时通过取余运算实现,从而防止队列的“假溢出”。进对针对队尾指针,即Q.rear=(Q.rear+1)%MAXSIZE,出队针对队头指针,即Q.front=(Q.front+1)%MAXSIZE。
2、什么是循环队列?给出循环队列中元素个数的计算式(设最大长度为N,队首指针FRONT,队尾指针REAR)。答:循环队列也就是将顺序队列中的一维数组首尾相连成环,即在逻辑上视为一个环连接起来,让队首指针和队尾指针沿着环走;循环队列中元素个数的计算式为(REAR-FRONT+N)%N。
三、串
1、名词解释:串。答:串是一种线性结构,它是一种特殊的线性表,由零个或多个字符组成的有限序列,串的数据元素必须是字符,其通常以字符串的形式出现。
2、描述以下概念的区别:空格串与空串答:空串是不含任何字符的串,长度为0,ASCII码为0,而空格串是一个字符,它是由空格组成的串,长度等于空格的个数,其ASCII码是32。
1、KMP算法较于Brute算法(朴素的字符串匹配算法)有哪些改进?答:一般的字符串匹配算法的时间复杂度为O(mn),而KMP算法的时间复杂度为O(m+n),其主串指针不用回溯,当主串的长度很大需要部分匹配和一次不能调入内存时,其优点较一般匹配更突出。
3、什么是广义表?广义表与线性表的区别。线性表中的元素可以是各种各样的,但必须具有相同的性质,属于同一数据对象。 广义表中的元素可以是元素也可以是子表。
第五章 树和二叉树
一、树和二叉树的概念
1、简要说明二叉树的概念。二叉树有哪些性质。(至少写出3个)答:二叉树是一种树形结构,每个结点至多只有两棵子树,即二叉树中不存在度大于2的结点,且二叉树的子树也有左右之分。 性质:
①非空二叉树的叶子结点等于度为2的结点数加1,即n0=n2+1;
②高度为h的二叉树至多有2h-1个结点;
③一棵树高为h的完全二叉树至少有2h-1个结点,至多有2h-1个结点,
④一棵树高为h的完全二叉树中,总结点数N与高h的关系是h=⌈log2(n+1)⌉;
⑤对于一棵含有n个结点的二叉树,当它为完全二叉树时,具有最小高度,最小高度为h=⌈log2(n+1)⌉或⌊log2n⌋+1;当它为一棵单支树时具有最大高度,为一个线性表,即最大高度为n。
1、树和二叉树的区别是什么?答:树和二叉树均有且只有一个根结点,根结点没有前驱结点,除了根结点其他所有结点都只有一个前驱结点,剩下的结点为m(m≥0)个互不相交的非空集合。树中结点的后继结点可以是任意多个,而二叉树中结点的后继结点最多只能有两个,即二叉树的度小于等于2。
1、什么是完全二叉树?什么是满二叉树?它们两者之间的关系是怎么样的?答:深度(高度)为h,具有2h-1个结点的二叉树,其中每层结点都是满的二叉树,称为满二叉树,而若一棵树中除最后一层外,其余层的结点都是满的或结点的右子树缺少连续的若干个结点 ,则称为完全二叉树。满二叉树是完全二叉树的特例,可以说,若一棵树是满二叉树,则它必是完全二叉树,但不能说一个完全二叉树必是满二叉树。
三、二叉树的遍历
1、由二叉树先序遍历和后序遍历序列能否唯一确定一棵二叉树?请举例解释。答:不能。例如,下面两个二叉树的前序序列和后序序列均相同,但是不是相同的二叉树。
2、简述为什么二叉树的中序遍历序列与其前序或后序遍历序列可以唯一确定一棵二叉树。
答:二叉树的中序遍历序列中,由“左中右”的遍历关系以及根结点可以确认二叉树的左右子树,同时由二叉树的前序或后序遍历序列再确定结点中的父子关系,从而结合可以唯一确定一棵二叉树。
1、试分析非空二叉树在什么情况下,其前序遍历序列与后序遍历序列相同以及前序遍历序列与后序遍历序列相反?答:若一棵二叉树为空树或只有根结点,则其前序遍历序列和后序遍历序列相同。若一棵非空的二叉树只有一个叶子结点或二叉树的高度等于结点个数,则其前序遍历序列和后序遍历序列相反。
四、二叉树的性质
1、证明任意一棵二叉树中,若叶子结点的个数为n0,度为2的结点个数为n2,则必用n0=n2+1。
答:设二叉树中度为1的结点个数为n1,由于二叉树中所有结点的度均小于等于2,所以总结点个数为N=n0+n1+n2,另外,二叉树中除了根结点外,其他结点至少有一个分支,度为1的结点有一个分支,度为2的结点有两个分支,则分支总数=N-1=n1+2n2,联立两式,可得n0=n2+1。
1、具有n个结点的二叉树,什么时候下其深度达到最大?什么情况下其深度达到最小?
答:单支树时,二叉树的深度最大,最大为n层;若深度为h,结点个数满足2h+1-1时,即为满二叉树时,二叉树的深度最小。
五、二叉树与树的存储结构
1、简述二叉树的顺序存储结构以及其优缺点。答:二叉树的顺序存储结构是通过使用一组地址连续的存储单元数组进行存储,优点是读取指定结点时,可以直接通过数组下标访问,效率高,且可以很快地查找到左右孩子以及双亲结点,但缺点是存在浪费空间的情况,一个高度(深度)为h的非完全二叉树需要占据2h-1个数组存储单元。
1、介绍树的三种存储方式。答:①双亲表示法:对于每个结点,只存储它的双亲结点的位置,即通过一个一维数组分别存储结点的数据域和存储该结点双亲的数组下标。通过双亲表示法中可以很容易地找到每个结点的双亲和祖先结点,但是若要寻找结点的孩子结点或兄弟结点时就较为麻烦,需遍历整个数组,效率较低;其中每个结点被赋予一个结构体类型,包含data域和parent域,分别存储结点的数据域和存储该结点双亲的数组下标。②孩子表示法:对于每个结点,只存储它的第一个孩子结点的位置和下一个兄弟结点的位置。通过孩子链表表示法可以很容易地找到该结点的孩子结点,但是若要找到结点的双亲则较为麻烦,需遍历n个结点中孩子链表指针域所指向的n个孩子链表;③孩子兄弟表示法:对于每个结点,只存储它的第一个孩子结点的位置和它的下一个兄弟结点的位置。这种方法查找一个节点的所有孩子节点和所有祖先节点的效率都很高,同时查找一个节点的所有兄弟节点的效率也很高,但缺点是若从当前结点查找其双亲结点时较为麻烦。
六、树、森林与二叉树的转化
1、将树、森林转化为二叉树的最终目的是什么?答:①简化操作,在二叉树中,只需要考虑每个节点的左右子节点,这使得操作如搜索、插入、删除等更为简单,而对于具有多个子节点的树或森林,通过转化为二叉树可以减少复杂性;②方便使用二叉树算法,转化后可以通过高效很多有效的二叉树算法,如二叉搜索树的搜索、插入、删除等操作,可以很容易地应用于转化后的二叉树,而树和森林复杂;③统一存储,将树、森林转化为二叉树后,可以实现统一存储,即可以利用二叉树的各种优点来简化操作并提高效率,例如能够以递归的方式对数据进行组织等等。
七、线索二叉树
1、线索二叉树的作用是什么?答:由于在含有n个结点的二叉树中,有n+1个空指针。对于叶子结点,它有两个空指针,对于度为1的结点,只有一个空指针。将这些空指针利用起来,让其存放指向该结点的前驱或后继信息,从而使遍历二叉树更加简便,加快查找结点的前驱或后继的速度。同时,也能节省内存开销。
八、前缀编码
1、什么是前缀编码?哈夫曼编码是前缀编码吗?简述其作用。答:在对字符集进行编码时,若字符集中任一字符的编码都不是其它字符的编码的前缀,则称这种编码为前缀编码。哈夫曼编码是一种无前缀编码,通过可变长度编码使用不等长的二进制信息进行编码,使字符的平均编码长度缩短,从而更好地压缩数据进行传输。
九、哈夫曼树
1、什么是哈夫曼树?若哈夫曼树有n个叶子结点,则其结点总数是多少?答:哈夫曼树是一棵最优二叉树,给定n个带有权值的叶子结点,构造一棵二叉树,使构造的二叉树的带权路径长度最小,即为最优二叉树,也称为哈夫曼树。若哈夫曼树有n个叶子结点,由于哈夫曼树中只有度为0和2的结点,不存在度为1的结点,则其结点总数为N=2n-1。
1、写出构建哈夫曼树的哈夫曼算法思想。答:基于给定的n个带权值的结点构成的初始森林,首先,选出两棵权值最小的树作为左右子树相加,得出的权值之和是一个新根结点的权值,然后,将新结点插入到森林中,同时将左右子树从森林中删除,重复选取,直到森林中只有一棵树时,即为哈夫曼树。
1、哈夫曼编码是什么?答:哈夫曼编码是一种可变长度编码,且是无前缀编码,它根据字符出现的概率来对每个字符设定二进制编码,规定一个编码不能是其它编码的前缀,主要应用在数据压缩、加密解密等场景。
十、二叉排序树
1、简述二叉排序树。答:二叉排序树也称为二叉查找树或二叉搜索树,其中各结点值的大小关系是:左子树<根结点<右子树,且左、右子树也是一棵二叉排序树满足其条件,若对该树进行中序遍历,可得到一个递增的序列。
用循环比递归的效率高吗?循环和递归两者是可以互换的,不能决定性的说循环的效率比递归高。
递归的优点:代码简洁清晰,容易检查正确性;缺点是:当递归调用的次数较多时,要增加额外的堆栈处理,有可能产生堆栈溢出的情况,对执行效率有一定的影响。循环的优点:结构简单,速度快;缺点是:它并不能解决全部问题,有的问题适合于用递归来解决不适合用循环。
- 查找
- 查找的概念
1、散列表存储的基本思想是什么?
散列表的基本思想是用关键字的值决定数据元素的存储地址
2、散列表存储中解决碰撞的基本方法有哪些?
a 、开放定址法根据di 的取值又分为线性探测再散列、二次探测再散列、伪随机探测再散列b 、再散列法 c、链地址法 d 、建立公共溢出区
1、简述静态查找和动态查找的概念,并举例相应的查找名称。答:查找某个特定元素是否在表中和它的相关属性称为静态查找,例如顺序、折半、分块、散列查找等;若在查找过程中需要插入或删除查找表的元素,则为动态查找,例如树形查找中的二叉搜索树、平衡二叉树、B树等。
1、什么情况下可以采用二分查找?若数据元素的个数为n,则查找成功的平均查找长度是多少?答:二分(折半)查找要求线性表必须采用顺序存储结构,且表中元素按关键字有序排列,由于在二分判定树中,比较次数最多不会超过树的高度h=⌈log2(n+1)⌉,即二分查找成功的平均查找长度为O(log2n)。
2、对于一个有序顺序表来说,折半查找是否任何时候都比顺序查找快?为什么?答:并不是,只是一般情况下折半查找比顺序查找快,因为折半查找每次比较都可以排除一半的元素,从而减少了查找时间。例如,若要查找的元素为顺序表的第一个元素,则通过顺序查找会比折半查找快。
1、在很多查找和排序算法中,经常使用“监视哨”,其目的是什么?答:监视哨的作用是免去了查找过程中每次都要检测整个表是否查找完毕,提高了查找效率。
二、散列查找
1、在采用线性探测法处理冲突的散列表中,所有同义词在表中是否一定相邻?答:不一定相邻。因为发生了冲突,即出现两个不同的关键字被哈希函数散列到同一个地址的情况,都争夺哈希地址。
1、简述构造哈希函数的常用方法。答:简述构造哈希函数的常用方法有以下:
(1)直接定址法:选取关键字或关键字的某个线性函数值为哈希地址;(2)除留余数法:选取关键字除以某个整数的余数作为哈希地址,即通过取余运算得到的余数作为哈希地址;(3)平方取中法:取关键字平方的中间几位作为哈希地址;(4)折叠法:将关键字分割成位数相同的几段,然后叠加求和作为哈希地址。
2、如何衡量Hash函数的优劣?答:评价Hash函数的优劣有:能否将关键字均匀影射到哈希空间上,有无好的解决冲突的方法,计算哈希函数是否简单高效等。另外,一个好的哈希函数可以减小冲突,但不可能避免冲突。
1、假设已按散列函数H和冲突处理方法R建立了散列表,试写出散列查找的步骤。答:设查找哈希表的关键字KEY,首先通过散列函数计算地址,然后用关键字KEY与该地址的关键字进行比较,若当前地址为空,则查找失败;若相同,则查找成功;若不同,则通过冲突处理方法R得到下一个地址进行比较,直到相同为止,其中若按照冲突处理方法R得到的新地址又比较为空,则证明查找失败。
1、简要叙述hash表技术中的冲突概念,并指出三种解决冲突的方法。答:两个不同的关键字被哈希函数散列到同一个地址的情况则称为冲突,解决冲突的方法有线性探查法、平方探查法、双散列法、链地址法等等。
散列函数的构造方法包括:直接定址法、除留余数法、数字分析法、平方取中法、折叠法、随机数法。其中,最常用的是除留余数法。(1)直接定址法:取关键字的某个线性函数值作为散列地址,即H(key) = a*key+b。
- 除留余数法:取关键字对p取余的值作为散列地址,其中p通常是小于或等于散列表表长m的质数,即H(key) = key % p处理冲突的方法包括:开放定址法和拉链法。其中,开放定址法包括:线性探查法,二次探查法,双重散列法。(1)线性探查法:将散列表T[0…m-1]看成是一个循环向量,若初始探查的地址为d(即h(key)=d),探查时从地址d开始,首先探查T[d],再探查T[d+1]…直到探查到T[m-1],此后循环到T[0],T[1]…直到探查到T[d-1]为止,探查时,如果遇到有空的地址就插入。(2)拉链法:若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数组,凡是散列地址为i的结点均插入到头指针为i的单链表中。
与开放定址法相比,链地址法的优点是:① 链地址法处理冲突简单,且无堆积现象,因此平均查找长度较短;② 在用链地址法构造的散列表中,删除结点的操作易于实现。而链地址法的缺点是:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间。
三、树形查找
1、什么是二叉搜索树?答:用于查找的二叉树,其中每个结点的值不小于左子树结点的值,不大于右子树结点的值。
1、什么是平衡二叉搜索树?有哪些动态平衡调整操作?答:平衡二叉树以二叉搜索树为基础,若二叉搜索树中左、右子树的高度之差的绝对值不超过1,则称为平衡二叉树,其左、右子树也为一棵平衡二叉树。有以下动态平衡调整操作:①左单旋转LL;②右单旋转RR;③先左后右双旋转LR;④先右后左双旋转RL。
1、一棵具有m层的AVL树至少有多少个结点,最多有多少个结点?答:一棵具有 m 层的平衡二叉树(AVL),最多有2m-1个结点,另外,由斐波那契数列(Fibonacci),可得最少有f(m) = f(m-1) + f(m-2) + 1个结点,其中f(1) = 1 、f(2) = 2、f(3) = 4。
第八章 排序
一、内排序和外排序
1、内排序和外排序有什么区别?内排序有哪些算法?答:根据排序过程中,数据元素是否完全在内存中进行,可分为内排序和外排序。内排序有直接/折半插入排序、简单旋转排序、冒泡排序、希尔排序、快速排序和堆排序。
二、排序算法的稳定性
1、什么是稳定排序?答:经过排序后能使关键字相同的元素保持原本顺序中的相对位置不变,则称这个算法是稳定的,反之则不稳定。
三、插入排序
1、简述直接插入排序算法的基本思想。答:直接插入排序是将要排序的序列按照关键字的大小插入至已排好序的子序列中,一直进行直到整个序列有序。
1、直接插入排序算法是不是稳定的排序方法?答:由于每次插入元素时总是从后向前比较后再移动,所以不会出现相同元素相对位置发生变化的情况,即直接插入排序是稳定的。
1、简述折半插入排序算法的基本思想。答:折半插入排序的具体步骤如下:
初始化一个已排序序列,该序列只包含第一个元素,从第二个元素开始,通过折半查找确定每个待排序元素的插入位置,根据已排序序列中元素的中点,比较待排序元素与中点元素的大小,若待排序元素大于中点元素,则插入位置在中间位置的右侧;否则,插入位置在中间位置的左侧,然后插入元素,同时,需要将插入位置及其之后的所有元素向后移动一位,以为待排序元素腾出空间,重复步骤,直到所有元素都被插入到已排序序列中。
1、简述希尔排序的基本思想。答:希尔排序也称为缩小增量排序,即通过选取一定的增量来排序的,本质还是插入排序,通过增量将序列分为几个子序列,然后对每个子序列进行直接插入排序。
四、交换排序
1、简述冒泡排序的步骤。答:通过两两比较相邻的元素,若发生逆序,则进行交换,直到整个序列有序为止,即若某一趟冒泡排序中没有发生元素交换,说明此时序列已整体有序。
1、设有n 个元素采用冒泡排序法进行排序,通常需要进行多少趟排序?对于第i 次冒泡通常需要进行多少次关键字比较?答:n个元素采用冒泡排序进行排序,最多需要进行n-1趟排序,即最坏情况下,排好的序列刚好与初始序列相反,呈逆序排列;而最少是初始序列正序,只需一趟即可完成排序。
2、设有n 个元素采用冒泡排序法进行排序,第i 次冒泡通常需要进行多少次关键字比较?
答:最好情况下,比较次数为n-1;最坏情况下,由于需要进行n-1趟排序,第i趟排序中要进行n-i次比较。
1、简述快速排序的步骤。答:快速排序又称为分区交换排序,通过多次划分操作来实现排序思想,其步骤如下:①每一趟排序中选取一个关键字作为枢轴;②枢轴将待排序的序列分为两个部分,比枢轴小的元素移到其前,比枢轴大的元素移到其后,这是一趟快速排序;
③然后递归地对两个部分按照枢轴划分规则继续进行快速排序,直至每个区域只有一个元素为止或序列为空,最后达到整个序列有序。
1、试举例说明快速排序的稳定性。答:快速排序是不稳定的。当快速排序在处理包含有相等的元素的数组时,相等元素的值没有改变,但它们的相对顺序已经发生了变化,从而导致排序结果不稳定。
五、堆排序
1、简述堆排序的基本思想。答:堆排序的基本思想是利用大根堆(小根堆)进行排序的方法,步骤如下:①将待排序的序列构造成一个大根堆(小根堆),此时,整个序列的最大值(最小值)即为堆的根结点。②将当前根结点移走,即与堆数组的末尾元素交换,此时末尾元素就是最大值(最小值),然后将剩余的n-1个序列重新构造成一个堆,依次得到n个元素中的次大值(次小值);③重复以上步骤,从而得到一个有序序列。
1、堆排序是不是稳定排序?答:堆排序不是,因为在进行筛选时可能会将后面相同关键字的元素调整到前面,所有不是稳定的排序算法。
1、设结点个数为 n,采用堆排序法进行排序,其时间复杂性是多少?答:堆排序的时间复杂性取决于堆的构造和调整过程,将结点个数为n的初始序列构造成一个大根堆或小根堆,建堆过程中元素比较次数最多为4n,由于需要遍历整个序列,所以这个构造过程的时间复杂度为O(n)。然后,从剩余n-1个元素中选出一个最大或最小的元素,与末尾元素交换,这样的步骤最多需要n-1次,所以复杂度是n(n-1)/2次对数级别的比较,但是需要减去n/2的建堆时间,即排序过程的时间复杂度为O(nlog2n),所以总的堆排序的时间复杂度为O(n)+O(nlog2n)=O(nlog2n)。
六、归并排序
1、什么是归并排序?答:将已有序的子序列合并,得到完全有序的序列,其中先使每个子序列有序,再使子序列间有序,即为归并排序。
1、归并排序是不是稳定的?答:归并排序是稳定的排序算法,满足稳定算法的定义,即假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面,且排序之后,a[i]仍然在a[j]前面。
1、简述二路归并排序的算法思想。答:二路归并排序的步骤如下:
①将含n个元素的序列分为由n个长度为1的有序子表;
②相邻的两个有序子表归并为一个有序子表(两两相邻归并);
③重复以上步骤,最终归并成一个长度为n的有序表。
七、排序算法的综合运用
1、现有一文件F含有 1000 个记录,其中只有少量记录次序不对,且它们距离正确位置不远如果以比较和移动次数作为度量,那么将其排序最好采用什么方法?为什么?答:由于文件中基本都是有序的,只有少量记录次序不正确,所以可以通过直接插入排序,它在初始序列已基本有序的情况下表现较好,即在每一步中,只需要移动很少的记录,而不像其他排序算法可能需要交换多个记录。因为只需要比较和交换记录的位置,所以比较次数较少,且由于距离正确位置不远,从而使通过直接插入排序的移动次数也较少,所以选择直接插入排序。
2、全国有 10000 人参加物理竞赛,只录取成绩优异的前 10 名,将他们从高分到低分输出。而对落选的其他考生,不需排出名次,问此种情况下,用何种排序方法速度最快?为什么?答:堆排序。一般在n个元素中选出k(k<<n,k>2)个最大(或最小)元素时,均采用堆排序,且堆排序建堆时的最多比较次数为4n,而其他排序算法的时间复杂度较高。
2、稳定排序有哪些?不稳定排序有哪些?稳定排序:直接插入排序、冒泡排序、归并排序、基数排序 不稳定排序:选择排序、希尔排序、快速排序、堆排序
3、快速排序是在所有情况下,排序速度最快的吗?为什么?不是,因为当序列已有序时,快速排序退化成了冒泡排序,时间复杂度为0(n2)。当待排序列无序,使每次划分完成后,枢轴 (pivot) 两侧子文件长度相当,此时快速排序性能最好。
4、比较次数与序列初态无关的算法是:二路归并排序、简单选择排序、基数排序
比较次数与序列初态有关的算法是:快速排序、直接插入排序、冒泡排序、堆排序、希 尔排序
5、简述堆的结构。堆是一种特殊的完全二叉树,所有父结点都比子结点要小的完全二叉树我们称为最小堆。反 之,如果所有父结点都比子结点要大,这样的完全二叉树称为最大堆。
- 线性表
数组和链表的区别。(1)数组优点:① 随机访问性强② 查找速度快缺点:① 插入和删除效率低② 可能浪费内存③ 大小固定,不能动态拓展(2)链表优点:① 插入和删除效率高② 内存利用率高,不会浪费内存③ 大小没有固定,拓展很灵活缺点:不能随机查找,必须从第一个开始遍历,查找效率低
单链表与双链表的区别?单链表:只能向后访问,不能逆向访问。双链表:在单链表的基础上添加一个指向前驱节点的指针域,实现双向遍历
单链表 双链表 循环链表的区别?单向链表,它包含两个域,一个信息域和一个指针域。这个链接指向表中的下一个节点,而最后一个节点则 指向一个空值NULL。单向链表只可向一个方向遍历。查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。也可以提前把一个节点的位置另外保存起来,然后直接访问。
双向链表,(双链表)。双向链表中不仅有指向后一个节点的指针,还有指向前一个节点的指针。第一个节点的"前连接"指向NULL,最后一个节点的"后连接"指向NULL。这样可以从任何一个节点访问前一个节点,也可以访问后一个节点,以至整个链表。一般是在需要大批量的另外储存数据在链表中的位置的时候用。
由于另外储存了指向链表内容的指针,并且可能会修改相邻的节点,有的时候第一个节点可能会被删除或者在之前添加一个新的节点。这时候就要修改指向首个节点的指针。有一种方便的可以消除这种特殊情况的方法是在最后一个节点之后、第一个节点之前储存一个永远不会被删除或者移动的虚拟节点,形成一个循环链表。这个虚拟节点之后的节点就是真正的第一个节点。这种情况通常可以用这个虚拟节点直接表示这个链表。
循环链表。在一个循环链表中, 首节点和末节点被连接在一起。这种方式在单向和双向链表中皆可实现。要转换一个循环链表,你开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点。循环链表可以被视为"无头无尾"。循环链表中第一个节点之前就是最后一个节点,反之亦然。循环链表的无边界使得在这样的链表上设计算法会比普通链表更加容易。对于新加入的节点应该是在第一个节点之前还是最后一个节点之后可以根据实际要求灵活处理,区别不大。另外有一种模拟的循环链表,就是在访问到最后一个节点之后的时候,手工跳转到第一个节点。访问到第一个节点之前的时候也一样。这样也可以实现循环链表的功能,在直接用循环链表比较麻烦或者可能会出现问题的时候可以用。
判断一个链表是否有环,如何找到这个环?给定一个单链表,只给出头指针h:
1)如何判断是否存在环?对于判断一个单链表是否存在环,可以利用追赶的方式,设立两个指针slow、fast,从头指针开始,每次分别前进一步和两步,如果存在环,则两者相遇;如果没有环,fast遇到NULL退出。
2)如何知道环的长度?在slow和fast相遇的地方标记,再次相遇所走过的操作数就是环的长度。
3)如何找出环的连接点在哪里?分别从相遇点和头指针开始走,再次相遇的那个点就是连接点。
4)带环链表的长度是多少?连接点距离头指针的长度,加上环的长度,即为链表长度。
链表头节点的作用?(1)由于第一个数据节点的位置被存放在头节点的指针域中,因此链表的第一个位置上的操作和在表的其他位置的操作一致,无需进行特殊处理(保证每一个结点都有前驱结点,使得插入和删除结点的处理统一)(2)无论链表是否为空,其头指针都指向头节点的非空指针,因此空表与非空表的处理也得到了统一(带头结点的链表,在表空时存在头结点,使得空表和非空表的处理统一)
一、顺序表
1、数组和顺序表的区别在哪里?答:顺序表体现了数据元素之间的线性关系,即一对一的关系,以及对数据元素定义的一组运算操作,所以操作起来比数组更容易实现、方便操作,而数组只是物理区域上的一组连续的存储单元,它是具有相同类型的若干元素按无序的形式组织起的一种形式。
二、链表
1、说明在线性表的链式存储结构中,头指针与头结点之间的根本区别,头结点与首元结点的关系。答:①头指针具有标识作用,常用头指针代指链表的名称,同时可以防止链表为空;头结点的设置可以使插入或删除操作统一起来并且方便。②首元结点是第一个元素结点,即头结点后的第一个结点。
2、单链表设置头结点的作用是?答:①防止单链表为空,若单链表为空时,则为一个空链表,即头结点L→next=NULL;②保证了插入元素和删除元素操作的统一性,带有头结点的单链表,其存储位置存放在头结点L的指针域中,指向单链表的第一个结点。
3、链表可以通过指针分为哪些类别?答:根据线性表的链式存储结构中每一个结点包含的指针个数,可将线性链表分成单链表和双链表,而又根据指针的连接方式,链表又可分成静态链表和(动态)链表。
三、顺序表与链表的对比
2、试举一例说明对相同的逻辑结构,同一种运算在不同的存储方式下实现,其运算效率不 同。答:线性表的插入删除操作。在顺序存储方式下平均移动一半元素,时间复杂度为0(n),在 链式存储方式下,插入和删除的时间复杂度都是0(1)。
3、说明头指针、头节点、首元结点的概念。头指针是指向链表中第一个结点(或头节点或首元结点)的指针。头节点是在链表的首元结点之前附加的一个结点,头跟点是为了操作的统一方便而设立的。 数据域一般无意义,只放空表标志和表长等信息。首元素结点是指链表中存储线性表中第一个无素结点。
1、简述顺序表和链表存储方式的特点。答:①顺序表实现简单,可以随机存取,其存储密度大,但是执行插入、删除操作需要移动大量元素,效率低,另外其存储空间需事先分配,容易造成空间浪费或溢出。②链表不支持随机存取,只能顺序存取,通过指针来体现元素之间的逻辑关系,存储密度比顺序表小,其执行插入、删除操作不需要移动元素,只需修改指针,效率高,另外它还支持动态分配存储空间,不会造成空间浪费或溢出。
2、顺序存储结构和链式存储结构分别是通过什么来表示数据元素之间的逻辑关系的?答:顺序存储结构是通过物理上相邻的地址来表示逻辑关系,而链式存储结构是通过指针来表示逻辑关系。
3、若线性表插入和删除操作比较频繁,则宜采用什么存储结构?为什么?答:链式存储结构,采用该结构在执行插入、删除操作时不需移动大量元素,只需修改指针,且可以支持存储空间的动态分配。
四、循环链表
1、循环单链表最大的优点是什么?答:循环单链表中从任一结点出发都可以访问到链表中的每一个元素。
五、静态链表
1、简述静态链表的定义以及其优缺点。答:静态链表借助数组来描述链式结构,每个数组元素有两个分量,一是数据元素的值,二是指针,指针指向下一个元素在数组中的位置 (下标)。静态链表插入和删除操作时只需修改指针,而不需要不移动数据,但是静态链表不能随机存取。另外,若定义的数组太大,有可能浪费较多的存储空间。
六、单链表的插入删除代码
4、简述顺序存储队列假溢出的避免方法及队满和空的条件。
答:避免方法: 一是将队列元素向前“平移”(占用0至rear—front1);二是将队列看成首尾相连,即看做循环队列(0...m-1)。在循环队列下,定义front=nea时为队空,而判断队满则常用两种方法:一种是用“牺牲一个单元”,即rear+1=front (准确说是(rear+1)%m==front 时 ,m是队列容量)时为队满:另一种方法是“设标记”,如设标记 tag,tag=0时为队空tag=1 时,若因插人导致front=rear 则为队满。
- 单链表中,在指针 *p 所指向的结点之后插入结点 *q,写出关键代码。答:先将 *q与原本 *p的指针域指向的结点,再与p相连【先连后,再连前】q->next=p->next;p->next=q;
2、在单链表中在 *p的前插入一个 *q指向的新结点,以temp为中间变量,写出关键代码。
q->next=p->next;
p->next=q;
temp=p->data; //交换数据域
p->data=q->data;
q->data=temp;
答:通过中间变量temp来交换数据域data的代码部分,【先后插,再交换】,代码如下:
- 在单链表中删除一个以前驱*p,*q指向的结点,写出关键代码。
q=p->next; //先定位,定位删除位置
p->next=q->next; //断开q与p的连接,p与下一个结点连接
free(q); //通过free()函数进行释放
答:查找后删除的步骤可概括为【先定位,后断开释放】,将*q指针指向要删除的结点,p为其前驱结点,代码如下:在这里插入图片描述
2、在单链表中删除*p指向的结点,写出关键代码。
答:通过交换两个指针的数据域,交换两个指针的数据域,然后通过free()函数删除后继结点,代码如下:q=p->next; //先定位,定位删除位置
p->data=p->next->data; //与后继结点交换数据域data
p->next=q->next; //断开q与p的连接,p与下一个结点连接
free(q); //通过free()函数进行释放
七、双链表的插入删除代码
1、双链表中,在指针 *p 所指向的结点之后插入结点 *q,写出关键代码。
答:双链表的插入操作可以概括为【先连后,后连前】,代码如下:q->next=p->next;
p->next->prior=q;
q->prior=p;
p->next=q;
1、双链表中,删除指针 *p 所指向的结点之后的结点 *q,写出关键代码。
答:代码如下:p->next=q->next;q->next->prior=p;free(q);
八、循环单链表的插入删除代码
1、循环单链表中,在指针 *p 所指向的结点之后插入结点 *q,写出关键代码。
答:循环单链表的插入操作与单链表类似,也是【先连后,再连前】,代码如下:q->next=p->next;//先连后p->next=q; //再连前
1、循环单链表中,在指针 *p 所指向的结点之后插入结点 *q,写出关键代码。
答:循环单链表的删除操作也与单链表类似,删除的步骤可概括为【先定位,后断开释放】,代码如下:q=p->next; //先定位,定位删除位置
p->next=q->next; //断开q与p的连接,p与下一个结点连接
free(q); //free()函数释放结点
九、循环双链表的插入删除代码
1、循环双链表中,在指针 *p 所指向的结点之后插入结点 *q,写出关键代码。
答:p结点为新结点q的前驱结点,代码如下:q->next=p->next;
p->next->prior=q;
q->prior=p;
p->next=q;
1、循环双链表中,删除*p指向的结点,写出关键代码。
答:将*p指针指向要删除的结点,代码如下:p->next->prior=p->prior;
p->prior->next=p->next;
free(p);
第六章 图
一、图的定义
1、什么是无向图?什么是有向图?答:按照图中的边是否有方向性,可以分为有向图和无向图,即一个图的前驱和后继关系没有区别,则为无向图;而一个图的前驱和后继关系有区别,则为有向图。
二、连通图及强连通图
1、什么是连通图?什么是强连通图?答:连通图指的是无向图,强连通图指的是有向图。在无向图中,任意两个结点都是连通的(任意两个结点之间有路径),则该图为连通图;而在一个有向图中,任意两个不同的顶点都存在相互之间的路径,则称为强连通图。极大连通子图,极小连通子图。极大是要求该连通子图包含其所有的边(暗指无向图),亦为连通分量。极小是在保持连通的情况下使边数最少的子图(暗指无向图),亦为最小生成树。
1、简述什么是连通分量和强连通分量?答:无向图的极大连通子图称为连通分量,类似,有向图的极大强连通子图称为强连通分量。
1、具有n个顶点的连通图,至少有多少条边?至多有多少条边?答:一个含有n个顶点的无向连通图,构成一棵树时图中边数最少,有n-1条边;而当无向完全图时图中边数最多,有n(n-1)/2条边。
三、图的遍历
1、说明图的深度优先遍历算法思想。答:图的深度优先遍历(DFS)需要借助栈来遍历:
①首先,选取图中某一顶点vi作为起始点访问;
②任意选取一个与vi邻接的顶点,且该顶点未被访问,一直重复下去,直到图中所有与vi连通的顶点都被访问到;【可概括为由起始顶点开始,沿着一条路径尽可能深入地搜索图,直到无法再继续下去】
③若还有顶点未被访问到,则另外选取一个未被访问的顶点再次作为起始点,回溯到上一个未访问的顶点,重复以上步骤,直至图中所有结点被访问。
1、说明图的广度优先遍历算法思想。答:图的广度优先搜索(BFS)需要借助到队列来遍历:
①首先,选取图中某一顶点vi作为出发点,访问后将其入队并标记为已访问(使用队列用于避免重复访问,存放已经访问过的各邻接顶点);
②依次访问与vi邻接的顶点,即当队列不为空时检查出队顶点的所有邻接顶点,访问未被访问的邻接顶点并将其入队,重复该过程;【可概括为由起始顶点开始,按照广度优先的顺序逐层遍历与当前顶点相邻的顶点将其访问】
③当队列为空时跳出循环,即所有已被访问的顶点的邻接顶点均被访问到,则此时遍历完成。
1、如何利用图的遍历算法来判断一个图是否是连通图?答:两种遍历算法都可以用于判断图的连通性,图的深度优先遍历和广度优先遍历中,若在遍历中,所有的顶点都被访问到,则图是连通的,否则,图是不连通的。
四、图的存储结构
1、图有哪两种常用的存储结构?另外还有哪些存储结构?答:图的常用存储结构有邻接矩阵和邻接表,另外还有十字链表、邻接多重表等等。图的邻接矩阵用于表示顶点之间的相邻关系,其中通过一个一维数组存储顶点,一个二维数组存储顶点之间的相邻关系,一个顶点数为n的图的邻接矩阵是n×n(n行n列);邻接表采用顺序存储结构和链式存储结构来存储图,对于图中每个顶点vi,将所有邻接于vi的顶点连成一个单链表,即这个单链表就称为顶点vi的邻接表,另外还需将所有顶点的邻接表放进数组中,通过邻接表存储图所用的空间大小取决于图的顶点数和边的个数,顶点数n决定了顶点表的空间大小,边的个数决定了边表结点的空间大小。
1、求有向图中每个顶点的入度和出度,采用哪种存储结构更为方便?为什么?答:邻接矩阵,因为有向图的邻接矩阵中,第i行非零元素的个数和第i列非零元素的个数对应该顶点的出度OD(vi)和入度ID(vi),又由于有向图中度等于出度和入度之和,即顶点vi的度为其邻接矩阵中第i行和第i列的非零元素的个数之和。而若采用邻接表,则需要遍历一个链表,才能求有向图中每个顶点的入度和出度。
1、简述图的邻接矩阵存储结构的优缺点。答:优点是可以很方便地从矩阵中通过值等于0或1来判断两个顶点是否存在边;另外还可以便于计算每个顶点的度,对于无向图,行之和为顶点的度,而对于有向图,行之和为顶点出度,列之和为顶点入度,即顶点的度为第i行和第i列的非零元素的个数之和。缺点是空间复杂度较高,对于n个顶点的有向图需要n2个存储单元来存储,而对于n个顶点的无向图通过压缩存储只需要n(n-1)/2个存储单元来存储,两个的空间复杂度均为O(n2),特别是对于稀疏图来说浪费存储空间。
1、简述图的邻接表存储结构的优缺点。答:优点是空间利用率高,对于稀疏图(边数相对较少的图)来说,邻接表可以有效地节省存储空间,其中每个顶点只需要存储其相邻顶点的信息;由于是一种链式数据结构,所以可以很方便地添加或删除顶点;另外,其查找效率高,通过链式结构,每个顶点都有一个链表存储其相邻顶点的信息,只需遍历该链表即可找到所有相邻顶点,而在邻接矩阵中,需要扫描整行或整列才能找到所有相邻顶点。 缺点是需要额外的空间存储边信息,每个顶点都需要存储其相邻顶点的信息,需要额外的空间;由于需要遍历邻接表中的所有边才能判断出,需要花费较高的时间复杂度,所以无法直接判断两个顶点是否存在边;另外,由于每个顶点的相邻顶点信息存储在链表中,需要遍历该链表才能计算出该顶点的度。
1、简述图的邻接多重表的定义及该存储结构解决了哪些问题?答:该存储结构对于无向图,将一条边的两个顶点存放在边表结点中,而将邻接于同一个顶点的边串联在顶点表结点中,即邻接多重表,它是邻接表的改进方法。这种存储方式解决了邻接表在存储无向图时同一条边要存储两次的问题,即一条边只需一个结点来记录,避免了同一条边的重复存储,提高了空间存储效率。
1、简述图的十字链表的定义及该存储结构解决了哪些问题?答:该存储结构对于有向图,中图的每个顶点都有两个链表,一个是以该顶点为起点的弧,另一个是以该顶点为终点的弧,将邻接表和逆邻接表结合起来,同时存储每个顶点的出度和入度,从而很方便地找到有向图顶点的入度和出度信息。
五、图的应用
1、简述最小生成树的Prim算法的基本步骤。答:每次从图中任取一个顶点与当前加入的树中顶点集合距离最近的顶点,并将该顶点和相应的边加入树,直到所有顶点都并入树中,得到最小生成树。
1、简述Kruskal算法求最小生成树的思想。答: 一个含n个顶点的图,克鲁斯卡尔算法的思想是将图的所有边对应的权值按照从小到大的顺序依次开始选取,若选取的某边与先前的树构成回路,则舍去,一直进行下去,直到所有顶点被访问到,当生成树的边的个数为n-1时为止,即可得到最小生成树。
1、Dijkstra算法和Floyd算法两者求解最短路径区别是什么?答:①求解目的不同,Dijkstra算法适用于图中某源点到其他顶点的最短路径问题,而Floyd算法适用于图中任意两点之间的最短路径问题;②时间复杂度不同,对于图G=(V,E),其中|V|表示图中顶点的数量,Dijkstra算法的时间复杂度为O(|V|2),而Floyd算法的时间复杂度为O(|V|3)。
1、简述拓扑排序的步骤。答:对于一个AOV网进行拓扑排序,其步骤如下:
1、从网中找选择一个没有前驱,即入度ID(v)=0的顶点;
2、删除该顶点且删除由该顶点的所有起始边(出度的边),并将该顶点输出;
3、重复(1)和(2)步骤,直至AOV网为空或不存在没有前驱的结点为止;
4、最后得到一个序列,即拓扑排序。
2、通过对AOV网进行拓扑排序得到的序列可以有多个,说法对吗?为什么?答:正确,AOV网的拓扑排序的序列不止一个,也可以有多个,是由于当网中有多个入度为0的顶点时,进行拓扑排序,从而得到的序列不止一种。
1、简述关键路径的求解过程。答:关键路径的求解步骤如下:
1、根据所给的图,求得该图的拓扑有序序列和逆拓扑有序序列;
2、通过得到的序列,先对事件,求得每个事件的最早发生时间和最迟发生时间;
3、根据(2)得到的结果,再对活动,求得每个活动的最早发生时间和最迟发生时间;
4、根据(3)得到的结果,找到最早发生时间和最迟发生时间相同的活动,就得到了关键活动,由关键活动连成的路径即为关键路径。
3、对一个图进行遍历可以获得不同的遍历序列,那么导致得到不同遍历序列不唯一的因素 有哪些?遍历不唯一的因素有:开始遍历的结点不同;存储结构不同;在邻接表情况下邻接点的顺序 不同。
4、在什么情况下,Prim 算法和 Kruskual 算法生成不同的最小生成树MST?在有相同权值边时生成不同的MST, 在这种情况下,用Prim 算法或 Kruskual 算法会产生不 同 的MST。
5、Prim 算法和Kruskual 算法区别Prim 算法是加点法,适合边稠密图; Kruskual 算法是一种按权值的递增次序选择合适边来 构造生成树的加边法,适合边稀疏而顶点较多的图。
普利姆算法(Prime)Prim(普里姆):采用了贪心算法的思想(1)将起始顶点并入生成树(2)将各顶点到生成树距离最短的那个顶点并入生成树(3)更新各顶点到生成树的距离(比较第二步并入的顶点到各顶点的距离是否会比原顶点距离短,会的话则更新顶点到生成树的距离)(4)重复以上三步直到所有顶点并入,此时最小生成树完成时间复杂度为O(n^2),适合用于稠密图克鲁斯卡尔算法(Kruska)思路:每次找出候选边中权值最小的边,并入生成树中
算法执行过程:将连通网中所有的边按照权值大小做升序排序,从权值最小的边开始选择,只要此边不和已选择的边一起构成环路,就可以选择它组成最小生成树。对于 N 个顶点的连通网,挑选出 N-1 条符合条件的边,这些边组成的生成树就是最小生成树。 适用于稀疏图
Dijkstra算法(迪杰斯特拉)从源点出发,每次选择离源点最近的一个顶点前进,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。用于计算图中某一结点到其余顶点的最短路径思路:(1)集合S存放图中一找到最短路径的顶点(2)集合U存放途中剩余顶点。算法执行过程:(1)初始时,S只包含原点,即:S={v},v的距离为0。U包含除v以外的其他顶点。即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。(2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v大k的最短路径长度)。(3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。(4)重复步骤(2)和(3)直到所有顶点都包含在S中。
Floyd算法(弗洛伊德)a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。 b.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。时间复杂度O(n3),空间复杂度O(n2)。算法描述:
(1)从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权值为无穷大。(2)对于每一对顶点u和v,看看是否存在一个顶点w,使得从u到w再到v比已知的路径更短。如果是更新它。(1)Dijkstra算法适用稠密图(邻接矩阵),因为稠密图问题与顶点关系密切;Floyd稠密图、稀疏图都适用;(2)Dijkstra不能处理负权图,Flyod能处理负权图;(3)Dijkstra处理单源最短路径,Flyod处理多源最短路径;
AOV网:一种以顶点表示活动,以边表示活动的先后次序且没有回路的有向图。反映出整个工程中各个活动之间的先后关系的有向图。拓扑算法的核心过程:(1)从有向图中选择一个没有前驱(入度为0)的顶点输出(2)删除1中的顶点,并且删除从该顶点发出的全部边(3)一直重复。若图中没有环的时候,还可采用深度优先搜索遍历的方法进行拓扑排序 比如:一个人早上起来,应该先穿衣服,再穿裤子,最后在带眼镜,也可以先穿裤子,再穿衣服,最后在带眼镜,这两个顺序都是拓扑序列,不唯一。
AOE网:在带权有向图中,若以顶点表示事件,有向边表示活动,边上的权值表示该活动持续的时间
AOV和AOE的区别:相同点:都是无环图。不同点: AOV活动在顶点,边无权值,代表活动之前的先后关系。AOE活动在边,边有权值,代表活动持续的时间。关键路径的核心算法:最大路径长度的路径称为关键路径 关键活动:关键路径上的活动为关键活动,关键活动的最早开始时间等于最晚开始时间。由于AOE网中的某些活动是可以同时发生的,所以完成整个工程的时间应该是从起始点到终点的最大路径长度,关键路径长度即为工程的最短完成时间。AOV网:顶点表示活动,边表示活动之间的先后关系,一般用来表示活动的制约关系;AOE网:边表示活动,边的权值表示活动持续时间,顶点用来表示活动的开始,一般用来分析工程最少需要多少时间完成,或者是工程为缩短时间可以加快哪些活动;
数据结构全书简答题汇总(期末、考研)三万多字
于 2025-01-09 21:44:43 首次发布