一、题目
- Tree Traversals Again :
链接:https://pintia.cn/problem-sets/1340842164139356160/problems/1371047298293096448
思考:根据Push和Pop环节分别给出了该树的先序遍历和中序遍历,找到该树的后序遍历。
可以根据先序和中序建树,然后再对树进行后序遍历;
也可直接根据先序和中序确定后序。
- 是否同一棵二叉搜索树:
链接:https://pintia.cn/problem-sets/1340842164139356160/problems/1373201693693399040
思考:根据输入序列,建树,然后判断是否是同一棵树,建树过程与楼上类似.
- Root of AVL Tree :
链接:https://pintia.cn/problem-sets/1340842164139356160/problems/1373201693693399041
思考:仍然是建树,但是这次建树过程与楼上不同的是,需要建立平衡二叉树,因此插入节点时,一旦不平衡,就需要进行旋转,有LL LR RR RL四种情况。
同时还需要动态跟进二叉树深度来判断现在该树是不是被破坏平衡了。
树建立好之后,输出根节点即可。
4. Complete Binary Search Tree :
链接:https://pintia.cn/problem-sets/1340842164139356160/problems/1373201693693399042
思考:需要同时考虑完全二叉树 二叉树搜索树的性质。
可以分为两种解法:
1.我觉得这种解法非常厉害,而且与网上很多人给出的解法不一样,更简洁明了。具体如下:
如果生成的树同时具备完全二叉树和二叉搜索树的性质,可以发现,如果对该树中序遍历,它是从小到大进行遍历的,对输入的数组进行排序,即可知中序遍历顺序。此时可以再想到完全二叉树的性质,左右子节点是2i,2i+1,对该二叉树进行中序遍历,即可将排序后的数组依次填入二叉树中。
2.第二种方法是先序遍历,先找根,根据完全二叉树和二叉搜索树的性质,知道总的节点个数,可以判断出根节点的位置,然后下放到左右子节点,继续找根节点的位置。因为是二叉搜索树,所以左边的一定都小于根节点,右边一定都大于,对于排序后的数组,可以很快锁定根节点的值。找根节点的思路如图:
二、解法
Tree Traversals Again
- 先建树,随后后序遍历。思路为:若树节点空,则建立根节点root,父节点father。随后对于Push操作,先创立节点压入栈,若左子树为空,则插入到左子树,更新父节点,不然插入到右子树,更新父节点。对于Pop操作,栈顶节点弹出并将弹出的节点更新为父节点。建树结束后,采用后序遍历树的递归算法得到答案。
#定义节点和栈的类以及方法
class Stack:
def __init__(self):
self.items = []
def Push(self,val):
self.items.append(val)
def Pop(self):
return self.items.pop()
class Node:
def __init__(self,val):
self.val = val
self.left = None
self.right = None
res = []
def postOrderTravel(tree):
if tree.left:
postOrderTravel(tree.left)
if tree.right:
postOrderTravel(tree.right)
res.append(tree.val)
number = int(input())
father = None
stack = Stack()
for i in range(2*number):
text = input()
if text == "Pop":
father =stack.Pop()
else:
text,value = text.split()
if not father:
newNode = Node(value)
root = newNode
stack.Push(newNode)
elif father.left == None:
newNode = Node(value)
stack.Push(newNode)
father.left = newNode
else:
newNode = Node(value)
stack.Push(newNode)
father.right = newNode
father = newNode
postOrderTravel(root)
print(" ".join(res))
- 根据前序和中序直接找到后序遍历:前序的第一个必为根,将其确定为后序的最后一个,之后在中序中找到根,从而确定该树左右子树的个数,继续在左右子树中寻找左右子树的后序遍历,采用递归实现,结束递归条件为,序列为零直接return,若树的个数为一,则前中后遍历一样,记住该数的位置,return.
class Stack:
def __init__(self):
self.items = []
def Push(self,val):
self.items.append(val)
def Pop(self):
return self.items.pop()
def ascertainPost(pre,mid,post,n):
#pre mid post 分别为该树的前序 中序 后序的数组起始位置 n 为该树的个数
if n == 0:
return
if n == 1:
postOrder[post] = preOrder[pre]
return
# 前序遍历的第一个数必为该树的根
root = preOrder[pre]
#则其为该树后序遍历的最后一个数
postOrder[post+n-1]=root
#根据根在中序遍历的位置 确定该树左右子树的数量
for i in range(n):
if inOrder[mid + i] == root:
break
leftChild = i
rightChild = n-i-1
#分别堆左右子树继续递归 更新 pre mid post为左右子树的pre mid post
ascertainPost(pre+1,mid,post,leftChild)
ascertainPost(pre+leftChild+1,mid+leftChild+1,post+leftChild,rightChild)
number = int(input())
preOrder = []
inOrder = []
postOrder = [0]*number
stack = Stack()
for i in range(2*number):
text = input()
if text == "Pop":
inOrder.append(stack.Pop())
else:
stack.Push(text.split()[1])
preOrder.append(text.split()[1])
ascertainPost(0,0,0,number)
print(" ".join(postOrder))
是否同一棵二叉搜索树
class binarySearchTree:
def __init__(self,val=None):
self.value = val
self.leftChild = None
self.rightChild = None
# 将节点依次插入到二叉搜索树中
def insert(self,node):
if self.value < node.value:
if self.leftChild == None:
self.leftChild = node
else:
return self.leftChild.insert(node)
else:
if self.rightChild == None:
self.rightChild = node
else:
return self.rightChild.insert(node)
def buildTree(alist):
root=binarySearchTree(alist[0])
for i in alist[1:]:
node = binarySearchTree(i)
root.insert(node)
return root
# 判断两棵树是否相等 用递归的方法
def isSame(root1,root2):
if root1 == root2 == None:
return True
if root1 and root2 :
if root1.value == root2.value:
return isSame(root1.leftChild,root2.leftChild) and isSame(root1.rightChild,root2.rightChild)
else:
return False
text = input()
while text != "0":
N,L = text.split()
initList = list(map(int,input().split()))
initTree = buildTree(initList)
for _ in range(int(L)):
comparList = list(map(int,input().split()))
comparTree = buildTree(comparList)
if isSame(initTree,comparTree):
print("Yes")
else:
print("No")
text = input()
Root of AVL Tree
class node:
def __init__(self,value = None):
self.value = value
self.leftChild = None
self.rightChild = None
def buildTree():
no = list(map(int,input().split()))
root = node(no[0])
for num in no[1:]:
root = insert(root,num)
return root
def height(root):
if root == None:
return 0
else:
return max(height(root.leftChild),height(root.rightChild))+1
def LLrotation(root):
br = root.leftChild.rightChild
a = root
root = root.leftChild
a.leftChild = br
root.rightChild = a
return root
def LRrotation(root):
c = root.leftChild.rightChild
cr = root.leftChild.rightChild.rightChild
cl = root.leftChild.rightChild.leftChild
b = root.leftChild
a = root
root = c
root.leftChild = b
root.rightChild = a
b.rightChild = cl
a.leftChild = cr
return root
def RRrotation(root):
b = root.rightChild
bl = root.rightChild.leftChild
a = root
root = b
b.leftChild = a
a.rightChild = bl
return root
def RLrotation(root):
c = root.rightChild.leftChild
b = root.rightChild
a = root
cl = root.rightChild.leftChild.leftChild
cr = root.rightChild.leftChild.rightChild
root = c
c.leftChild = a
c.rightChild = b
a.rightChild = cl
b.leftChild =cr
return root
def insert(root,newNode):
if root == None:
root = node(newNode)
else:
if newNode < root.value:
root.leftChild = insert(root.leftChild,newNode)
if abs(height(root.leftChild)-height(root.rightChild) == 2):
if newNode < root.leftChild.value:
root = LLrotation(root)
else:
root = LRrotation(root)
else:
root.rightChild = insert(root.rightChild,newNode)
if abs(height(root.rightChild) - height(root.leftChild) == 2):
if newNode > root.rightChild.value:
root = RRrotation(root)
else:
root = RLrotation(root)
return root
number = int(input())
root = buildTree()
print(root.value)
Complete Binary Search Tree
def inOrder(root):
if root > number:
return
inOrder(root*2)
global index
treeArray[root] = sortList[index]
index += 1
inOrder(root*2+1)
number = int(input())
treeArray = [0]*(number+1)
index = 0
sortList = list(map(int,input().split()))
sortList.sort()
inOrder(1)
print(" ".join(list(map(str,treeArray[1:]))))
import math
# 找根节点的位置
def getLeft(n):
H = int(math.log2(n+1))
X = n+1-2**H
L = (2**(H-1)-1)+min(X,2**(H-1))
return L
# 先序遍历根节点 并填入值
def solve(left,right,root):
n = right-left+1
if n == 0:
return
leftIndex = getLeft(n)
treeArray[root] = sortList[left+leftIndex]
solve(left,left+leftIndex-1,root*2)
solve(left+leftIndex+1,right,root*2+1)
number = int(input())
treeArray = [0]*(number+1)
sortList = list(map(int,input().split()))
sortList.sort()
solve(0,number-1,1)
print(" ".join(list(map(str,treeArray[1:]))))
总结
对于二叉树的结构,节点的插入,二叉树的平衡转换操作,二叉树的深度,有了更清晰的认识。