二叉树
一.把一个有序整数数组放到二叉树中
首先取数组的中间结点作为二叉树的根结点,把数组分成左右两部分,然后对于数组的左右两部分子数组分别运用同样的方法进行二叉树的构建,依此类推
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