文章目录
二叉树
二叉树遍历
前序、中序——> 后序
后序、中序——> 前序
![](https://img-blog.csdnimg.cn/ab7201e0abfe47248b55332712032fd4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16)
对于二叉树的前中后序一定要熟悉,算是基本功,图片来源于百度百科。
孩子兄弟表示法
写出二叉树的双亲孩子兄弟表示法的存储结构与过程?
孩子兄弟的结构体类型如下:
typedef struct CSNode {
ElemType data; // 数据域
struct CSNode *firstchild,*nextsibling; // 第一个孩子和右兄弟指针
}CSNode,*CSTree;
这种有个特点就是左节点为孩子,右节点为兄弟即同级节点。只要理解了这个,那么再复杂的树或者森林,都是基于此变化,这里就不再赘述。
平衡二叉树旋转过程
依次把结点(34,23,15,98,115,28,107)插入初始状态为空的平衡二叉排序树,使得在每次插入后保持该树仍然是乎衡二叉树;.,请依次画出每次插入后所形成的平衡二叉排序树。
本题为王道该节第三题,这种题目就一定需要知道平衡二叉的LL旋转,RR旋转,RL旋转与LR旋转,这四个概念在王道上都解释得很清楚了,可以去看一遍做点选择题就有印象了,很可惜,考试那天我忘了,虽然我那个题目是考选择,问旋转次数与每次旋转种类。所以过程如下:
![]() |
![]() |
哈夫曼树的构造
【2012统考真题】设有6个有序表A,B,C,D,E,F,分别含有10,35,40,50,60和200个数据元素,各表中的元素按升序排列。要求通过5次两两合并,将6个表最终合并为1个升序表,并使最坏情况下比较的总次数达到最小,给出完整的合并过程,并求出最坏情况下比较的总次数。
一般哈夫曼树的题目不会明显告诉是要构造这种树形结构,而是需要从题干精炼信息,这题是408原题,同样很明显指明了5次两两合并,6表合并为一个表,我之前有写过一篇关于一次编程笔试题总结里的题,是直接给一个实际例子,然后需要写算法思想和代码,我感觉这样已经超纲了,明明lc medium难度以上的题去手写,很难不让人怀疑是搞事。王道解答为:
![](https://img-blog.csdnimg.cn/0b97bd929b5943fdb596a350eb6f391d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16)
森林、树与二叉树互转
这里王道上面的比较一般,篇幅很小,但对于非408的设计题来讲,是依然可能出大题的。我在process里面找了个开源的已经画好的流程图,最后的参考文献里会标明引用,这里合并截图为:
树转二叉树:
![](https://img-blog.csdnimg.cn/da6a7eb3010748f2ae72f1facfdd3df2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16)
森林转二叉树:
![](https://img-blog.csdnimg.cn/59c8de212d4b4fd09e854772f2019143.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16)
二叉树转树:
![](https://img-blog.csdnimg.cn/cef88d8e5a784ab29d823f9e7684a9c8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16)
二叉树转森林:
![](https://img-blog.csdnimg.cn/a2361786c86944329e303651ac610c65.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16)
图
邻接矩阵、邻接表与图
已知带权有向图G的邻接矩阵如下图所示,请画出该带权有向图G。
[
0
15
2
12
∞
∞
∞
∞
0
∞
∞
6
∞
∞
∞
∞
0
∞
8
4
∞
∞
∞
∞
0
∞
∞
3
∞
∞
∞
∞
0
∞
9
∞
∞
∞
5
∞
0
10
∞
4
∞
∞
∞
∞
0
]
\begin{bmatrix} 0 & 15 & 2 & 12 & \infty & \infty & \infty \\ \infty & 0 & \infty & \infty & 6 & \infty & \infty \\ \infty & \infty & 0 & \infty & 8 & 4 & \infty \\ \infty & \infty & \infty & 0 & \infty & \infty & 3 \\ \infty & \infty & \infty & \infty & 0 & \infty & 9 \\ \infty & \infty & \infty & 5 & \infty & 0 & 10 \\ \infty & 4 & \infty & \infty & \infty & \infty & 0 \end{bmatrix}
0∞∞∞∞∞∞150∞∞∞∞42∞0∞∞∞∞12∞∞0∞5∞∞68∞0∞∞∞∞4∞∞0∞∞∞∞39100
![](https://img-blog.csdnimg.cn/15d6b86ae9a6442b96edc0a9e3c1ec37.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_15,color_FFFFFF,t_70,g_se,x_16)
用process画了半天,发现很难画,想了想还是截图好了。对于邻接表、矩阵与图的互相转换,肯定是知其一解决另外两个,难度不高并且不容易错,因为错了一个可能就不能构成连通图了。
图的深度搜索与广度搜索
下图G=(V,E)以邻接表存储,如下图所示,试画出图G的深度优先生成树和广度优先生成树(假设从结点1开始遍历).
自己尝试画了下,如果用常用的那些软件visio or process确实不好画,除非画得很开,不然容易误触,因为每根竖线都是可编辑的,没法完全固定,另外process数字是镶嵌上去的,visio应该不会有这问题。
这里的邻接表与王道有不同地方在于,单节点有两个数据,因为王道上对于无权图的邻接表只存一个数据,即相连的点,有权图才在第二个位置写权值,但是统一写更好,不会记混,写无穷、0或者空着都没影响。关于深搜和广搜,也经常是选择题重点,普遍选择比大题难,设计题里只要出现肯定就是一起的。
Prim算法与Kruskal算法
这两种算法原理推荐:最小生成树-Prim算法和Kruskal算法
![](https://img-blog.csdnimg.cn/afa41b25978b41a8967540116bb3a070.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16)
直接看第四问,kruskal和prim的区别,我感觉就是一个是按点出发,从一个点,按广度搜索最小边然后一一连起来,而kruskal是按边,以最小边出发,若是选定的边上点没有入度,即没有连线,那么这条边就可以作为该算法的过程。
![](https://img-blog.csdnimg.cn/fbc1263400414a1aac1b5831779009c3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16)
可能标的不是很清晰,原书上就是这样,所以:
Kruskal具体路径为1—2、1—3,3—6,5—7,3—5,6—4
Prim算法具体路径为:1—2、1—3,3—6,3—5、5—7,6—4
关于prim,找到一个模板,比书上要清晰明了,为:
![](https://img-blog.csdnimg.cn/e46698d7559b42dfa3f5c3ae213616c6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3VibWFyaW5lYXM=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
最短路径与AOE网(Activity on edge network)
下表给出了某工程各工序之间的优先关系和各工序所需的时间(其中“一”表示无先驱工序),请完成以下各题:
- 画出相应的AOE网
- 列出各事件的最早发生时间和最迟发生时间.
- 求出关键路径并指明完成该工程所需的最短时间.
工序代号 | A | B | C | D | E | F | G | H |
---|---|---|---|---|---|---|---|---|
所需时间 | 3 | 2 | 2 | 3 | 4 | 3 | 2 | 1 |
先驱工序 | — | — | A | A | B | A | C、E | D |
这里只要注意好先驱工序也就是结点对应关系就好了,括号里的无先驱的A与B,其实就是选定的点能直接到它们的意思。
2)求解各事件和活动的最早发生时间与最迟发生时间公式在引用中提到,事件 v i v_i vi的最早发生时间为:
v e ( i ) = M a x { v e ( k ) + d u t ( < k , j > ∈ ) ∣ < k , j > T , 1 ≤ i ≤ n − 1 } ve(i)=Max\{ve(k)+dut(<k,j>\in)| <k,j>T,1 \leq i \leq n-1\} ve(i)=Max{ve(k)+dut(<k,j>∈)∣<k,j>T,1≤i≤n−1}
事件 v i v_i vi的最晚发生时间为:
v l ( i ) = M i n { v l ( k ) − d u t ( < i , k > ) ∣ < i , k > ∈ S , 0 ≤ i ≤ n − 2 } vl(i)=Min\{vl(k)-dut(<i,k>)|<i,k>\in S,0 \leq i \leq n-2\} vl(i)=Min{vl(k)−dut(<i,k>)∣<i,k>∈S,0≤i≤n−2}
通俗理解,就是最早发生时间是从起点往终点推,即到每个事件结点所需最长的时间,比如V4点,从V1—V2—V4的距离是5,而V1—V3—V4所需距离是6,那么V4的最短时间为6,选长的确保都能完成;最迟发生时间就是从终点往起点推,比如V6点,从V1—V3—V5—V6需要7,而V1—V3—V6只需要6,那么最迟发生时间为7。
所以可得到结果为:
v 1 v_1 v1 | v 2 v_2 v2 | v 3 v_3 v3 | v 4 v_4 v4 | v 5 v_5 v5 | v 6 v_6 v6 | |
---|---|---|---|---|---|---|
v e ( i ) v_e(i) ve(i) | 0 | 3 | 2 | 6 | 6 | 8 |
v l ( i ) v_l(i) vl(i) | 0 | 4 | 2 | 6 | 7 | 8 |
3)如果前面两问没问题,那么第三问各活动最早发生时间 e e e、最迟发生时间1和时间余址 d ( i ) = l ( i ) − e ( i ) d(i)=l(i)- e(i) d(i)=l(i)−e(i)如下:
A | B | C | D | E | F | G | H | |
---|---|---|---|---|---|---|---|---|
e ( i ) e(i) e(i) | 0 | 0 | 3 | 3 | 2 | 3 | 6 | 6 |
l ( i ) l(i) l(i) | 1 | 0 | 4 | 4 | 2 | 5 | 6 | 7 |
l ( i ) − e ( i ) l(i)-e(i) l(i)−e(i) | 1 | 0 | 1 | 1 | 0 | 2 | 0 | 1 |
所以关键路径为B、E、G,完成该工程最少需要8。
查找
折半查找
设有序顺序表中的元素依次为017,094,154,170,275,503, 509,512,553,612,677,765,897,908.
- 试画出对其进行折半查找的判定树.
- 若查找275或684的元素,将依次与表中的哪些元素比较?
- 计算查找成功的平均查找长度和查找不成功的平均查找长度.
本题难度不大,主要需要注意的是计算,折半查找又叫做二分查找,刷lc题会经常遇见,这些的前提是数组或者顺序表必须有序。
B树与B+树
原理:mysql索引全解
给定一组关键字{20,30,50,52,60,68,70},给出创建一棵3阶B树的过程。
B树与B+出设计题概率不大,主要偏向于选择,也是选择题难度会大于大题,上面我引用的那篇原理也是之前学mysql索引写的,因为在找资料的时候,基本上谈及B树,就绕不开mysql索引,深点就是磁盘I/O,以及底层引擎,考试只会考虑过程。
散列查找与性能分析
原理:Hash详解
散列表一般分为两个部分,一个是散列函数的构造,一个是在构造完成后处理冲突的方法,前者常用方法有直接定址法、除留余数法、数字分析法和平方取中法,但这只是常用类型,作为设计题来讲,我遇到的恶心的真的就构造一个函数开根号了,没计算器就是折磨了,也幸好不是立方以上,这点如果非408想恶心人的话,可能是数据结构里唯一一个需要带计算器的地方。
后者处理冲突的方法统称为开放定址法和拉链法,开放定址法其中常用的有一次探测法(线性探测),二次探测法(平方探测),再散列法和伪随机序列法,这里一般常考前面两种,具体使用场景,王道有提过,比如说人的身份证信息,长但是有规律,每段代表具体含义,这种一般用平方取中更为合适。后两种我没过多了解,再散列法我感觉除了做题毫无意义,因为时间复杂度过于大,而且很浪费资源。真要出题就是搞人心态,跟直接抄lc medium以上原题一样恶心。
开放定址法与拉链法的区别在于经常进行插入和删除的情况。而关于散列查找,还需要了解一下装填因子的概念,散列表的装填因子一般记为
α
α
α,定义为一个表的装满程度,即:
α
=
表中记录数
n
散列表长度
m
α = \frac{表中记录数n}{散列表长度m}
α=散列表长度m表中记录数n
题目为:
【2010统考真题】将关键字序列(7,8,30,11,18,9,14)散列存储到散列表中。散列表的存储空间是一个下标从0开始的一维数组,散列函数为H(key) =(key× 3)MOD 7,处理冲突采用线性探测再散列法,要求装填(载)因子为0.7.
- 请画出所构造的散列表。
- 分别计算等概率情况下,查找成功和查找不成功的平均查找长度。
排序
排序概念总结
![]() |
![]() |
很久之前画的排序图,顺便跟书上排序性质结合,本来是弄到一张图里,但是process这功能需要开通VIP,所以只能手动HTML。。确实有点丑,mark一下,之后remake。
关于排序这一章,如果出设计题,最可能的是希尔、快速排序以及堆排序,而希尔更大可能考代码加设计,快排一般与其它算法一起考代码,比如说贪心+快排,堆就是大根堆与小根堆,只要了解整个过程,不要记混,从设计题来讲,就是常规题了,下面会介绍快排与堆。
快速排序
快排原理:面试常用排序算法总结
上面那篇引用大概很久之前写的,写这篇的时候突然想到,然而刷王道的时候感觉已经完全不记得了。。不过没什么关系,这些东西本来就是硬刷,快排特别需要注意的是枢轴选定,起始可以是任意一个,也就是上图中的base作为第一轮,当第一轮结束后,枢轴元素已经确定,那么对两边元素,取中间的枢轴进行第二轮,直到集合为2与3时,即为最后一轮。
快排在划分算法中,若右端区间有两个关键字相同,且均小于基准值的记录,则在交换到左端区间后,它们的相对位置会发生变化,即快速排序是一种不稳定的排序方法。例如,集合L{3,2,2},经过一趟排序后L={2,2, 3},最终排序序列也是L={2,2,3},显然,2与2的相对次序己发生了变化。
题目:
已知关键字集合{11,2,16,30,8,28,4,9,20,17}。
-
若采用快速排序,且关键字按非递增排序,请给出以最后一个关键字为枢轴的第一趟排序结果。
-
若采用小根堆排序,请以完全二叉树的形式画出初始建堆的结果。
此题为2021年某自命题10分的题,第一问答案为{20,28,30,17,16,8,2,4,9,11},需要注意的是题目给出的非递增排序,意思就是递减排序,那么low指针开始指向11向右走,指向元素如果比17小,则需交换,而high指针开始指向20向左走,指向元素比17大,则需交换,否则指针+1。这里本来是想做一个动态图解析,但是在线网站好像只能是递增+首元素的,就如果说对于{17,11,2,16,30,8,28,4,9,20}进行排序,第一轮的动态图为:
网址:https://visualgo.net/en
对于第二问,需要注意的是建堆,答案为:
堆排序
这里我也没找到什么比较好的题,上面那篇中的图和代码我觉得对于理解堆来讲,基本就已经够了。
Reference
[1]. 2022王道考研系列数据结构复习指导