# Python 实现二叉树的创建、二叉树的添加、二叉树的删除、二叉树的修改、二叉树的查找、二叉树的的遍历 最详细的二叉树 增 删 改 查

### 二叉树的创建、添加和遍历

• 因为我之前文章>>>二叉树详解 已经详细写了二叉树的创建以及二叉树的广度和深度遍历，这里就不重复叙述实现过程，直接将代码规范书写如下：
class TreeNote(object): # 创建树的结点
def __init__(self, val=-1):
self.val = val
self.left = None
self.right = None

class BinaryTree(object): # 创建二叉树
def __init__(self):
self.root = None # 根结点

node = TreeNote(val)
if self.root is None:
self.root = node
return
queue = [self.root]
while queue:
temp_node = queue.pop(0)
if temp_node.left is None:
temp_node.left = node
return
else:
queue.append(temp_node.left)
if temp_node.right is None:
temp_node.right = node
return
else:
queue.append(temp_node.right)

def bre_order(self, node):  # 二叉树的广度遍历
if node is None:
return
queue = [node]
while queue:
temp_node = queue.pop(0)
print(temp_node.val, end=" ")
if temp_node.left is not None:
queue.append(temp_node.left)
if temp_node.right is not None:
queue.append(temp_node.right)

'''递归实现二叉树的三种深度遍历'''
# def pre_order(self, node):  # 二叉树的前序遍历（递归）
#     if node is None:
#         return
#     print(node.val, end=" ")
#     self.pre_order(node.left)
#     self.pre_order(node.right)
#
# def in_order(self, node):  # 二叉树的中序遍历（递归）
#     if node is None:
#         return
#     self.in_order(node.left)
#     print(node.val, end=" ")
#     self.in_order(node.right)
#
# def post_order(self, node): # 二叉树的后序遍历（递归)
#     if node is None:
#         return
#     self.post_order(node.left)
#     self.post_order(node.right)
#     print(node.val, end=" ")

'''非递归实现二叉树的三种深度遍历'''
def pre_order(self, node):
if node is None:
return
stack = []
temp_node = node
while temp_node or stack:
while temp_node:
print(temp_node.val, end=" ")
stack.append(temp_node)
temp_node = temp_node.left
node = stack.pop()
temp_node = node.right

def in_order(self, node):
if node is None:
return
stack = []
temp_node = node
while temp_node or stack:
while temp_node:
stack.append(temp_node)
temp_node = temp_node.left
node = stack.pop()
print(node.val, end=" ")
temp_node = node.right

def post_order(self, node):  # 二叉树的后序遍历（非递归)
if node is None:
return None
stack = []
temp_node = node
while temp_node or stack:
while temp_node:
stack.append(temp_node)
temp_node = temp_node.left
left_node = stack[-1]
temp_node = left_node.right
if temp_node is None:
node = stack.pop()
print(node.val, end=" ")
while stack and node == stack[-1].right:
node = stack.pop()
print(node.val, end=" ")

if __name__ == '__main__':
t = BinaryTree()
for i in range(10):
print("\n广度遍历为:")
t.bre_order(t.root)
print("\n前序遍历为：")
t.pre_order(t.root)
print("\n中序遍历为：")
t.in_order(t.root)
print("\n后序遍历为：")
t.post_order(t.root)

'''

0 1 2 3 4 5 6 7 8 9

0 1 3 7 8 4 9 2 5 6

7 3 8 1 9 4 0 5 2 6

7 8 3 9 4 1 5 6 2 0
'''


### 二叉树的查找与修改

#### 查找指定元素的父结点

• 还是以为这下图为例，我们先来实现如何查找到给定值的父结点
• 整体思路用的是广度遍历，一层一层的去判断，并添加每一个结点的左右子结点，然后重复判断
class TreeNode(object):
def __init__(self, val=-1):
self.val = val
self.left = None
self.right = None

class BinaryTree(object):
def __init__(self):
self.root = None

node = TreeNode(val)
if self.root is None:
self.root = node
return
queue = [self.root]
while queue:
temp_node = queue.pop(0)
if temp_node.left is None:
temp_node.left = node
return
else:
queue.append(temp_node.left)
if temp_node.right is None:
temp_node.right = node
return
else:
queue.append(temp_node.right)

def get_parent(self, val):  # 二叉树查找父结点
if self.root.val == val:  # 根结点没有父结点
return None
queue = [self.root]
while queue:
temp_node = queue.pop(0)
if temp_node.left and temp_node.left.val == val:
return temp_node
if temp_node.right and temp_node.right.val == val:
return temp_node
if temp_node.left:
queue.append(temp_node.left)
if temp_node.right:
queue.append(temp_node.right)
return None

if __name__ == '__main__':
t = BinaryTree()
for i in range(10):
print(t.get_parent(2).val) # 如要查找值为2的结点的父结点，结果为 0 即是根结点


#### 查找指定值/结点、修改指定值/结点

