zoukankan      html  css  js  c++  java
  • python 实现二叉树相关算法

    一、构建与遍历二叉树

    基本性质
    1)在二叉树的第i层上最多有2i-1 个节点 。(i>=1)
    2)二叉树中如果深度为k,那么最多有2k-1个节点。(k>=1)
    3)在完全二叉树中,具有n个节点的完全二叉树的深度为[log2n]+1,其中[log2n]是向下取整。向下取整就是小数点后面的数字无论多少,都只取前面的整数。

    4)二叉树的存储可以顺序存储即数组形式,也可以链式存储。
     

    class Node(object):
        def __init__(self,item):
            self.key=item
            self.left=None
            self.right=None
    class BinaryTree(object):
        def __init__(self):
            self.root=None
    
        def addNode(self,item):
            new_node = Node(item)
            if self.root is None:
               self.root=new_node
            else:
                stack=[]
                stack.append(self.root)
                while True:
                    node=stack.pop(0)
                    if node.left is None:
                        node.left=new_node
                        return
                    elif node.right is None:
                        node.right=new_node
                        return
                    else:
                        stack.append(node.left)
                        stack.append(node.right)
    
        def traverse(self):  #层次遍历
            if self.root is None:
                return None
            else:
                s=[]
                s.append(self.root)
                while len(s) > 0:
                    node = s.pop(0)
                    print(node.key)
                    if node.left is not None:
                        s.append(node.left)
                    if node.right is not None:
                        s.append(node.right)

    #一层层打印
    def
    Print(self, pRoot): if pRoot is None: return [] l=[] s=[] s.append(pRoot) while len(s)>0: length=len(s) v=[] for i in range(length): tmp=s.pop(0) v.append(tmp.val) if tmp.left: s.append(tmp.left) if tmp.right: s.append(tmp.right) l.append(v) return l
    
    
    
    def preOrder(self,root):
            if root is None:
                return None
            print(root.key)
            self.preOrder(root.left)
            self.preOrder(root.right)
    
        def inOrder(self,root):
            if root is None:
                return None
    
            self.inOrder(root.left)
            print(root.key)
            self.inOrder(root.right)
    
        def postOrder(self,root):
            if root is None:
                return None
    
            self.postOrder(root.left)
            self.postOrder(root.right)
            print(root.key)

     之字形打印二叉树

    def print(root):
        if root is None:
            return None
        s1=[]
        s2=[]
        s1.append(root)#靠两个栈交替左右压入栈,实现左右交替输出,形成之字形打印
        while len(s1)>0 or len(s2)>0:
            while len(s1)>0:
                tmp=s1.pop()
                print(tmp.value)
                if tmp.left is not None:
                    s2.append(tmp.left)
                if tmp.right is not None:
                    s2.append(tmp.right)
            while len(s2)>0:
                tmp=s2.pop()
                print(tmp.value)
                if tmp.right is not None:
                    s1.append(tmp.right)
                if tmp.left is not None:
                    s1.append(tmp.left)

    非递归前序遍历:

    def PreOrderWithoutRecursion(root):
        if root is None:
            return
        s=[]
        p=root
        while len(s)>0 or p is not None:
            if p is not None:
                print(p.key)
                s.append(p)
                p=p.left
            else:
                p=s.pop()
                p=p.right

    非递归中序遍历:

    def InOrderWithoutRecursion(root):
        if root is None:
            return
        s=[]
        p=root
        while len(s)>0 or p is not None:
            if p is not None:
                s.append(p)
                p=p.left
            else:
                p=s.pop()
                print(p.key)
                p=p.right

    非递归后序遍历:

    def PostOrderWithoutRecursion(root):
        if root is None:
            return
        s=[]
        p=root
        lastVisit=None
        while p is not None:
            s.append(p)
            p=p.left
        while len(s)>0:
            p=s.pop()
            if p.right==None or lastVisit==p.right:
                print(p.key)
                lastVisit=p
            else:
                s.append(p)
                p=p.right
                while p is not None:
                    s.append(p)
                    p=p.left

    二、二叉树的宽度与深度

    def treeDepth(root):
        if root is None:
            return 0
        nleft=treeDepth(root.left)+1
        nright=treeDepth(root.right)+1
        return nleft if nleft > nright else nright
    
    #求解二叉树的宽度,节点数最多的一层的节点数即为二叉树的宽度
    def treeWidth(root):
        if root is None:
            return 0
        max_width=0
        s=[]
        s.append(root)
        while len(s)>0:
            width=len(s)
            if width>max_
                max_width=width
            for i in range(width):
                node=s.pop(0)
                if node.left is not None:
                    s.append(node.left)
                if node.right is not None:
                    s.append(node.right)
    
        return max_width

     三、判断是否为子树

    #如果两个节点值相同,则继续判断下面节点值是否也相等
    def
    isPart(pRoot1,pRoot2): if pRoot2 is None: return True if pRoot1 is None: return False if pRoot1.val!=pRoot2.val: return False return isPart(pRoot1.left,pRoot2.left) and isPart(pRoot1.right,pRoot2.right) def HasSubtree(pRoot1, pRoot2): res=False if pRoot1 is not None and pRoot2 is not None: if pRoot1.val==pRoot2.val: res=isPart(pRoot1,pRoot2) if not res: res=HasSubtree(pRoot1.left,pRoot2) if not res: res=HasSubtree(pRoot1.right,pRoot2) return res

     四、判断是否为平衡二叉树

    def TreeDepth(self,root):
            if root is None:
                return 0
            nleft=self.TreeDepth(root.left)
            nright=self.TreeDepth(root.right)
            return nleft+1 if nleft>nright else nright+1
    
    def IsBalanced_Solution(self, pRoot):
        isBalance=True
        if pRoot is None:
            return isBalance
        leftDepth=self.TreeDepth(pRoot.left)
        rightDepth=self.TreeDepth(pRoot.right)
        if abs(leftDepth-rightDepth)>1:
            isBalance=False
        return isBalance and self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)

    五、判断是否为对称二叉树

    def isSame(self,left,right):
            if left and right :
                if left.val==right.val:
                    return self.isSame(left.left,right.right) and self.isSame(left.right,right.left)
                else:
                    return False
            elif not left and not right:
                return True
            else:
                return False
    def isSymmetrical(self, pRoot):
        if pRoot is None:
            return True
        return self.isSame(pRoot.left,pRoot.right)

     六、序列化与反序列化

    def Serialize(self, root):
            if root is None:
                return '#'
            return str(root.val)+self.Serialize(root.left)+self.Serialize(root.right)
    def Deserialize(self, s):
        if len(s)<=0:
            return None
        root=None
        val=s.pop(0)
        if val!='#':
            root=TreeNode(int(val))
            root.left=self.Deserialize(s)
            root.right=self.Deserialize(s)
        return root

    七、查找二叉树某个值的路径(先根方式)

    def findval(root,val):
        if root is None:
            return None
        s=[]
        p=root
        path=[] #利用先根遍历的方式进行查找,path保存那些右子树不为空的根节点,进入path说明遍历过了,以便后续判断何时出栈。
        while len(s)>0 or p is not None:
            if p is not None:
                if p in path:
                    s.pop()#如果在path中了,说明之前遍历过来,就直接出栈吧,不用再向下子树遍历了
                else:
                    s.append(p)
                    if p.key==val:
                        return s
                    p=p.left
            else:
                p=s[len(s)-1]#暂时先不出栈,看看右子树是否为空,右子树不为空,就暂时不出栈
                if p.right is None or p in path:#右子树为空的,或者之前遍历过的就直接出栈吧
                    s.pop()
                    p=None
                else:
                    path.append(p) #之前没遍历过的且其右子树不为空,那就先不出栈了,放入path中,表示遍历过了。
                    p=p.right

     例如上图中:E的路径就是A,C ,E。  F的路径就是A,C,F.

     

    参考来源:https://www.jianshu.com/p/bf73c8d50dc2

     

  • 相关阅读:
    [轉]SQLServer : EXEC和sp_executesql的区别
    CSS 中文字体
    [转]71种 menu css源码
    DataTable做為數據源手動分頁
    [轉]9个优秀的基于 JavaScript 与 CSS 的 Web 图表框架
    [轉]10 Tools to help you select a Web 2.0 Color Palette
    [轉]ASP模拟POST提交请求上传文件
    Web配色資源
    [轉]sqlhelper 下载 使用指南
    [轉]查看SQL Server数据库连接
  • 原文地址:https://www.cnblogs.com/gczr/p/8033104.html
Copyright © 2011-2022 走看看