一文读懂什么是二叉搜索树(BST)、中序遍历、前序遍历、后序遍历

什么是二叉搜索树(BST)?


其实这个概念非常简单,二叉树里每个节点都是一个爸爸,每个爸爸有两个儿子
而二叉“搜索”树就是要满足一个额外的条件:所有左儿子的数字都比爸爸数字小,所有右儿子的数字都比爸爸数字大。
示例:
屏幕快照 2020-07-03 下午12.04.44.png
(图源:力扣(LeetCode))
我们可以很容易看见,每个爸爸节点分出来的左边部分里,任何一个数字都比这个爸爸数字小;右边部分里,任何一个数字都比这个爸爸数字大。

至于为什么叫二分“搜索”树,我的理解是这样的:
比如我们玩一个游戏,我心里想一个数字,你要猜这个数字是什么,那你可以用这样一棵搜索树,从最顶上的父节点开始,每次问我,“你想的数字比当前节点大还是小?”,你就可以一步步顺着树往下走,搜索到我心里想的数字。所以这就是一个搜索的过程,是一个不断缩小搜索范围的过程。

言归正传,为什么我们已经满足了题目二分搜索树的条件,因为题目一开始就给了我们一个有序的数列,你每次在中间取一个爸爸,爸爸的左边部分必定小于爸爸数,右边部分也必定大于爸爸树。

什么是中序遍历?

“前序遍历”、“中序遍历”、“后序遍历”里说的遍历,实际上是我们遍历二叉树的方式
其实一张图就能给你解释什么叫中序遍历:
(其中,箭头表示遍历顺序。二叉树本身的箭头没画。)
在这里插入图片描述

我们发现,这个“前”、“中”、“后”其实指的就是ROOT在遍历当中的位置嘛,左右两部分一直都是从左到右。

比如中序遍历的过程,我们来看一个例子:
如下一棵随便画的二叉树,搞得很丑但我不管:
在这里插入图片描述

注意,遍历的时候,记住一个关键点:我们遍历的是树而不是节点
这么说有点抽象,具体一点说:每次遍历的时候,要把子树看成一个整体,
比如我们来看一个最大的格局:爸爸节点是1号,那么左子树是2、4、5、7、8整个整体,右子树是3、6、9、10整个整体,
在这个最大格局上进行遍历,那就是左子树整体->1号->右子树整体

所以我们现在知道要从左子树开始,那么左子树也要遵循中序遍历,所以顺序应该是
4、7整体 -> 2 -> 5、8整体

然后进入1

然后进入右子树,右子树也遵循中序遍历:
空白(3开头的右子树并没有左边部分) -> 3 -> 6、9、10整体

依此类推,如果你能理解完整的顺序:
4、7、2、8、5、1、3、9、6、10
说明你已经理解了中序遍历,记住每次进入一个子树的时候,不要急着先遍历这个子树的爸爸,每个子树也都是要从左边开始才能是中序遍历的!

如果用前序、后序遍历这棵树呢?

其实是一样的道理,只要每次遵循前序、后序遍历的规则,而不是用中序的规则而已。
前序:1、2、4、7、5、8、3、6、9、10
后序:7、4、8、5、2、9、10、6、3、1

好的,我可以帮你解决这些问题。以下是代码实现: ```python class TreeNode: def __init__(self, val=None): self.val = val self.left = None self.right = None class BST: def __init__(self): self.root = None def insert(self, val): if not self.root: self.root = TreeNode(val) else: self._insert(val, self.root) def _insert(self, val, node): if val < node.val: if not node.left: node.left = TreeNode(val) else: self._insert(val, node.left) else: if not node.right: node.right = TreeNode(val) else: self._insert(val, node.right) def inorder_traversal(self): if not self.root: return [] else: return self._inorder_traversal(self.root) def _inorder_traversal(self, node): res = [] if node: res = self._inorder_traversal(node.left) res.append(node.val) res = res + self._inorder_traversal(node.right) return res def search(self, val): if not self.root: self.root = TreeNode(val) else: self._search(val, self.root) def _search(self, val, node): if val < node.val: if not node.left: node.left = TreeNode(val) else: self._search(val, node.left) elif val > node.val: if not node.right: node.right = TreeNode(val) else: self._search(val, node.right) def postorder_traversal(self): if not self.root: return [] else: return self._postorder_traversal(self.root) def _postorder_traversal(self, node): res = [] if node: res = self._postorder_traversal(node.left) res = res + self._postorder_traversal(node.right) res.append(node.val) return res def __del__(self): self._delete_tree(self.root) def _delete_tree(self, node): if node: self._delete_tree(node.left) self._delete_tree(node.right) print("Deleting node:", node.val) del node ``` 代码的解释: - `TreeNode` 类定义了二叉树节点的结构,包含一个值和左右子节点。 - `BST` 类定义了二叉排序树,包含一个根节点。它实现了插入节点、中序遍历、搜索节点、后序遍历和释放二叉树的功能。 - `_insert` 方法是一个递归方法,用于将新节点插入到二叉排序树中。 - `inorder_traversal` 方法实现了中序遍历,并返回遍历结果。 - `_search` 方法是一个递归方法,用于搜索二叉排序树中是否存在指定值的节点。如果不存在,则将新节点插入到二叉排序树中。 - `postorder_traversal` 方法实现了后序遍历,并返回遍历结果。 - `_delete_tree` 方法是一个递归方法,用于释放整个二叉排序树。它依次删除每个节点,并输出节点的值。 以下是测试代码: ```python bst = BST() # 插入节点 bst.insert(5) bst.insert(2) bst.insert(8) bst.insert(1) bst.insert(4) bst.insert(7) bst.insert(9) # 中序遍历 print("Inorder Traversal:", bst.inorder_traversal()) # 搜索节点 bst.search(6) bst.search(3) # 中序遍历 print("Inorder Traversal:", bst.inorder_traversal()) # 后序遍历 print("Postorder Traversal:", bst.postorder_traversal()) # 释放二叉排序树 del bst ``` 输出结果: ``` Inorder Traversal: [1, 2, 4, 5, 7, 8, 9] Inorder Traversal: [1, 2, 3, 4, 5, 6, 7, 8, 9] Postorder Traversal: [1, 4, 2, 7, 9, 8, 5] Deleting node: 1 Deleting node: 4 Deleting node: 2 Deleting node: 7 Deleting node: 9 Deleting node: 8 Deleting node: 5 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值