python数据结构——二叉排序(搜索)树

概念

二叉排序树很重要的性质就是左子树的内容 小于 根节点 小于 右子树,并且具有递归的性质,也就是每一个子树都满足。

按照这个顺序,我们难免想到中序遍历,因为中序遍历就是左中右的顺序,使得我们的遍历结果为已排序序列
这里不提中序遍历,如果有问题看这里。(C代码,稍微改一下就行)

我们提一下寻找一个结点p的上一个结点和下一个结点的方式(如果没有返回None)。

上一个结点

按照左中右的顺序,如果有左子树,那上一个结点一定在左子树中。
那么应该是哪一个呢? 是左子树遍历的最后一个结点,也就是左子树的最右结点。

如果没有,事情就麻烦了。这时候,和问题相关的就只剩下父亲结点了。
如果没有父亲结点,也就是当前结点为根节点,直接返回none;
否则我们看一下父亲结点和当前结点的关系:

  • 如果当前结点是父亲结点的右孩子,那么父亲结点就是前一个;
  • 如果当前结点是父亲结点的左孩子,那么事情就麻烦了。(注意这里不是没有)

看一下这张图:
在这里插入图片描述
只有这种情况,不过可能没这么好运,上两代就找到了,也可能是n代,也可能找不到。

下一个结点

这个基本上同理,还是有右孩子直接起飞,找到右子树的最左边结点即可。
没有,我们就需要找到一个将这部分当成左子树的祖先结点,和上面的长得差不多。

实现一下
class text(LinkedBinaryTree):
	# 下一个结点
    def after(self,p):
        if self.right(p) is not None:
            # 有右子树
            walk = self.right(p)
            while self.left(walk):
                walk = self.left(walk)
            return walk
        else:
            walk = p
            # 退出条件:祖先结点为空或者是祖先结点的左孩子是walk
            ancestor = self.parent(walk)
            while ancestor is not None and walk == self.right(ancestor):
                walk, ancestor = ancestor, self.parent(ancestor)
            return ancestor

这里提到的LinkedBinaryTree就是一个二叉树,只要支持parent、left和right即可(对于没有的,要置为none)。

相似的,我们就有before函数

    def before(self,p):
        if self.left(p) is not None:
            # 有左子树
            walk = self.left(p)
            while self.right(walk):
                walk = self.right(walk)
            return walk
        else:
            walk = p
            ancestor = self.parent(walk)
            while ancestor is not None and walk == self.left(ancestor):
                walk, ancestor = ancestor, self.parent(ancestor)
            return ancestor

操作

搜索

因为二叉排序树的性质,我们在查找一个元素的时候,只需要和根节点比较即可:

  1. 等于根节点的,不用说就是找到了
  2. 小于根节点的,很明显应该是在左子树上的
  3. 大于根节点,那就是在右子树上

当我们发现要找的左子树/右子树已经为空了,说明是没找到,但是这个地方可不是随便给的。
当我们要进行插入操作,插入的位置就是我们找到的空位置。

代码:

    def TreeSearch(self,T, p, k):
        if k==p.key():
            return p
        elif k<p.key() and T.left(p) is not None:
            return self.TreeSearch(T,T.left(p),k)
        elif k>p.key() and T.right(p) is not None:
            return self.TreeSearch(T,T.right(p),k)
        else:
            return p
插入删除

插入删除的操作,还是要基于查找案来完成的。

插入的话,我们先明白一个事——插入的位置一定是叶子节点。
因为我们已经有了p结点,只需要判断一下是左孩子还是右孩子即可。

删除比较烦,如果是没孩子,直接删;
有一个也不怕,把孩子往上提一下即可;
如果是有两个孩子,就有一点难了,因为要考虑性质,我们有这样两个选择:

  • 将要删除的前一个元素拿出来作为根节点
  • 将要删除的后一个元素拿出来作为根节点

因为拿出来的结点最多有一个子树(这个看上面,都走到最后了),所以只需要提一下即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Python中实现二叉搜索树的代码: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right 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 search(self, val): return self._search(val, self.root) def _search(self, val, node): if not node or node.val == val: return node elif val < node.val: return self._search(val, node.left) else: return self._search(val, node.right) def delete(self, val): self._delete(val, self.root) def _delete(self, val, node): if not node: return node if val < node.val: node.left = self._delete(val, node.left) elif val > node.val: node.right = self._delete(val, node.right) else: if not node.left: temp = node.right node = None return temp elif not node.right: temp = node.left node = None return temp temp = self._get_min_value(node.right) node.val = temp.val node.right = self._delete(temp.val, node.right) return node def _get_min_value(self, node): while node.left: node = node.left return node def inorder_traversal(self): traversal = [] self._inorder_traversal(self.root, traversal) return traversal def _inorder_traversal(self, node, traversal): if node: self._inorder_traversal(node.left, traversal) traversal.append(node.val) self._inorder_traversal(node.right, traversal) ``` 在上面的代码中,我们定义了一个`TreeNode`类来表示二叉的节点,以及一个`BST`类来表示二叉搜索树。`BST`类具有以下方法: - `__init__()`:构造函数,用于初始化根节点为`None`。 - `insert(val)`:插入一个值为`val`的节点到二叉搜索树中。 - `_insert(val, node)`:递归执行插入操作的辅助函数。 - `search(val)`:在二叉搜索树中查找值为`val`的节点。如果找到了,则返回该节点;否则返回`None`。 - `_search(val, node)`:递归执行查找操作的辅助函数。 - `delete(val)`:从二叉搜索树中删除值为`val`的节点。 - `_delete(val, node)`:递归执行删除操作的辅助函数。 - `_get_min_value(node)`:获取以`node`为根节点的子中最小的节点。 - `inorder_traversal()`:对二叉搜索树进行中序遍历,返回遍历结果。 - `_inorder_traversal(node, traversal)`:递归执行中序遍历操作的辅助函数。 以上就是Python中实现二叉搜索树的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值