• 分别用广度、深度三种方式来实现查找指定值，如果找到则返回该结点，并打印该结点值，没找到则返回空
• 分别测试查找一个指定值，所花费的次数，注意测试次数和选定的结点数值位置有关
class TreeNode(object):
def __init__(self, val=-1):
self.val = val
self.left = None
self.right = None

class BinaryTree(object):
def __init__(self):
self.root = None

node = TreeNode(val)
if self.root is None:
self.root = node
return
queue = [self.root]
while queue:
temp_node = queue.pop(0)
if temp_node.left is None:
temp_node.left = node
return
else:
queue.append(temp_node.left)
if temp_node.right is None:
temp_node.right = node
return
else:
queue.append(temp_node.right)

def bre_search(self, val):  # 二叉树广度查找
print("进入广度查找") # 进入，需要直接比较根结点
if self.root.val == val:
return self.root
queue = [self.root]
while queue:
temp_node = queue.pop(0)
print("进入广度查找") # 注意计算比较次数的位置
if temp_node.left and temp_node.left.val == val:
return temp_node.left
print("进入广度查找") # 第二条分支也应当有一个
if temp_node.right and temp_node.right.val == val:
return temp_node.right
if temp_node.left:
queue.append(temp_node.left)
if temp_node.right:
queue.append(temp_node.right)
return None

def pre_search(self, node, val):  # 二叉树前序查找（递归）
if node is None:
return
print("进入前序查找") # 比较次数进入位置
if node.val == val:
return node
left_part = self.pre_search(node.left, val)
if left_part:
return left_part
right_part = self.pre_search(node.right, val)
if right_part:
return right_part
return None

def in_search(self, node, val):  # 二叉树中序查找（递归）
if node is None:
return
left_part = self.in_search(node.left, val)
if left_part:
return left_part
print("进入中序查找") # 从这里开始计算比较
if node.val == val:
return node
right_part = self.in_search(node.right, val)
if right_part:
return right_part
return None

def post_search(self, node, val):  # 二叉树后序查找（递归）
if node is None:
return
left_part = self.post_search(node.left, val)
if left_part:
return left_part
right_part = self.post_search(node.right, val)
if right_part:
return right_part
print("进入后序查找") # 从这里开始计算比较
if node.val == val:
return node
return None

if __name__ == '__main__':
t = BinaryTree()
for i in range(10):
# 广度查找
bre_res = t.bre_search(4)
if bre_res:
print(bre_res.val)
else:
print(bre_res)
# 前序查找
pre_res = t.pre_search(t.root, 4)
if pre_res:
print(pre_res.val)
else:
print(pre_res)
# 中序查找
in_res = t.in_search(t.root, 4)
if in_res:
print(in_res.val)
else:
print(in_res)
# 后序查找
post_res = t.post_search(t.root, 4)
if post_res:
print(post_res.val)
else:
print(post_res)
'''输出结果:

4

4

4

4
'''

• 上述示例以查找结点4值为4，比较四种遍历方式所花费次数，广度遍历 依次为：[0,1,2,3,4] 所以是5次，分别在根结点，左右子结点处发生比较；前序遍历依 次为[0,1,3,7,8,4] 所以是6次；中序遍历 依次为：[7,3,8,1,9,4] 所以是6次；后序遍历 依次为：[7,8,3,9,4] 所以是5次，可以对比下图，去验证一下！
• 关于二叉树的修改和二叉树查找原理是一样的，只需要用四种查找方式的一种先找到要修改的结点，然后返回该结点，把新的值赋值给该结点的val就可以了，这里就不加赘述了！

### 二叉树的删除

• 二叉树的删除，真正的操作是在二叉搜索树的基础上来实现的，至于二叉搜索树（二叉排序树）的删除会另开文章详解

• 这里仅叙述二叉树如何删除节点，而且规定：

• 如要要删除非叶子结点，就把它的左右子树都删除，即：如果要删的不是非叶子结点，删除它就连同它的左右子树一起删除；这是因为二叉树通常“指向”都是从根指向叶子，只能去找它的左右子树结点，而无法去找它的“根结点”（下面这种情况，通过写一个方式可以找各个“根结点”）；这种情况用递归能很好完成！

class TreeNode(object):
def __init__(self, val=-1):
self.val = val
self.left = None
self.right = None

class BinaryTree(object):
def __init__(self):
self.root = None
self.flag = False # 主函数输出判断

node = TreeNode(val)
if self.root is None:
self.root = node
return
queue = [self.root]
while queue:
temp_node = queue.pop(0)
if temp_node.left is None:
temp_node.left = node
return
else:
queue.append(temp_node.left)
if temp_node.right is None:
temp_node.right = node
return
else:
queue.append(temp_node.right)

def pre_oreder(self, node):  # 用前序遍历来测试 删除前和删除后的数据
if node is None:
return
stack = []
temp_node = node
while temp_node or stack:
while temp_node:
print(temp_node.val, end=" ")
stack.append(temp_node)
temp_node = temp_node.left
node = stack.pop(-1)
temp_node = node.right

