首页 > 其他分享 >二叉搜索树

二叉搜索树

时间:2023-01-12 12:55:57浏览次数:40  
标签:node lchild self 二叉 搜索 rchild pointer 节点

1. 二叉搜索树

  二叉搜索树又称二叉排序树,他的左子树上的节点都小于根节点,他的右子树上的节点都大于根节点,每一个左右子树又是一个二叉搜索树

  

 

2. 删除节点的几种情况:

   

 

 3. 二叉搜索树的实现:

# 构建节点类
class BiTreeNode:
    def __init__(self, item):
        self.item = item
        self.lchild = None  # 左孩子
        self.rchild = None  # 右孩子
        self.parent = None  # 父节点
# 二叉搜索树类
class BiSelectTree:
    def __init__(self, li=None):
        self.root = None    # 根节点默认为空
        # 如果传入参数,则调用非递归插入节点
        if li:
            for val in li:
                self.insert_no_rec(val)

    # 递归插入
    def insert(self, node, val):
        # 判断是否存在根节点,不存在直接插入无需判断
        if not node:
            node = BiTreeNode(val)
        # 如果元素小于当前指针指向节点,则插入当前节点的左孩子处
        elif val < node.item:
            node.lchild = self.insert(node.lchild, val)
        # 如果元素大于当前指针指向节点,则插入当前节点的右孩子处
        elif val > node.item:
            node.rchild = self.insert(node.rchild, val)
        return node

    # 非递归插入
    def insert_no_rec(self, val):
        # 构建指针
        pointer = self.root
        # 如果输为空,则直接插入节点
        if not pointer:
            self.root = BiTreeNode(val)
            return
        # 重复循环
        while True:
            # 当插入元素小于指针指向节点时
            if val < pointer.item:
                if pointer.lchild:      # 如果存在左孩子时,则指针指向下一层
                    pointer = pointer.lchild
                else:
                    pointer.lchild = BiTreeNode(val)    # 不存在左孩子,直接插入元素至左孩子处
                    pointer.lchild.parent = pointer     # 插入元素的父节点指向指针所在元素
                    return
            # 当插入元素大于指针指向节点时
            elif val > pointer.item:
                if pointer.rchild:      # 如果存在右孩子时,则指针指向下一层
                    pointer = pointer.rchild
                else:
                    pointer.rchild = BiTreeNode(val)    # 不存在右孩子,直接插入元素至左孩子处
                    pointer.rchild.parent = pointer     # # 插入元素的父节点指向指针所在元素
                    return
            else:
                return

    # 递归查询
    def query(self, node, val):
        # 传入的二叉树如果为空树,则直接返回None
        if not node:
            return None
        # 如果查询的元素小于当前的节点,则递归传入左孩子作为根节点继续查询
        if val < node.item:
            return self.query(node.lchild, val)
        # 如果查询的元素大于当前的节点,则递归传入右孩子作为根节点继续查询
        elif val > node.item:
            return self.query(node.rchild, val)
        # 等于时输出
        else:
            return node

    # 非递归查询
    def query_no_rec(self, val):
        pointer = self.root         # 指针指向当前根节点
        while pointer:              # 如果存在指针元素
            if val > pointer.item:          # 如果查询元素大于指针指向节点,则指针进入右孩子层
                pointer = pointer.rchild
            elif val < pointer.item:        # 如果查询元素小于指针指向节点,则指针进入左孩子层
                pointer = pointer.lchild
            else:
                return pointer        # 等于直接输出
        return None         # 不存在指针,说明到底了

    # 删除节点
    # 情况1:删除的是叶子节点,即没有子节点的节点
    def remove_node_1(self, node):
        # 如果删除节点时根节点,则变成一棵空树
        if not node.parent:
            self.root = None
        # 如果删除元素node是它父节点的左孩子
        elif node == node.parent.lchild:
            node.parent.lchild = None
        # 如果删除元素node是它父节点的右孩子
        else:
            node.parent.rchild = None

    # 情况2:删除节点只有一个左孩子
    def remove_node_2(self, node):
        # 如果删除的是根节点,那他的左孩子为根节点
        if not node.parent:
            self.root = node.lchild
            node.lchild.parent = None
        # 删除节点是它父节点的左孩子,它只有一个左孩子
        elif node == node.parent.lchild:
            node.parent.lchild = node.lchild
            node.lchild.parent = node.parent
        # 删除节点是它父节点的右孩子,它只有一个左孩子
        else:
            node.parent.rchild = node.lchild
            node.lchild.parent = node.parent

    # 情况3:删除节点只有一个右孩子
    def remove_node_3(self, node):
        # 如果删除的是根节点,则他的右孩子为根节点
        if not node.parent:
            self.root = node.rchild
            node.rchild.parent = None
        # 删除节点是它父节点的左孩子,但它只有一个右孩子
        elif node == node.parent.lchild:
            node.parent.lchild = node.rchild
            node.rchild.parent = node.parent
        # 删除节点是它父节点的有孩子,但他只有一个左孩子
        else:
            node.parent.rchild = node.rchild
            node.rchild.parent = node.parent

    def delete(self, val):
        # 不为空树,执行查找元素
        if self.root:
            node = self.query_no_rec(val)   # 查询到该节点
            # 当node不存在
            if not node:
                return False
            # 当它没有左孩子和右孩子,即叶子节点,符合情况1
            if not node.lchild and not node.rchild:
                self.remove_node_1(node)
            # 如果只有一个左孩子,符合情况2
            elif not node.rchild:
                self.remove_node_2(node)
            # 如果只有一个右孩子,符合情况3
            elif not node.lchild:
                self.remove_node_3(node)
            # 如果左右孩子都存在,方法一:将有孩子集合中最小的节点提至删除节点处
            else:
                min_node = node.rchild      # 取删除节点的有孩子
                while min_node.lchild:      # 当它存在左孩子时,说明该节点不是最小节点
                    min_node = min_node.lchild  # 在进入下一层,指向它的左孩子
                node.item = min_node.item       # 如果没有左孩子,说明该节点是最小的,将删除的节点等于右最小节点
                # 删除该最小节点,两种情况:只有一个右孩子和叶子节点
                if min_node.rchild:         # 只有一个右孩子时,符合第三章情况
                    self.remove_node_3(min_node)
                else:
                    self.remove_node_1(min_node)    # 叶子节点,符合第一种情况

    # 前序遍历
    def pro_order(self, root):
        if root:
            print(root.item,end=',')
            self.pro_order(root.lchild)
            self.pro_order(root.rchild)

    # 中序遍历
    def cen_order(self, root):
        if root:
            self.cen_order(root.lchild)
            print(root.item, end=',')
            self.cen_order(root.rchild)

    # 后续遍历
    def later_order(self, root):
        if root:
            self.later_order(root.lchild)    # 先找左边的子节点
            self.later_order(root.rchild)   # 在找优点的子节点
            print(root.item, end=',')

