zoukankan      html  css  js  c++  java
  • 二叉树

    二叉树

    一.把一个有序整数数组放到二叉树中

    首先取数组的中间结点作为二叉树的根结点,把数组分成左右两部分,然后对于数组的左右两部分子数组分别运用同样的方法进行二叉树的构建,依此类推

    class BiTNode(object):
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    def arraytotree(arr,start,end):
        root=None
    
        if end>=start:
            root=BiTNode()
            mid=int((start+end+1)/2)
            root.data=arr[mid]
            root.lchild=arraytotree(arr,start,mid-1)
            root.rchild=arraytotree(arr,mid+1,end)
        else:
            root=None
        return root
    
    
    def printTreeMidOrder(root):
        if root==None:
            return
    
        if root.lchild!=None:
            printTreeMidOrder(root.lchild)
    
        print(root.data,end=" ")
    
        if root.rchild!=None:
            printTreeMidOrder(root.rchild)
    
    
    def printTreePreOrder(root):
        if root==None:
            return
    
        print(root.data,end=" ")
    
        if root.lchild!=None:
            printTreePreOrder(root.lchild)
    
        if root.rchild!=None:
            printTreePreOrder(root.rchild)
    
    if __name__=="__main__":
        arr=[1,2,3,4,5,6,7,8,9,10]
        print("数组:")
    
        i=0
        while i<len(arr):
            print(arr[i],end=" ")
            i+=1
    
        print("
    ")
    
        root=arraytotree(arr,0,len(arr)-1)
        print("转成树的中序遍历为:")
        printTreeMidOrder(root)
    
        print("
    ")
        print("转成树的前序遍历为:")
        printTreePreOrder(root)
    
    数组:
    1 2 3 4 5 6 7 8 9 10 
    
    转成树的中序遍历为:
    1 2 3 4 5 6 7 8 9 10 
    
    转成树的前序遍历为:
    6 3 2 1 5 4 9 8 7 10
    

    二.从顶部开始逐层打印二叉树结点数据

    1.空间复杂度为O(n)

    from collections import deque
    
    class BiTNode(object):
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    def arraytoTree(arr,start,end):
        root=None
        if end>=start:
            root=BiTNode()
            mid=int((start+end+1)/2)
            root.data=arr[mid]
            root.lchild=arraytoTree(arr,start,mid-1)
            root.rchild=arraytoTree(arr,mid+1,end)
        else:
            root=None
    
        return root
    
    
    def printTreeLayer(root):
        if root==None:
            return
    
        queue=deque()
    
        queue.append(root)
        while len(queue)>0:
            p=queue.popleft()
            print(p.data,end=" ")
            if p.lchild!=None:
                queue.append(p.lchild)
            if p.rchild!=None:
                queue.append(p.rchild)
    
    if __name__=="__main__":
        arr=[1,2,3,4,5,6,7,8,9,10]
        root=arraytoTree(arr,0,len(arr)-1)
        print("树的层序遍历结果为:")
        printTreeLayer(root)
    
    树的层序遍历结果为:
    6 3 9 2 5 8 10 1 4 7
    

    2.空间复杂度为O(1)

    class BiTNode(object):
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    def arraytoTree(arr,start,end):
        root=None
        if end>=start:
            root=BiTNode()
            mid=int((start+end+1)/2)
            root.data=arr[mid]
            root.lchild=arraytoTree(arr,start,mid-1)
            root.rchild=arraytoTree(arr,mid+1,end)
        else:
            root=None
    
        return root
    
    
    def printAtLevel(root,level):
        if root==None or level<0:
            return 0
        elif level==0:
            print(root.data,end=" ")
            return 1
        else:
            return printAtLevel(root.lchild,level-1)+printAtLevel(root.rchild,level-1)
    
    if __name__=="__main__":
        arr=[1,2,3,4,5,6,7,8,9,10]
        root=arraytoTree(arr,0,len(arr)-1)
        print("树的层序遍历结果为:")
    
        printAtLevel(root, 0)
        printAtLevel(root, 1)
        printAtLevel(root, 2)
        printAtLevel(root,3)
    
    树的层序遍历结果为:
    6 3 9 2 5 8 10 1 4 7
    

    三.求一棵二叉树的最大子树和

    import sys
    
    class BiTNode(object):
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    class Test:
        def __init__(self):
            self.maxSum=-sys.maxsize-1
    
        def findMaxSubTree(self,root,maxRoot):
            if root==None:
                return 0
    
            lmax=self.findMaxSubTree(root.lchild,maxRoot)
            rmax=self.findMaxSubTree(root.rchild,maxRoot)
            sums=lmax+rmax+root.data
    
            if sums>self.maxSum:
                self.maxSum=sums
                maxRoot.data=root.data
    
            return sums
    
        def constructTree(self):
            root=BiTNode()
            node1=BiTNode()
            node2=BiTNode()
            node3=BiTNode()
            node4=BiTNode()
    
            root.data=6
            node1.data=3
            node2.data=-7
            node3.data=-1
            node4.data=9
    
            root.lchild=node1
            root.rchild=node2
            node1.lchild=node3
            node1.rchild=node4
            return root
    
    
    if __name__=="__main__":
        test=Test()
        root=test.constructTree()
        maxRoot=BiTNode()
        test.findMaxSubTree(root,maxRoot)
        print("最大子树和为:",test.maxSum)
        print("对应子树的根结点为:",maxRoot.data)
    
    最大子树和为: 11
    对应子树的根结点为: 3
    

    **算法性能分析:**时间复杂度为O(N)

    四.判断两棵二叉树是否相等

    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    def isEqual(root1,root2):
        if root1==None and root2==None:
            return True
    
        if root1==None and root2!=None:
            return False
    
        if root1!=None and root2==None:
            return False
    
        if root1.data==root2.data:
            return isEqual(root1.lchild,root2.lchild) and isEqual(root1.rchild,root2.rchild)
        else:
            return False
    
    def constructTree():
        root=BiTNode()
        node1=BiTNode()
        node2=BiTNode()
        node3=BiTNode()
        node4=BiTNode()
    
        root.data=6
        node1.data=3
        node2.data=-7
        node3.data=-1
        node4.data=9
    
        root.lchild=node1
        root.rchild=node2
        node1.lchild=node3
        node1.rchild=node4
        return root
    
    def constructTree1():
        root=BiTNode()
        node1=BiTNode()
        node2=BiTNode()
        node3=BiTNode()
        node4=BiTNode()
    
        root.data=6
        node1.data=4
        node2.data=-7
        node3.data=-1
        node4.data=9
    
        root.lchild=node1
        root.rchild=node2
        node1.lchild=node3
        node1.rchild=node4
        return root
    
    if __name__=="__main__":
        root1=constructTree()
        root2=constructTree1()
        equal=isEqual(root1,root2)
        if equal:
            print("这两棵树相等")
        else:
            print("这两棵树不相等")
    
    这两棵树不相等
    

    五.把二叉树转换为双向链表

    转换后的双向链表中结点的顺序与二叉树的中序遍历的顺序相同.实现思路:

    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    class Test:
        def __init__(self):
            self.pHead=None
            self.pEnd=None
    
        def arraytoTree(self,arr,start,end):
            root=None
            if end>=start:
                root=BiTNode()
                mid=int((start+end+1)/2)
                root.data=arr[mid]
                root.lchild=self.arraytoTree(arr,start,mid-1)
                root.rchild=self.arraytoTree(arr,mid+1,end)
            else:
                root=None
    
            return root
    
        def inOrderBSTree(self,root):
            if root==None:
                return
    
            self.inOrderBSTree(root.lchild)
            root.lchild=self.pEnd
    
            if self.pEnd==None:
                self.pHead=root
            else:
                self.pEnd.rchild=root
            self.pEnd=root
    
            self.inOrderBSTree(root.rchild)
    
    
    if __name__=="__main__":
        arr=[1,2,3,4,5,6,7]
        test=Test()
        root=test.arraytoTree(arr,0,len(arr)-1)
        test.inOrderBSTree(root)
    
        print("转换后双向链表正向遍历:")
        cur=test.pHead
        while cur!=None:
            print(cur.data,end=" ")
            cur=cur.rchild
    
        print("
    ")
        print("转换后双向链表逆向遍历:")
        cur=test.pEnd
        while cur!=None:
            print(cur.data,end=" ")
            cur=cur.lchild
    
    转换后双向链表正向遍历:
    1 2 3 4 5 6 7 
    
    转换后双向链表逆向遍历:
    7 6 5 4 3 2 1
    

    **算法性能分析:**时间复杂度为O(N),空间复杂度为O(1)

    六.判断一个数组是否是二元查找树后序遍历的序列

    def IsAfterOrder(arr,start,end):
        if arr==None:
            return False
    
        root=arr[end]
    
        i=start
        while i<end:
            if arr[i]>root:
                break
            i+=1
    
        j=i
        while j<end:
            if arr[j]<root:
                return False
            j+=1
    
        left_IsAfterOrder=True
        right_IsAfterOrder=True
    
        if i>start:
            left_IsAfterOrder=IsAfterOrder(arr,start,i-1)
    
        if j<end:
            right_IsAfterOrder=IsAfterOrder(arr,i,end)
    
        return left_IsAfterOrder and right_IsAfterOrder
    
    if __name__=="__main__":
        arr=[1,3,2,5,7,6,4]
        result=IsAfterOrder(arr,0,len(arr)-1)
        i=0
        while i<len(arr):
            print(arr[i],end=" ")
            i+=1
    
        if result:
            print("是某一二元查找树的后序遍历序列")
        else:
            print("不是某一二元查找树的后序遍历序列")
    
    1 3 2 5 7 6 4 是某一二元查找树的后序遍历序列
    

    七.找出排序二叉树上任意两个结点的最近共同父节点

    1.路径对比法

    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    class stack:
        def __init__(self):
            self.items=[]
    
        def isEmpty(self):
            return len(self.items)==0
    
        def size(self):
            return len(self.items)
    
        def peek(self):
            if not self.isEmpty():
                return self.items[len(self.items)-1]
            else:
                return None
    
        def pop(self):
            if len(self.items)>0:
                return self.items.pop()
            else:
                print("栈已经为空")
                return None
    
        def push(self,item):
            self.items.append(item)
    
    def arraytoTree(arr,start,end):
        root=None
        if end>=start:
            root=BiTNode()
            mid=int((start+end+1)/2)
            root.data=arr[mid]
            root.lchild=arraytoTree(arr,start,mid-1)
            root.rchild=arraytoTree(arr,mid+1,end)
        else:
            root=None
    
        return root
    
    
    def getPathFromRoot(root,node,s):
        if root==None:
            return False
        if root==node:
            s.push(root)
            return True
    
        if getPathFromRoot(root.lchild,node,s) or getPathFromRoot(root.rchild,node,s):
            s.push(root)
            return True
    
        return False
    
    def FindParentNode(root,node1,node2):
        stack1=stack()
        stack2=stack()
    
        getPathFromRoot(root,node1,stack1)
        getPathFromRoot(root,node2,stack2)
    
        commonParent=None
    
        while stack1.peek()==stack2.peek():
            commonParent=stack1.peek()
            stack1.pop()
            stack2.pop()
    
        return commonParent
    
    if __name__=="__main__":
        arr=[1,2,3,4,5,6,7,8,9,10]
        root=arraytoTree(arr,0,len(arr)-1)
        node1=root.lchild.lchild.lchild
        node2=root.lchild.rchild
    
        res=None
        res=FindParentNode(root,node1,node2)
    
        if res!=None:
            print(str(node1.data)+"与"+str(node2.data)+"的最近公共父结点为:"+str(res.data))
        else:
            print("没有公共父结点")
    
    1与5的最近公共父结点为:3
    

    **算法性能分析:**时间复杂度为O(N),空间复杂度为O(N)

    2.结点编号法

    import math
    
    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    def arraytotree(arr,start,end):
        root=None
    
        if end>=start:
            root=BiTNode()
            mid=int((start+end+1)/2)
            root.data=arr[mid]
    
            root.lchild=arraytotree(arr,start,mid-1)
            root.rchild=arraytotree(arr,mid+1,end)
        else:
            root=None
    
        return root
    
    class IntRef:
        def __init__(self):
            self.num=None
    
    def getNo(root,node,number):
        if root==None:
            return False
        if root==node:
            return True
        tmp=number.num
        number.num=2*tmp
    
        if getNo(root.lchild,node,number):
            return True
        else:
            number.num=tmp*2+1
            return getNo(root.rchild,node,number)
    
    def getNodeFromNum(root,number):
        if root==None or number<0:
            return None
        if number==1:
            return root
    
        lens=int((math.log(number)/math.log(2)))
        number-=1<<lens
        while lens>0:
            if (1<<(lens-1))&number==1:
                root=root.rchild
            else:
                root=root.rchild
        return root
    
    def FindParentNode(root,node1,node2):
        ref1=IntRef()
        ref1.num=1
        ref2=IntRef()
        ref2.num=1
        getNo(root,node1,ref1)
        getNo(root,node2,ref2)
        num1=ref1.num
        num2=ref2.num
    
        while num1!=num2:
            if num1>num2:
                num1/=2
            else:
                num2/=2
    
        return getNodeFromNum(root,num1)
    
    if __name__=="__main__":
        arr=[1,2,3,4,5,6,7,8,9,10]
        root=arraytotree(arr,0,len(arr)-1)
        node1=root.lchild.lchild.lchild
        node2=root.lchild.rchild
        res=None
        res=FindParentNode(root,node1,node2)
        if res!=None:
            print(str(node1.data)+"与"+str(node2.data)+"的最近公共父结点为:"+str(res.data))
        else:
            print("没有公共父结点")
    

    **算法性能分析:**时间复杂度为O(N),空间复杂度为O(1)

    3.后序遍历法

    很多与二叉树相关的问题都可以通过对二叉树的遍历方法进行改装而求解.对于本题可以通过对二叉树的后序遍历进行改编而得到.具体思路为:查找结点ode1与结点node2的最近共同父结点可以转换为找到一个结点node,使得node1与node2分别位于结点node的左子树或右子树中

    def FindParentNode(root,node1,node2):
        if root==None or root==node1 or root==node2:
            return root
        
        lchild=FindParentNode(root.lchild,node1,node2)
        rchild=FindParentNode(root.rchild,node1,node2)
        
        if lchild==None:
            return rchild
        elif rchild==None:
            return lchild
        else:
            return root
    

    引申:计算二叉树中两个结点的距离

    在没有给出父结点的条件下,计算二叉树中两个结点的距离.两个结点之间的距离是从一个结点到达另一个结点所需的最小的边数.

    分析与解答:给定的二叉树root,只要能找到两个结点n1和n2最低的公共父结点parent,那么就可以通过下面的公式计算出这两个结点的距离:Dist(n1,n2)=Dist(root,n1)+Dist(root,n2)-2*Dist(root,parent)

    八.复制二叉树

    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    def createDupTree(root):
        if root==None:
            return None
    
        dupTree=BiTNode()
        dupTree.data=root.data
    
        dupTree.lchild=createDupTree(root.lchild)
        dupTree.rchild=createDupTree(root.rchild)
    
        return dupTree
    
    def constructTree():
        root = BiTNode()
        node1 = BiTNode()
        node2 = BiTNode()
        node3 = BiTNode()
        node4 = BiTNode()
    
        root.data = 6
        node1.data = 3
        node2.data = -7
        node3.data = -1
        node4.data = 9
    
        root.lchild = node1
        root.rchild = node2
        node1.lchild = node3
        node1.rchild = node4
        return root
    
    def PrintTreeMidOrder(root):
        if root==None:
            return
    
        if root.lchild!=None:
            PrintTreeMidOrder(root.lchild)
    
        print(root.data,end=" ")
    
        if root.rchild!=None:
            PrintTreeMidOrder(root.rchild)
    
    
    if __name__=="__main__":
        root1=constructTree()
        root2=createDupTree(root1)
        
        print("原始二叉树中序遍历:")
        PrintTreeMidOrder(root1)
    
        print("
    新的二叉树中序遍历:")
        PrintTreeMidOrder(root2)
    
    原始二叉树中序遍历:
    -1 3 9 6 -7 
    新的二叉树中序遍历:
    -1 3 9 6 -7
    

    九.在二叉树中找出与输入整数相等的所有路径

    从树的根结点开始往下访问一直到叶子结点经过的所有结点形成一条路径.找出所有的这些路径,使其满足这条路径上所有结点数据的和等于给定的整数

    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    def constructTree():
        root = BiTNode()
        node1 = BiTNode()
        node2 = BiTNode()
        node3 = BiTNode()
        node4 = BiTNode()
    
        root.data = 6
        node1.data = 3
        node2.data = -7
        node3.data = -1
        node4.data = 9
    
        root.lchild = node1
        root.rchild = node2
        node1.lchild = node3
        node1.rchild = node4
        return root
    
    def FindRoad(root,num,sums,v):
        sums+=root.data
        v.append(root.data)
    
        if root.lchild==None and root.rchild==None and sums==num:
            i=0
            while i<len(v):
                print(v[i],end=" ")
                i+=1
    
            print("
    ")
    
        if root.lchild!=None:
            FindRoad(root.lchild,num,sums,v)
    
        if root.rchild!=None:
            FindRoad(root.rchild,num,sums,v)
    
        sums-=v[-1]
        v.remove(v[-1])
    
    
    if __name__=="__main__":
        root=constructTree()
        s=[]
        print("满足路径结点和等于8的路径为:")
        FindRoad(root,8,0,s)
    
    满足路径结点和等于8的路径为:
    6 3 -1
    

    十.对二叉树进行镜像反转

    from collections import deque
    
    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    def arraytoTree(arr,start,end):
        root=None
    
        if end>=start:
            root=BiTNode()
            mid=int((start+end+1)/2)
            root.data=arr[mid]
    
            root.lchild=arraytoTree(arr,start,mid-1)
            root.rchild=arraytoTree(arr,mid+1,end)
        else:
            root=None
    
        return root
    
    def reverseTree(root):
        if root==None:
            return
    
        reverseTree(root.lchild)
        reverseTree(root.rchild)
        tmp=root.lchild
        root.lchild=root.rchild
        root.rchild=tmp
    
    
    def PrintTreeLayer(root):
        if root==None:
            return
    
        queue=deque()
    
        queue.append(root)
    
        while len(queue)>0:
            p=queue.popleft()
            print(p.data,end=" ")
    
            if p.lchild!=None:
                queue.append(p.lchild)
    
            if p.rchild!=None:
                queue.append(p.rchild)
    
    
    if __name__=="__main__":
        arr=[1,2,3,4,5,6,7]
        root=arraytoTree(arr,0,len(arr)-1)
        print("二叉树层次遍历结果:")
        PrintTreeLayer(root)
    
        reverseTree(root)
        print("
    反转后的二叉树层次遍历结果为:")
        PrintTreeLayer(root)
    
    二叉树层次遍历结果:
    4 2 6 1 3 5 7 
    反转后的二叉树层次遍历结果为:
    4 6 2 7 5 3 1
    

    十一.在二叉排序树中找出第一个大于中间值的结点

    首先根据二叉树的性质求出最大值和最小值.接下来对二叉树进行中序遍历

    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    def getMinNode(root):
        if root==None:
            return root
    
        while root.lchild!=None:
            root=root.lchild
    
        return root
    
    
    def getMaxNode(root):
        if root==None:
            return root
    
        while root.rchild!=None:
            root=root.rchild
    
        return root
    
    def getNode(root):
        maxNode=getMaxNode(root)
        minNode=getMinNode(root)
        mid=int((maxNode.data+minNode.data)/2)
    
        result=None
        while root!=None:
            if root.data<=mid:
                root=root.rchild
            else:
                result=root
                root=root.lchild
        return result
    
    def arraytoTree(arr,start,end):
        root=None
    
        if end>=start:
            root=BiTNode()
            mid=int((start+end+1)/2)
            root.data=arr[mid]
    
            root.lchild=arraytoTree(arr,start,mid-1)
            root.rchild=arraytoTree(arr,mid+1,end)
        else:
            root=None
    
        return root
    
    if __name__=="__main__":
        arr=[1,2,3,4,5,6,7]
        root=arraytoTree(arr,0,len(arr)-1)
        print(getNode(root).data)
    
    5
    

    **算法性能分析:**查找最大结点与最小结点的时间复杂度为O(h),h为二叉树的高度.对于有N个结点的二叉排序树,最大的高度为O(N),最小的高度为O(logN).综上所述:最好的情况下时间复杂度为O(logN),最坏的情况下为O(N)

    十二.在二叉树中找出路径最大的和

    import sys
    
    class BiTNode:
        def __init__(self):
            self.data=None
            self.lchild=None
            self.rchild=None
    
    
    class InRef:
        def __init__(self):
            self.val=None
    
    
    def Max(a,b,c):
        maxs=a if a>b else b
        maxs=maxs if maxs>c else c
        return maxs
    
    
    def FindMaxPathRecursive(root,maxs):
        if root==None:
            return 0
        else:
            sumLeft=FindMaxPathRecursive(root.lchild,maxs)
            sumRight=FindMaxPathRecursive(root.rchild,maxs)
    
            allMax=root.data+sumLeft+sumRight
            leftMax=root.data+sumLeft
            rightMax=root.data+sumRight
            tmpMax=Max(allMax,leftMax,rightMax)
    
            if tmpMax>maxs.val:
                maxs.val=tmpMax
    
            subMax=sumLeft if sumLeft>sumRight else sumRight
    
        return root.data+subMax
    
    def FindMaxPath(root):
        maxs=InRef()
        maxs.val=-sys.maxsize-1
        FindMaxPathRecursive(root,maxs)
        return maxs.val
    
    def constructTree1():
        root = BiTNode()
        node1 = BiTNode()
        node2 = BiTNode()
        node3 = BiTNode()
        node4 = BiTNode()
    
        root.data = 6
        node1.data = 3
        node2.data = -7
        node3.data = -1
        node4.data = 9
    
        root.lchild = node1
        root.rchild = node2
        node1.lchild = node3
        node1.rchild = node4
        return root
    
    def constructTree2():
        root = BiTNode()
        node1 = BiTNode()
        node2 = BiTNode()
    
        root.data = 2
        node1.data = 3
        node2.data = 5
    
    
        root.lchild = node1
        root.rchild = node2
        return root
    
    
    if __name__=="__main__":
        root1=constructTree1()
        print(FindMaxPath(root1))
    
        root2=constructTree2()
        print(FindMaxPath(root2))
    
    18
    10
    
  • 相关阅读:
    LA 2038 Strategic game(最小点覆盖,树形dp,二分匹配)
    UVA 10564 Paths through the Hourglass(背包)
    Codeforces Round #323 (Div. 2) D 582B Once Again...(快速幂)
    UVALive 3530 Martian Mining(贪心,dp)
    UVALive 4727 Jump(约瑟夫环,递推)
    UVALive 4731 Cellular Network(贪心,dp)
    UVA Mega Man's Mission(状压dp)
    Aizu 2456 Usoperanto (贪心)
    UVA 11404 Plalidromic Subsquence (回文子序列,LCS)
    Aizu 2304 Reverse Roads(无向流)
  • 原文地址:https://www.cnblogs.com/LQ6H/p/12940549.html
Copyright © 2011-2022 走看看