python常用算法(5)——树,二叉树与AVL树(二)

简介: python常用算法(5)——树,二叉树与AVL树

python常用算法(5)——树,二叉树与AVL树(一)https://developer.aliyun.com/article/1542698

4.4  二叉搜索树的查询操作

   从根节点开始查找,待查找的值是否与根节点的值相同,若相同则返回True;否则,判断待寻找的值是否比根节点的值小,若是则进入根节点左子树进行查找,否则进入右子树进行查找。该操作使用递归实现。

  代码如下:

def query(self, node, val):
    if not node:
        return None
    if node.data < val:
        return self.query(node.rchild, val)
    elif node.data > val:
        return self.query(node.lchild, val)
    else:
        return node
4.5  二叉树的查询操作——找最大值(最小值)

  查找最小值:从根节点开始,沿着左子树一直往下,直到找到最后一个左子树节点,按照定义可知,该节点一定是该二叉搜索树中的最小值节点。

  程序代码如下:

def findMin(self, root):
    '''查找二叉搜索树中最小值点'''
    if root.left:
        return self.findMin(root.left)
    else:
        return root

  查找最大值:从根节点开始,沿着右子树一直往下,知道找到最后一个右子树节点,按照定义可知,该节点一定是该二叉搜索树中的最大值节点。

  程序代码如下:

def findMax(self, root):
    '''查找二叉搜索树中最大值点'''
    if root.right:
        return self.findMax(root.right)
    else:
        return root
4.6  二叉搜索树的删除操作

  对二叉搜索树节点的删除操作分为以下三种情况

  1,如果要删除的节点是叶子节点:直接删除

  2,如果要删除的节点只有一个孩子:将此节点的父亲与孩子连接,然后删除该节点(注意:该待删节点可能只有左子树或者右子树)

  3,如果要删除的节点有两个孩子:将其右子树的最小节点(该节点最多有一个右孩子)删除,并替换当前节点

  代码如下:

# _*_coding:utf-8_*_
import random
 
 
class BiTreeNode:
    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_no_rec(val)
 
 
    def __remove_node_1(self, node):
        # 第一种情况:node是叶子节点
        if not node.parent:
            self.root = None
        if node == node.parent.lchild:  # node是他父亲的左孩子
            node.parent.lchild = None
            node.parent = None  # 可以不写
        else:  # node是他父亲的右孩子
            node.parent.rchild = None
 
    def __remove_node_21(self, node):
        # 情况2.1:node只有一个孩子,且为左孩子
        if not node.parent:  # 根节点
            self.root = node.lchild
            node.lchild.parent = None
        elif node == node.parent.lchild:  # node是它父亲的左孩子
            node.parent.lchild = node.lchild
            node.lchild.parent = node.parent
        else:  # node 是它父亲的右孩子
            node.parent.rchild = node.lchild
            node.lchild.parent = node.parent
 
    def __remove_node_22(self, node):
        # 情况2.2:node只有一个孩子,且为右孩子
        if not node.parent:
            self.root = node.rchild
        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)
            if not node:  # 不存在
                return False
            if not node.lchild and not node.rchild:  # 1,叶子节点
                self.__remove_node_1(node)
            elif not node.rchild:  # 2.1 只有一个左孩子
                self.__remove_node_21(node)
            elif not node.lchild:  # 2.2 只有一个右孩子
                self.__remove_node_22(node)
            else:
                # 3,两个孩纸都有
                min_node = node.rchild
                while min_node.lchild:  # 有左孩子
                    min_node = min_node.lchild
                node.data = min_node.data
                # 删除min_node
                if min_node.rchild:
                    self.__remove_node_22(min_node)
                else:
                    self.__remove_node_1(min_node)
4.7  二叉搜索树的打印操作

  实现二叉搜索树的前序遍历,中序遍历,后序遍历,并打印出来。其中中序遍历打印出来的数列是按照递增顺序排列。

  程序的代码如下:

def printTree(self, root):
    # 打印二叉搜索树(中序打印,有序数列—)
    if root == None:
        return 
    self.printTree(root.left)
    print(root.val, end=',')
    self.printTree(root.right)
4.8  二叉树的插入,查询,删除,打印完整代码

  代码如下:

# _*_coding:utf-8_*_
import random
 
 
class BiTreeNode:
    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_no_rec(val)
 
    def insert(self, node, val):
        if not node:
            node = BiTreeNode(val)
        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
        return node
    def insert_no_rec(self, val):
        p = self.root
        if not p:  # 空树
            self.root = BiTreeNode(val)
            return
        while True:
            if val < p.data:
                if p.lchild:
                    p = p.lchild
                else:  # 左孩子不存在
                    p.lchild = BiTreeNode(val)
                    p.lchild.parent = p
                    return
            elif val > p.data:
                if p.rchild:
                    p = p.rchild
                else:
                    p.rchild = BiTreeNode(val)
                    p.rchild.parent = p
                    return
            else:
                return
 
    def query(self, node, val):
        if not node:
            return None
        if node.data < val:
            return self.query(node.rchild, val)
        elif node.data > val:
            return self.query(node.lchild, val)
        else:
            return node
    def query_no_rec(self, val):
        p = self.root
        while p:
            if p.data < val:
                p = p.rchild
            elif p.data > val:
                p = p.lchild
            else:
                return p
        return None
    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=',')
    def __remove_node_1(self, node):
        # 第一种情况:node是叶子节点
        if not node.parent:
            self.root = None
        if node == node.parent.lchild:  # node是他父亲的左孩子
            node.parent.lchild = None
            node.parent = None  # 可以不写
        else:  # node是他父亲的右孩子
            node.parent.rchild = None
 
    def __remove_node_21(self, node):
        # 情况2.1:node只有一个孩子,且为左孩子
        if not node.parent:  # 根节点
            self.root = node.lchild
            node.lchild.parent = None
        elif node == node.parent.lchild:  # node是它父亲的左孩子
            node.parent.lchild = node.lchild
            node.lchild.parent = node.parent
        else:  # node 是它父亲的右孩子
            node.parent.rchild = node.lchild
            node.lchild.parent = node.parent
 
    def __remove_node_22(self, node):
        # 情况2.2:node只有一个孩子,且为右孩子
        if not node.parent:
            self.root = node.rchild
        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)
            if not node:  # 不存在
                return False
            if not node.lchild and not node.rchild:  # 1,叶子节点
                self.__remove_node_1(node)
            elif not node.rchild:  # 2.1 只有一个左孩子
                self.__remove_node_21(node)
            elif not node.lchild:  # 2.2 只有一个右孩子
                self.__remove_node_22(node)
            else:
                # 3,两个孩纸都有
                min_node = node.rchild
                while min_node.lchild:  # 有左孩子
                    min_node = min_node.lchild
                node.data = min_node.data
                # 删除min_node
                if min_node.rchild:
                    self.__remove_node_22(min_node)
                else:
                    self.__remove_node_1(min_node)
 
 
    def printTree(self, root):
        # 打印二叉搜索树(中序打印,有序数列—)
        if root == None:
            return
        self.printTree(root.left)
        print(root.val, end=',')
        self.printTree(root.right)
 
