python 二叉树

Posted 码农帅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 二叉树相关的知识,希望对你有一定的参考价值。

为了准备面试,早就学习了二叉树,最近想撸一下红黑树。先把二叉树给总结一下吧。

1.二叉树定义

在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

图中就是一个典型的二叉树。

2.二叉树的一些概念

树的结点(node):包含一个数据元素及若干指向子树的分支;
孩子结点(child node):结点的子树的根称为该结点的孩子;
双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;
祖先结点: 从根到该结点的所经分支上的所有结点
子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙
结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;
树的深度:树中最大的结点层
结点的度:结点子树的个数
树的度: 树中最大的结点度。
叶子结点:也叫终端结点,是度为 0 的结点;
分枝结点:度不为0的结点;
有序树:子树有序的树,如:家族树;
无序树:不考虑子树的顺序;

 

----------------回头更新--------
 3.二叉树的可视化
要学习二叉树,利用python来构建二叉树,首先要有一个办法能将二叉树可视化。这我找了不少地方,最后不记得在哪找到了一个方法使用networkx和matplotlib来进行绘制。
import networkx as nx
import matplotlib.pyplot as plt

def create_graph(G, node, pos={}, x=0, y=0, layer=1):
    pos[node.key] = (x, y)
    if node.left:
        G.add_edge(node.key, node.left.key)
        l_x, l_y = x - 1 / 2 ** layer, y - 1
        l_layer = layer + 1
        create_graph(G, node.left, x=l_x, y=l_y, pos=pos, layer=l_layer)
    if node.right:
        G.add_edge(node.key, node.right.key)
        r_x, r_y = x + 1 / 2 ** layer, y - 1
        r_layer = layer + 1
        create_graph(G, node.right, x=r_x, y=r_y, pos=pos, layer=r_layer)
    return (G, pos)

def draw(node):   # 以某个节点为根画图
    graph = nx.DiGraph()
    graph, pos = create_graph(graph, node)
    fig, ax = plt.subplots(figsize=(8, 10))  # 比例可以根据树的深度适当调节
    nx.draw_networkx(graph, pos, ax=ax, node_size=600)
    plt.show()

调用的时候,使用draw(tree.root)就可以将整个树绘制出来,如下图所示

 

4.二叉树的构建

这个没啥好说的,基本就是构建一个节点类作为节点,有左枝和右枝,值,父节点四个属性;还有一个树类,要求要有节点的增,删,查功能。

增:增加一个元素就是从根节点开始,不断对比节点与插入的值,最后找到所在的位置新增一个节点

查:从根节点开始不断向下查找。

删:这个比较麻烦,需要分三种情况讨论:

4.1所删除的节点是叶子节点,直接删除就可以了。

4.2所删除的节点有一个分支,那么就使用它的分支的第一个节点代替它就好了

4.3所删除的节点有两个分支,那么要查找它的最小后继(一定在它的右枝里)然后替换它,再删除原来的最小后继(注意,这个再删除是一个递归过程)

构建代码如下

class node(object):
    def __init__(self,value):
        self.key=value
        self.right=None
        self.left=None
        self.parent=None

class tree(object):
    def __init__(self):
        self.root=None
        self.nodeArr=[]
    def add(self,element):
        newNode=node(element)

        if self.root:
            index=self.root
            lastIndex=index
            while index!=None:
                lastIndex = index
                if index.key <element:
                    index=index.right
                else :
                    index=index.left
            if lastIndex.key < element:
                lastIndex.right=newNode
                newNode.parent =lastIndex
            else:
                lastIndex.left=newNode
                newNode.parent = lastIndex
        else:
            self.root= newNode

    def find(self,element,root):
        temp=root
        while temp:
            if temp.key<element:
                temp=temp.right
            elif temp.key>element:
                temp=temp.left
            else:
                return temp
    def maxNode(self,node):
        temp=node
        while temp.right:
            temp=temp.right
        return temp
    def minNode(self,node):
        temp=node
        while temp.left:
            temp=temp.left
        return temp
    def remove(self,element,root):
        temp=self.find(element,root)
        print(temp)
        if temp:
            newNode=None
            del_node=temp
            if temp.right and temp.left:#如果有两个分支
                rightMax = self.maxNode(temp)
                newNode=node(rightMax.key)

                newNode.parent=del_node.parent
                del_node.parent.right=newNode

                newNode.left=del_node.left
                if del_node.left:
                    del_node.left.parent=newNode
                newNode.right = del_node.right
                if del_node.right:
                    del_node.right.parent = newNode
                del del_node
                self.remove(newNode.key,newNode.right)

            elif not temp.right and not temp.left:#没有分支
                del_node.parent.right=None
                del del_node

            else :#只有一个分支
                value=temp.right or temp.left
                value.parent=del_node.parent
                if del_node.parent.right.key==temp.key:
                    value.parent.right=value
                else:
                    value.parent.left=value
                del del_node

5.整体效果

运行以下代码,可以看到删除节点335前和删除节点335以后的效果。

myTree=tree()
s=[149, 382, 364, 335, 35, 498, 370, 272, 327, 191]
for i in range(10):
    myTree.add(s[i])

draw(myTree.root)
myTree.remove(335,myTree.root)#删除335节点
draw(myTree.root)

 

以上是关于python 二叉树的主要内容,如果未能解决你的问题,请参考以下文章

判断对称二叉树 python代码

python代码实现二叉树的序列化和反序列化

Python数据结构系列☀️《树与二叉树-基础知识》——知识点讲解+代码实现☀️

判断一颗二叉树是否为二叉平衡树 python 代码

python代码实现二叉树的分层打印

python代码实现二叉树的镜像树