BFS,DFS,以及图(Graph),树(Tree)的思考(4)

计算机中的树(2)

总目录传送门:

BFS,DFS,以及图(Graph),树(Tree)的思考_PigeonEssence的博客-CSDN博客最近刷leetcode发现了很多题有使用到树,图,dfs和bfs,回想当时在离散数学,图论,还有数据结构的课上都有讨论过这方面的问题,于是就想尽自己的力去总结一份文档分享出来,也方便自己需要的时候查阅。个人理解可能并不准确,如有问题请联系修改。 这里做个目录吧: 1.图论中图的基础定义: BFS,DFS,以及图(Graph),树(Tree)的思考(1)_PigeonEssence的博客-CSDN博客我们在算法题以及很多算法理论中,经常会讨论到DFS和BFS算...https://blog.csdn.net/m0_56289903/article/details/121270356?spm=1001.2014.3001.5502

目录

计算机中的树(2)

二叉查找树(Binary Search Tree):

平衡二叉树(ALV Tree):


从二叉查找树到二叉平衡树

二叉查找树(Binary Search Tree):

        二叉搜索树就是在二叉树的基础上,固定了数据存入的顺序,我们固定左边子树小于根节点,右边子树大于根节点,存入的时候排好顺序,那么我们搜索的速度就会加快很多了。而且不仅搜索,还支持快速插入和删除数据

二叉搜索树有以下特点:

  1. 若任意节点的左⼦树不空,则左⼦树上所有结点的值均⼩于它的根结点的值; 


  2. 若任意节点的右⼦树不空,则右⼦树上所有结点的值均⼤于它的根结点的值; 


  3. 任意节点的左、右⼦树也分别为⼆叉查找树

        我们从root节点:27来看,27的左子树都是小于27的,右子树都是大于27的,他的左子树和右子树也都是二叉查找树。我们就说这个树是一个二叉查找树。

        这样的好处是什么呢?这就解决了一个搜索的无序性问题,我们要搜索一个数,只需要对当前节点的大小与目标值进行判断,首先判断是否相等,然后判断大于就递归查询右子树,小于就遍历查询左子树,大大的减少了搜索的O。

        但是二叉查找树会不会存在一种特殊情况呢?当二叉查找树处于链状结构的时候,他的搜索又会回到遍历链表的情况:

        如果我们对一个二叉搜索树进行了操作,导致其成为上图的链状结构的时候,我们会发现,这个树满足二叉树的所有定义,但是他的O还是达到了O(n),也就是遍历链表。因此,在二叉查找树的基础上,又出现了AVL树,红黑树,它们两个都是基于二叉查找树,只是在二叉查找树的基础上又对其做了限制.  

平衡二叉树(ALV Tree):

        AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1。不管我们是执行插入还是删除操作只要左右子树树高超过了1,我们就要通过旋转来保持平衡。所以这种数据结构一般用于删除增加较少,查询较多的情况完全平衡的状态下,最好的情况是 O(logn)。

        平衡的定义是说从空链接到根节点距离相等

平衡二叉树中一个重要的概念就是左旋和右旋:

        右旋的基本实现就是,当成为一个连续左链(左子树树高超过了1)的情况下,用自己的左子节点代替自己的位置,然后自己变成右子节点:

假设我们有一个树,节点是2-3:

        

 这时我们需要插入一个新节点1:

 此时1-3的高超过了1,所以右旋:用2代替3的位置,3变成2的右子节点:

 左旋也是相同的道理,我们在上图中插入4和5:

 1节点和节点3的高度相差超过了1,所以我们用4代替3的位置,然后3变成4的左子节点:

 那么我再继续插入6会出现什么情况呢:

 很明显节点2的左子树右子树的高度相差超过了1,所以左旋(注意2-4-3),用4代替2的位置,3变成2的右子节点:

 继续插入7:

 很明显需要左旋来达到平衡:

 这时候如果我们先插入10,再插入9会变成什么样呢:也就是先查大的,再插相对小的

 这个结构和我们之前看到的是不同的,所以这种情况我们需要进行两次旋转:

我们首先主要这三个节点,这种降低高度很明显需要变成下图:

 所以我们需要先右旋用9代替10的位置,然后10变成9的右子节点:

 然后再左旋,用9代替7的位置,7变成9的左子节点,就得到了上面我们想要的形态:

 这时候整体图变成了:

 结合上图总结一下规律:

插入方式描述旋转方式
LL在a的左子树根节点的左子树上插入节点而破坏平衡右旋转
RR在a的右子树根节点的右子树上插入节点而破坏平衡左旋转
LR在a的左子树根节点的右子树上插入节点而破坏平衡先左旋后右旋
RL在a的右子树根节点的左子树上插入节点而破坏平衡先右旋后左旋

        这就是平衡二叉树的基本性质与平衡方法。但是我们也可以明显的发现,AVL树为了实现完全的平衡,他的旋转操作很多,所以增加和删除的性能损耗就会很大。所以红黑树作为新的数据结构,就是用来处理插入和删除相对较多的情况下的使用。

好的,针对您的问题,我会分别介绍DFP算法BFS算法来构造给定简单的生成。 首先来介绍DFP算法,也称为深度优先搜索算法。该算法的基本思路是从任一顶点开始深度优先遍历,对于每一个未被访问的顶点,选择一个它的邻接顶点进行递归遍历,直到所有的顶点都被访问到为止。在遍历的过程中,可以维护一个父节点数组,记录每一个节点的父节点,就可以构建出生成。 下面是DFP算法构造生成的示例代码: ```python def dfs(u, parent, graph, visited): visited[u] = True for v in graph[u]: if not visited[v]: parent[v] = u dfs(v, parent, graph, visited) def construct_tree_by_dfs(graph): n = len(graph) parent = [-1] * n visited = [False] * n for i in range(n): if not visited[i]: dfs(i, parent, graph, visited) return parent ``` 接下来介绍BFS算法,也称为广度优先搜索算法。该算法的基本思路是从任一顶点开始广度优先遍历,对于每一个未被访问的顶点,选择一个它的邻接顶点加入队列,直到所有的顶点都被访问到为止。在遍历的过程中,同样可以维护一个父节点数组,记录每一个节点的父节点,就可以构建出生成。 下面是BFS算法构造生成的示例代码: ```python def bfs(start, parent, graph, visited): queue = [start] visited[start] = True while queue: u = queue.pop(0) for v in graph[u]: if not visited[v]: visited[v] = True parent[v] = u queue.append(v) def construct_tree_by_bfs(graph): n = len(graph) parent = [-1] * n visited = [False] * n for i in range(n): if not visited[i]: bfs(i, parent, graph, visited) return parent ``` 以上就是使用DFP算法BFS算法分别构造生成的示例代码。需要注意的是,这里的代码是针对无向无权的,如果是有向或带权,需要对代码进行相应的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

PigeonEssence

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值