def del_val(self, node, val):
if node is None:
return
if node.val == val and node == self.root: # 如果删除的是根结点，直接置空，然后退出
self.root = None
return
if node.val == val: # 找到了该结点，将当前结点左右置空，然后返回该结点的值
node.left = None
node.right = None
return node.val # 返回结点值来提供判断条件，如果有返回值，说明找到了，没有则没找到
left_part = self.del_val(node.left, val)
if left_part: # 如果左侧有返回值，说明找到了，将当前层的结点的左侧置为空即可
self.flag = True
node.left = None
right_part = self.del_val(node.right, val) # 如果左侧递归到最后一个左结点，返回值还是空，就从左侧最后一层，开始向右递归
if right_part:
self.flag = True
node.right = None
return None # 如果遍历完二叉树，发现都没找到，说明要删除的值二叉树不存在

if __name__ == '__main__':
t = BinaryTree()
for i in range(10):
print("删除前:")
t.pre_oreder(t.root)
print()
del_res = t.del_val(t.root, 1)
# del_res = t.del_val(t.root, 16) # "要删除的值，二叉树中不存在"
# del_res = t.del_val(t.root, 0)  # "删除根结点，二叉树置空"
if del_res == -1:
print("删除根结点，二叉树置空")
elif t.flag:
print("删除后:")
t.pre_oreder(t.root)
elif not t.flag:
print("要删除的值，二叉树中不存在")
'''

0 1 3 7 8 4 9 2 5 6

0 2 5 6
'''
'''

'''


• 如果不删除二叉树的根结点（如果删除根结点，需要按照二叉搜索树的变换规则），这里规定不删除二叉树的第一个结点，那么可以这样实现：

（1）关键是 先获取 待删除节点值 val 的父节点，上面查找里已经写了获取父结点的方法，这里直接拿来用就可以了！具体操作过程如下：

class TreeNode(object):
def __init__(self, val=-1):
self.val = val
self.left = None
self.right = None

class BinaryTree(object):
def __init__(self):
self.root = None

node = TreeNode(val)
if self.root is None:
self.root = node
return
queue = [self.root]
while queue:
temp_node = queue.pop(0)
if temp_node.left is None:
temp_node.left = node
return
else:
queue.append(temp_node.left)
if temp_node.right is None:
temp_node.right = node
return
else:
queue.append(temp_node.right)

def pre_oreder(self, node):  # 用前序遍历来测试 删除前和删除后的数据
if node is None:
return
stack = []
temp_node = node
while temp_node or stack:
while temp_node:
print(temp_node.val, end=" ")
stack.append(temp_node)
temp_node = temp_node.left
node = stack.pop(-1)
temp_node = node.right

def get_parent(self, val):  # 二叉树查找父结点
if self.root.val == val:  # 根结点没有父结点
return None
queue = [self.root]
while queue:
temp_node = queue.pop(0)
if temp_node.left and temp_node.left.val == val:
return temp_node
if temp_node.right and temp_node.right.val == val:
return temp_node
if temp_node.left:
queue.append(temp_node.left)
if temp_node.right:
queue.append(temp_node.right)
return None

def del_val(self, val):
if self.root is None:  # 如果根为空，直接返回
return False
parent = self.get_parent(val)  # 获取到要删除节点值得父结点
if parent:
del_node = parent.left if parent.left.val == val else parent.right  # 待删除节点
if del_node.left is None:  # 左子树为空
if parent.left.val == val:
parent.left = del_node.right
else:
parent.right = del_node.right
del del_node
return True
elif del_node.right is None:  # 右子树为空
if parent.left.val == val:
parent.left = del_node.left
else:
parent.right = del_node.left
del del_node
return True
else:  # 左右子树都不为空
tmp_pre = del_node
tmp_next = del_node.right
if tmp_next.left is None:
# 替代
tmp_pre.right = tmp_next.right
tmp_next.left = del_node.left
tmp_next.right = del_node.right
else:
while tmp_next.left:  # 让tmp指向右子树的最后一个叶子
tmp_pre = tmp_next
tmp_next = tmp_next.left
# 替代
tmp_pre.left = tmp_next.right
tmp_next.left = del_node.left
tmp_next.right = del_node.right
if parent.left.val == val:
parent.left = tmp_next
else:
parent.right = tmp_next
del del_node
return True
else:
return False

if __name__ == '__main__':
t = BinaryTree()
for i in range(10):
print("删除前:")
t.pre_oreder(t.root)
print()
print(t.del_val(4))
print("删除后:")
t.pre_oreder(t.root)

''' 输出结果：可以对照上面的图比较下

0 1 3 7 8 4 9 2 5 6
True

0 1 3 7 8 9 2 5 6
'''


12-05

03-15 2275
09-20 2644
10-28 495
04-25 115
06-13 31
05-07 544
02-24 3384
07-22 1572
08-22 629