二叉树

二叉树

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

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

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("\n")

    root=arraytotree(arr,0,len(arr)-1)
    print("转成树的中序遍历为:")
    printTreeMidOrder(root)

    print("\n")
    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("\n")
    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("\n新的二叉树中序遍历:")
    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("\n")

    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("\n反转后的二叉树层次遍历结果为:")
    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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值