二叉树需要实现的功能及思路
-
找到最小值
没什么好说的就是二叉树最左下的顶点
-
找到最大值
没什么好说的就是二叉树最右下的顶点
-
插入
分情况,如果二叉树为空那么直接直接设置成根节点就好了。否则就逐层向下,比当前小的往左边方向,否则往右边方向
-
删除
为了要实现删除的功能,我们先定义一个方法,它返回的是被删除的节点和它的父节点,返回形式为tuple,即(parent,node)
这个就比较复杂了,分三种情况:
-
被删除的节点没有子节点
再分为两种:
- 有父节点:看是父节点的左节点还是右节点,将对应的赋为None
- 无父节点:很明显这就是根节点本身了,直接赋为None就好了
-
被删除的节点有1个子节点
将返回的父节点直接链接到被删除节点的子节点,用一张图说明就是:
具体去代码中感受就好
-
被删除的节点有2个子节点
这种情况要么找左子树的最右边节点或者右子树的最左节点(由二叉树的定义可知)
-
-
查找某个节点
就是从根节点开始,根据大小关系逐层往下找就好了
-
先序/中序/后序遍历
代码不同的一行在于输出当前节点的语句的位置,具体看代码
-
宽度优先遍历
也就是逐层遍历,通过队列实现,将根节点入队,然后扫描左右节点,分别入队,这样出队的时候一定是左边的节点先出来,子节点在入队。入队-出队持续到队列为空为止。
代码
from collections import deque
class Node:
def __init__(self, data=None):
self.data = data
self.left_child = None
self.right_child = None
class Tree:
def __init__(self):
self.root_node = None
def find_min(self):
current = self.root_node
while current.left_child:
current = current.left_child
return current
def find_max(self):
current = self.root_node
while current.right_child:
current = current.right_child
return current
def insert(self, data):
node = Node(data)
if self.root_node is None:
self.root_node = node
else:
current = self.root_node
parent = None
while True:
parent = current
if node.data < current.data:
current = current.left_child
if current is None:
parent.left_child = node
return
else:
current = current.right_child
if current is None:
parent.right_child = node
return
def get_node_with_parent(self, data):
current = self.root_node
parent = None
if current is None:
return (parent,None)
while True:
if current.data == data:
return (parent,current)
elif current.data > data:
parent = current
current = current.left_child
else:
parent = current
current = current.right_child
return (parent,current)
def remove(self, data):
parent, node = self.get_node_with_parent(data)
if parent is None and node is None:
return False
children_count = 0
if node.left_child and node.right_child:
children_count = 2
elif (node.left_child is None) and (node.right_child is None):
children_count = 0
else:
children_count = 1
if children_count == 0:
if parent:
if parent.right_child is node:
parent.right_child = None
else:
parent.left_child = None
else: #只有根节点
self.root_node = None
elif children_count == 1:
'''要删除的节点有一个子节点'''
next_node = None
if node.left_child:
next_node = node.left_child
else:
next_node = node.right_child #确定子节点是在左边还是在右边
if parent:
if parent.left_child is node:
parent.left_child = next_node
else:
parent.right_child = next_node
else:
self.root_node = next_node
else:
'''要么找左子树的最右边节点或者右子树的最左节点'''
parent_of_leftmost_node = node
leftmost_node = node.right_child #右边的顶点才会比要被删除的节点大
while leftmost_node.left_child:
parent_of_leftmost_node = leftmost_node
leftmost_node = leftmost_node.left_child #找到最左下的顶点,保持平衡性,这个是右子树的最小节点
node.data = leftmost_node.data
if parent_of_leftmost_node.left_child == leftmost_node:
parent_of_leftmost_node.left_child = leftmost_node.right_child
else:
parent_of_leftmost_node.right_child = leftmost_node.right_child
def search(self, data):
current = self.root_node
while True:
if current is None:
return None
elif current.data == data:
return data
elif current.data > data:
current = current.left_child
else:
current = current.right_child
def inorder(self, root_node):
current = root_node
if current is None:
return
self.inorder(current.left_child)
print(current.data)
self.inorder(current.right_child)
def preorder(self, root_node):
current = root_node
if current is None:
return
print(current.data)
self.preorder(current.left_child)
self.preorder(current.right_child)
def postorder(self, root_node):
current = root_node
if current is None:
return
self.postorder(current.left_child)
self.postorder(current.right_child)
print(current.data)
def breadth_first_traversal(self):
list_of_nodes = []
traversal_queue = deque([self.root_node])
while len(traversal_queue) > 0:
node = traversal_queue.popleft()
list_of_nodes.append(node.data)
if node.left_child:
traversal_queue.append(node.left_child)
if node.right_child:
traversal_queue.append(node.right_child)
return list_of_nodes