tree = BiSelectTree([4,3,6,9,1,2,5,8])

 

标签:node,lchild,self,二叉,搜索,rchild,pointer,节点
From: https://www.cnblogs.com/chf333/p/17046321.html

相关文章

  • 算法刷题 Day 15 | 层序遍历 226.翻转二叉树 101. 对称二叉树
    今日内容:层序遍历10翻转二叉树对称二叉树2层序遍历看完本篇可以一口气刷十道题,试一试,层序遍历并不难,大家可以很快刷了十道题。题目链接/文章讲解/视......
  • 【BFS】LeetCode 297. 二叉树的序列化与反序列化
    题目链接297.二叉树的序列化与反序列化思路代码classCodec{//Encodesatreetoasinglestring.publicStringserialize(TreeNoderoot){i......
  • CQF学习笔记M1L2二叉树模型
    https://blog.csdn.net/weixin_42859140/article/details/107018914?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCo......
  • 74. 搜索二维矩阵
    问题链接https://leetcode.cn/problems/search-a-2d-matrix/description/解题思路我们可以确定,数据是有序的。所以我们有2种办法用二分来解决。第一种,我们可以写个下标......
  • 双系统开机直接进入ubuntu界面,搜索不到Windows启动项
    原因为止,确定是由ubuntu更新导致的结果解决方法执行命令sudorm/etc/grub.d/20_memtest86+删掉文件输入命令sudovim/etc/default/grub修改此配置文件,加入GRUB_DISAB......
  • 洛谷P1040. 加分二叉树
    题目描述设一个\(n\)个节点的二叉树tree的中序遍历为(\(1,2,3,…,n\)),其中数字\(1,2,3,…,n\)为节点编号。每个节点都有一个分数(均为正整数),记第\(i\)个节点的分数......
  • 33. 搜索旋转排序数组
    问题链接https://leetcode.cn/problems/search-in-rotated-sorted-array/description/解题思路这个题目要求复杂度了。我们不要慌,首先分析一下数据。也就是说,这个数组......
  • 列表form搜索参数的细节
    像这样,有form的列表页。需求要加一个搜索组件,这个form的method最好用get,而不是post。因为如果用post,点了返回,会出现此网页需要使用您之前输入的数据才能正常显示。您可以重......
  • 二叉搜索树
    性质二叉搜索树是一种具有以下性质的树:如果左子树不为空的话,左子树的所有节点的值都小于根节点的值如果右子树不为空的话,右子树的所有节点的值都大于根节点的值他的左......
  • pdd商品列表接口,PDD商品详情接口,关键词搜索pdd商品接口代码展示
    前言item_search-根据关键词取商品列表接口,可以通过关键词搜索请求接口拿到商品列表页面的商品标题,商品价格,商品优惠价,商品视频,商品图片,商品sku属性,商品sku属性描述,发货地,库......