zoukankan      html  css  js  c++  java
  • 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)

  • 相关阅读:
    bzoj 1179[Apio2009]Atm (tarjan+spfa)
    tarjan讲解(用codevs1332(tarjan的裸题)讲解)
    spfa
    codevs 1021 玛丽卡(spfa)
    Redis-mac安装与使用
    心血来潮整理一下STL——string
    基础算法整理(1)——递归与递推
    一道水的不能再水的中国盒子问题——小试牛刀(3)
    论久违的八数码问题——小试牛刀(2)
    8皇后及其普及(N)——小试牛刀(1)
  • 原文地址:https://www.cnblogs.com/NewsunLs/p/10069238.html
Copyright © 2011-2022 走看看