# 删除
tree = BST([1, 4, 2, 5, 3, 8, 6, 9, 7])
tree.in_order(tree.root)
print(" ")
tree.delete(4)
tree.delete(1)
tree.delete(8)
tree.in_order(tree.root)
 
'''
# 插入操作
tree = BST([4,6,7,9,2,1,3,5,8])
tree.pre_order(tree.root)
print(" ")
tree.in_order(tree.root)
print(" ")
tree.post_order(tree.root)
print(" ")
'''
4, 2, 1, 3, 6, 5, 7, 9, 8,
1, 2, 3, 4, 5, 6, 7, 8, 9,
1, 3, 2, 5, 8, 9, 7, 6, 4,
'''
# 查询操作
li = list(range(0, 500, 2))
random.shuffle(li)
tree = BST(li)
print(tree.query_no_rec(4).data)
# 4
'''
4.9  二叉搜索树的效率

  平均情况下,二叉搜索树进行搜索的时间复杂度为O(nlgn)

  最坏情况下,二叉搜索树可能非常偏斜,如下图所示:

解决方案

  1. 随机化传入
  2. AVL树

python常用算法(5)——树,二叉树与AVL树(三)https://developer.aliyun.com/article/1542700

相关文章
|
3天前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
16 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
4天前
|
算法 Python
震惊!Python 算法设计背后,时间复杂度与空间复杂度的惊天秘密大起底!
在 Python 算法设计中,理解并巧妙运用时间复杂度和空间复杂度的知识,是实现高效、优雅代码的必经之路。通过不断地实践和优化,我们能够在这两个因素之间找到最佳的平衡点,创造出性能卓越的程序。
17 4
|
5天前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
19 4
|
3天前
|
算法 程序员 Python
程序员必看!Python复杂度分析全攻略,让你的算法设计既快又省内存!
在编程领域,Python以简洁的语法和强大的库支持成为众多程序员的首选语言。然而,性能优化仍是挑战。本文将带你深入了解Python算法的复杂度分析,从时间与空间复杂度入手,分享四大最佳实践:选择合适算法、优化实现、利用Python特性减少空间消耗及定期评估调整,助你写出高效且节省内存的代码,轻松应对各种编程挑战。
14 1
|
4天前
|
算法 计算机视觉 Python
Python并查集大揭秘:让你在算法界呼风唤雨,秒杀一切复杂场景!
在编程与算法的广袤天地中,总有一些工具如同神兵利器,能够助你一臂之力,在复杂的问题前游刃有余。今天,我们就来深入探讨这样一件神器——Python并查集(Union-Find),看看它是如何让你在算法界呼风唤雨,轻松应对各种复杂场景的。
14 2
|
3天前
|
机器学习/深度学习 人工智能 算法
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台。果蔬识别系统,本系统使用Python作为主要开发语言,通过收集了12种常见的水果和蔬菜('土豆', '圣女果', '大白菜', '大葱', '梨', '胡萝卜', '芒果', '苹果', '西红柿', '韭菜', '香蕉', '黄瓜'),然后基于TensorFlow库搭建CNN卷积神经网络算法模型,然后对数据集进行训练,最后得到一个识别精度较高的算法模型,然后将其保存为h5格式的本地文件方便后期调用。再使用Django框架搭建Web网页平台操作界面,实现用户上传一张果蔬图片识别其名称。
16 0
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
2月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【7月更文挑战第22天】在大数据领域,Python算法效率至关重要。本文深入解析时间与空间复杂度,用大O表示法衡量执行时间和存储需求。通过冒泡排序(O(n^2)时间,O(1)空间)与快速排序(平均O(n log n)时间,O(log n)空间)实例,展示Python代码实现与复杂度分析。策略包括算法适配、分治法应用及空间换取时间优化。掌握这些,可提升大数据处理能力,持续学习实践是关键。
58 1
|
3月前
|
存储 机器学习/深度学习 算法
Python算法基础教程
Python算法基础教程
20 0
|
数据采集 SQL 算法
C++、Python、数据结构与算法、计算机基础、数据库教程汇总!
C++、Python、数据结构与算法、计算机基础、数据库教程汇总!
209 0
C++、Python、数据结构与算法、计算机基础、数据库教程汇总!