平衡二叉树
什么是平衡二叉树
平衡二叉树指,每个节点的左右子树高度差绝对值不大于1的二叉树。
相较于普通二叉树,平衡二叉树把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。解决了普通二叉树退化成链表的问题。时间上更加稳定。但是将普通的二叉树转换为平衡二叉树的过程中,不断地旋转会牺牲掉O(logN)左右的时间。
判断平衡二叉树
LeetCode 110
判断一棵二叉树是否平衡
解题思路:由根节点向下进行深度搜索
代码实现:
def isBalanced(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
left_length = self.maxDepth(root.left) # 左子树高度
right_length = self.maxDepth(root.right) # 右子树高度
delta_length = abs(left_length - right_length) # 子树高度差
if delta_length < 2: # 当前节点符合要求
if left_length == 0 or right_length == 0: # 子树到达底端
return True
else: # 继续深度搜索
return self.isBalanced(root.left) and self.isBalanced(root.right)
else: # 不平衡
return False
如何使二叉树平衡
平衡,指通过旋转的方式使当前节点的左子树与右子树的高度差减少到1以内。
右旋
当左子树高度大于右子树高度时,我们进行右旋操作
当左节点下只有一个子节点时
1 2
/ \ / \
2 3 4 1
/ => / \
4 5 3
/
5
当左节点含有两个子节点时
1 2
/ \ / \
2 3 4 1
/ \ => / / \
4 5 6 5 3
/
6
代码实现
def right_rotate(parent):
# 打印右旋前的树结构
print('before right rotate')
print(parent.val)
show_data([parent])
print('\n\n\n\n')
child = parent.left
parent.left = child.right
child.right = parent
# 打印右旋后的树结构
print('\n\n\n\n after right rotate')
print(child.val)
show_data([child])
print('\n\n\n\n')
return child
左旋
当右子树高度大于左子树高度时,我们进行左旋操作
当右节点下只有一个子节点时
1 3
/ \ / \
2 3 1 4
\ => / \
4 2 5
\
5
当右节点含有两个子节点时
1 3
/ \ / \
2 3 1 5
/ \ => / \ \
4 5 2 4 6
\
6
代码实现
def left_rotate(parent):
# 打印左旋前的树结构
print('before left rotate')
print(parent.val)
show_data([parent]) #
print('\n\n\n\n')
child = parent.right
parent.right = child.left
child.left = parent
# 打印左旋后的树结构
print('\n\n\n\n after left rotate')
print(child.val)
show_data([child])
return child
将链表以旋转的形式转换为平衡二叉树
代码
def sortedArrayToBST(self, nums):
"""
:type nums: List[int]
:rtype: TreeNode
"""
def conunterweigh(root, direction):
left_length = self.maxDepth(root.left)
right_length = self.maxDepth(root.right)
delta_length = left_length - right_length
if left_length <= 2 and right_length <= 2 and 1 >= delta_length >= -1:
self.stack.append(root)
return
elif 1 >= delta_length >= -1:
self.stack.append(root)
conunterweigh(root.left, 'l')
self.stack.append(root)
conunterweigh(root.right, 'r')
elif delta_length > 1:
if direction == 'l':
self.stack[-1].left = right_rotate(root)
conunterweigh(self.stack[-1].left, direction)
elif direction == 'r':
self.stack[-1].right = right_rotate(root)
conunterweigh(self.stack[-1].right, direction)
else:
root = right_rotate(root)
conunterweigh(root, direction)
elif delta_length < -1:
if direction == 'l':
self.stack[-1].left = left_rotate(root)
conunterweigh(self.stack[-1].left, direction)
elif direction == 'r':
self.stack[-1].right = left_rotate(root)
conunterweigh(self.stack[-1].right, direction)
else:
root = left_rotate(root)
conunterweigh(root, direction)
self.stack = []
item = TreeNode(nums.pop())
root = item
for num in nums[::-1]:
item.left = TreeNode(num)
item = item.left
conunterweigh(root, '')
return self.stack[0]
LeetCode 108 将有序数组转换为平衡二叉树
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
示例
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
代码实现
运用二分法,将数组对半分配给左右子树
class Solution:
def half(self, nums):
length = len(nums)
if length > 3:
root = TreeNode(nums[length // 2 - 1])
print(root.val)
print(nums[0:length // 2 - 1])
print(nums[length // 2:length])
root.left = self.half(nums[0:length // 2 - 1])
root.right = self.half(nums[length // 2:length])
elif length == 3:
root = TreeNode(nums[1])
root.left = TreeNode(nums[0])
root.right = TreeNode(nums[2])
elif length == 2:
root = TreeNode(nums[1])
root.left = TreeNode(nums[0])
elif length == 1:
root = TreeNode(nums[0])
else:
root = None
return root
def sortedArrayToBST(self, nums):
return self.half(nums)