IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> [数据结构] python 二叉搜索树(BST树)的插入 -> 正文阅读

[数据结构与算法][数据结构] python 二叉搜索树(BST树)的插入

一、概念

二叉搜索树(Binary Search Tree)是一颗二叉树且满足性质:设x是二叉树的一个节点。如果y树x左子树的一个节点,那么y.key\leq x.key;如果y是x右子树的一个节点,那么y.key\geq x.key

用通俗一点的话来说就是在一棵二叉树中,左子树所有节点都比它的根节点小,右子树所有节点都比它的根节点大。(如图所示)

所以当我们要定义一个BST树时,用双链表来做就要想到要初始化的东西:

1. 数据域data 0

2. 树的左孩子和右孩子(lchild/rchild)?

3. 他们的双亲parent

定义BST树代码如下:

class BSTreeNode:
    def __init__(self):
        self.data=data
        self.lchild=None    #左孩子
        self.rchild=None     #右孩子
        self.parent=None

?二、搜索二叉树的插入

递归插入代码思路:

1. 判断当前节点是否为空,是的话就直接插入结点

2. 如果当前节点不为空,则有三种判断

当前节点大于插入的结点,插入的结点应放在当前结点的左边

当前节点小于插入的结点,插入的结点应放在当前节点的右边

当前节点等于插入的结点,这个代码可以不执行,可以不写,如果想优化代码可以写如果当前及诶点等于插入的结点会怎样怎样

3. 最后别忘了绑定要插入的结点的双亲

代码如下:

# 递归插入函数 node结点位置 val为要插入的结点
def insert(self, node, val):
    # 如果node是空,有空间,可直接插入结点
    if not node:
        node = BSTreeNode(val)
    # 如果node不为空则有两种判断 插入的结点值小于(大于)node结点值
    elif val < node.data:
        node.lchild = self.insert(node.lchild, val)  # 递归查空左孩子,给左孩子赋值
        node.lchild.parent = node  # 绑定左孩子的双亲
    elif val > node.data:
        node.rchild = self.insert(node.rchild, val)
        node.rchild.parent = node
        # 其实这里还有一个else val=node.data , 这个默认我们找到了就不找了,所以不做什么回应
        # 如果想优化代码可以写上else
    return node

非递归插入代码思路如下:

1. 定义一个变量来保存这棵树的根

2. 判断该树是否为空,判断方法为判断根是否存在,如果是空,直接将要插入的结点插入根节点

3. 不是空树,则有三种判断

当前节点大于根节点,插入的结点应放在根节点的左边,所以要判断根节点有没有左子树,有左子树的话就再找它的左子树的下一个左子树,直到找到空节点进行插入

当前节点小于根节点,插入的结点应放在根节点的右边,所以要判断根节点有没有右子树,有右子树的话就再找它的右子树的下一个右子树,直到找到空节点进行插入

当前节点等于插入的结点,代码可以不写,也可以写,这里不写

代码如下:

def insert_not_rec(self,val):
    p=self.root
    #如果树是空树
    if not p:
        self.root=BSTreeNode(val)
        return
    #递归函数中因为直接判断是空树就直接返回了,不用特殊处理,但是这里需要特殊处理,因为这里不是递归
    # 如果不是空树:
    while True:
        if val<p.data:
            # 判断左子树是否为空,是空就直接插入,不是空就往下一个左子树找空间
            if p.lchild:  #如果存在左子树,左子树不为空
                p=p.lchild
            else:
                p.lchild=BSTreeNode(val)
                p.lchild.parent=p
                return
        elif val>p.data:
            if p.rchild: #如果存在右子树,右子树不为空
                p=p.rchild
            else:
                p.rchild=BSTreeNode(val)
                p.rchild.parent=p
                return
        else: #如果val=p.data
            return

总体代码如下:

因为递归执行效率较慢,所以改代码使用非递归执行,因为再创建了另一个类,所以需要初始化一下树的根

class BSTreeNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None  # 左孩子
        self.rchild = None  # 右孩子
        self.parent = None


class BST:
    # 初始化树的根
    def __init__(self,li=None):
        self.root = None
        if li:
            for val in li :
                self.insert_not_rec(val)

    # 递归插入函数 node结点位置 val为要插入的结点
    def insert(self, node, val):
        # 如果node是空,有空间,可直接插入结点
        if not node:
            node = BSTreeNode(val)
        # 如果node不为空则有两种判断 插入的结点值小于(大于)node结点值
        elif val < node.data:
            node.lchild = self.insert(node.lchild, val)  # 递归查空左孩子,给左孩子赋值
            node.lchild.parent = node  # 绑定左孩子的双亲
        elif val > node.data:
            node.rchild = self.insert(node.rchild, val)
            node.rchild.parent = node
        # 其实这里还有一个else val=node.data , 这个默认我们找到了就不找了,所以不做什么回应
        # 如果想优化代码可以写上else
        return node

    # 非递归插入函数 参数只需要一个插入的结点
    def insert_not_rec(self,val):
        p=self.root
        #如果树是空树
        if not p:
            self.root=BSTreeNode(val)
            return
            #递归函数中因为直接判断是空树就直接返回了,不用特殊处理,但是这里需要特殊处理,因为这里不是递归
        # 如果不是空树:
        while True:
            if val<p.data:
                # 判断左子树是否为空,是空就直接插入,不是空就往下一个左子树找空间
                if p.lchild:  #如果存在左子树,左子树不为空
                    p=p.lchild
                else:
                    p.lchild=BSTreeNode(val)
                    p.lchild.parent=p
                    return
            elif val>p.data:
                if p.rchild: #如果存在右子树,右子树不为空
                    p=p.rchild
                else:
                    p.rchild=BSTreeNode(val)
                    p.rchild.parent=p
                    return
            else: #如果val=p.data
                return

    def pre_order(self,root):
        if root:
            print(root.data, end=",")
            self.pre_order(root.lchild)
            self.pre_order(root.rchild)

    def in_order(self,root):
        if root:
            self.in_order(root.lchild)
            print(root.data, end=",")
            self.in_order(root.rchild)

    def post_order(self,root):
        if root:
            self.post_order(root.lchild)
            self.post_order(root.rchild)
            print(root.data, end=",")

tree=BST([4,6,7,9,2,1,3,5,8])
tree.pre_order(tree.root)
print("")
tree.in_order(tree.root)
print("")
tree.pre_order(tree.root)

结果输出为:

4,2,1,3,6,5,7,9,8,
1,2,3,4,5,6,7,8,9,
4,2,1,3,6,5,7,9,8,

可以看出,BST树的中序遍历一定是顺序的,记住这不是巧合就行

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-30 12:11:23  更:2021-09-30 12:13:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 12:11:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码