1、概述
属于树状结构的一种,每个节点最多只能有2个分叉,左边的是左子树,右边的是右子树。
2、存储方法
顺序存储
链式存储:1个元素域 + 2个地址域(左子树,右子树)
3、模拟二叉树
1. 定义 节点类,并初始化节点
需求:接收输入的元素,设置初始左、右子节点为None
# 1. 定义 节点类
class Node:
# 初始化节点
def __init__(self, item):
self.item = item # 元素域
self.lchild = None # 地址域:左子节点
self.rchild = None # 地址域:右子节点
2. 定义 二叉树类,并初始化二叉树
需求:2.1 接收二叉树的 根节点,没有默认初始值为None
# 2. 定义 二叉树类
class BinaryTree:
# 2.1 指定二叉树的 根节点
def __init__(self, root=None):
self.root = root
2.2 在二叉树类中,定义 添加数据 函数
需求:1. 接收要往二叉树中 添加的数据,首先判断根节点是否为空,若为空,则将输入的
元素设置为根节点,并结束程序;
2. 不为空,设置一个空列表,用于存储二叉树的所有节点,将 根节点 添加到列表中;
3. 设置死循环,从头开始获取 存储在列表中的所有节点,判断当前节点的 左子树 是
否为空,若为空则将 新节点添加为当前节点的 左子树,若不为空,则将当前节点
的左子树加到 列表中;判断右子树同上
# 2.2 添加元素
def add(self, item):
"""
往二叉树中 添加数据
:param item: 要添加的数据
:return:
"""
# 1. 判断 根节点是否为空,若为空,当前元素为根节点,程序结束
if self.root == None:
self.root = Node(item)
return
# 2. 不为空,用列表 存储 二叉树的所有节点
queue = []
queue.append(self.root)
# 3. 循环获取 二叉树中的 节点
while True:
cur_node = queue.pop(0)
# 4. 判断当前节点的 左子树 是否为空
if cur_node.lchild == None:
# 4.1 若为空, 则将: 新节点添加为当前节点的 左子树
cur_node.lchild = Node(item)
return
else:
# 4.2 如果不为空, 则将: 当前节点的左子树加到 队列中
queue.append(cur_node.lchild)
# 5. 判断当前节点的 右子树 是否为空
if cur_node.rchild == None:
# 5.1 若为空, 则将: 新节点添加为当前节点的 右子树
cur_node.rchild = Node(item)
return
else:
# 5.2 如果不为空, 则将: 当前节点的右子树加到 队列中
queue.append(cur_node.rchild)
2.3 在二叉树类中,定义 遍历(广度优先) 函数
需求:从根节点一层一层遍历
# 2.3 遍历,广度优先
def breadth_travel(self):
# 1. 判断 根节点是否为空
if self.root == None:
return
# 2. 创建队列 存储 二叉树的元素
queue = []
queue.append(self.root) # 添加根节点到队列中
# 3. 循环获取元素,只要队列不为空,就一直遍历
while len(queue) > 0:
# 3.1 队列有数据,从队头获取元素
node = queue.pop(0)
# 3.2 打印当前节点的内容
print(node.item, end=' ')
# 3.3 判断当前节点是否有左子树, 有就添加到 队列中
if node.lchild is not None:
queue.append(node.lchild)
# 3.4 判断当前节点是否有右子树, 有就添加到 队列中
if node.rchild is not None:
queue.append(node.rchild)
2.4 定义 遍历(深度优先)函数 => 前序:根,左,右
需求:按前序打印
# 2.4 遍历,深度优先 => 前序,即:根,左,右
def preorder_travel(self, root):
# 1. 判断 根节点 是否为空
if root is not None:
# 2. 有则打印
print(root.item, end=' ')
# 3. 再拿左子树
self.preorder_travel(root.lchild)
# 4. 最后拿右子树
self.preorder_travel(root.rchild)
2.5 定义 遍历(深度优先)函数 => 中序:左,根,右
需求:按中序打印
# 2.5 遍历,深度优先 => 中序,即:左,根,右
def inorder_travel(self, root): # root表示节点
# 1. 判断根节点是否不为空, 不为空, 就按照 左, 根, 右 顺序逐个获取.
if root is not None:
# 2. 左, 递归获取.
self.inorder_travel(root.lchild)
# 3. 根
print(root.item, end=' ')
# 4. 右, 递归获取.
self.inorder_travel(root.rchild)
2.6 定义 遍历(深度优先)函数 => 后序:左,右,根
需求:按后序打印
# 2.6 遍历,深度优先 => 后序,即:左,右,根
def postorder_travel(self, root): # root表示节点
# 1. 判断根节点是否不为空, 不为空, 就按照 左, 右, 根 顺序逐个获取.
if root is not None:
# 2. 左, 递归获取.
self.postorder_travel(root.lchild)
# 3. 右, 递归获取.
self.postorder_travel(root.rchild)
# 4. 根
print(root.item, end=' ')
3. 测试代码1
需求:创建节点 和 二叉树
# 3. 测试代码1,创建节点 和 二叉树
def test1():
# 3.1 创建节点
node = Node('小林')
# 3.2 打印节点
print(node.item)
# 3.3 创建二叉树对象
bt = BinaryTree(node)
print(bt) # 二叉树
print(bt.root) # 二叉树的根节点
print(bt.root.item) # 二叉树的根节点的元素域
4. 测试代码2
需求:演示队列,为先进先出
# 4. 测试代码2,演示队列,先进先出
def test2():
queue = []
queue.append('A')
queue.append('B')
queue.append('C')
print(queue.pop(0)) # [A,B,C] => A
print(queue.pop(0)) # [B,C] => B
print(queue.pop(0)) # [C] => C
5. 测试代码3
需求:添加元素到二叉树,广度优先遍历
# 5. 测试代码3,添加元素到二叉树,广度优先遍历
def test3():
# 5.1 创建二叉树
bt = BinaryTree()
# 5.2 添加元素
bt.add('A')
bt.add('B')
bt.add('C')
bt.add('D')
bt.add('E')
bt.add('F')
# 5.3 广度优先遍历, 查看结果
bt.breadth_travel()
print() # 换行美观
6. 测试代码4
需求:添加元素到二叉树,深度优先遍历(前序、中序、后序)
# 6. 测试代码4,添加元素到二叉树,深度优先遍历
def test4():
# 6.1 创建二叉树
bt = BinaryTree()
# 6.2 添加元素
bt.add('0')
bt.add('1')
bt.add('2')
bt.add('3')
bt.add('4')
bt.add('5')
bt.add('6')
bt.add('7')
bt.add('8')
bt.add('9')
# 6.3 深度优先, 前序
print('前序: ', end='')
bt.preorder_travel(bt.root)
print()
# 6.4 深度优先, 中序
print('中序: ', end='')
bt.inorder_travel(bt.root)
print()
# 6.5 深度优先, 后序
print('后序: ', end='')
bt.postorder_travel(bt.root)
7. 在 main函数中,调用测试函数
# 7. 在 main函数中,完成测试
if __name__ == '__main__':
test1()
test2()
test3()
test4()
完整代码:
# 1. 定义 节点类
class Node:
# 初始化节点
def __init__(self, item):
self.item = item # 元素域
self.lchild = None # 地址域:左子节点
self.rchild = None # 地址域:右子节点
# 2. 定义 二叉树类
class BinaryTree:
# 2.1 指定二叉树的 根节点
def __init__(self, root=None):
self.root = root
# 2.2 添加元素
def add(self, item):
"""
往二叉树中 添加数据
:param item: 要添加的数据
:return:
"""
# 1. 判断 根节点是否为空,若为空,当前元素为根节点,程序结束
if self.root == None:
self.root = Node(item)
return
# 2. 不为空,用列表 存储 二叉树的所有节点
queue = []
queue.append(self.root)
# 3. 循环获取 二叉树中的 节点
while True:
cur_node = queue.pop(0)
# 4. 判断当前节点的 左子树 是否为空
if cur_node.lchild == None:
# 4.1 若为空, 则将: 新节点添加为当前节点的 左子树
cur_node.lchild = Node(item)
return
else:
# 4.2 如果不为空, 则将: 当前节点的左子树加到 队列中
queue.append(cur_node.lchild)
# 5. 判断当前节点的 右子树 是否为空
if cur_node.rchild == None:
# 5.1 若为空, 则将: 新节点添加为当前节点的 右子树
cur_node.rchild = Node(item)
return
else:
# 5.2 如果不为空, 则将: 当前节点的右子树加到 队列中
queue.append(cur_node.rchild)
# 2.3 遍历,广度优先
def breadth_travel(self):
# 1. 判断 根节点是否为空
if self.root == None:
return
# 2. 创建队列 存储 二叉树的元素
queue = []
queue.append(self.root) # 添加根节点到队列中
# 3. 循环获取元素,只要队列不为空,就一直遍历
while len(queue) > 0:
# 3.1 队列有数据,从队头获取元素
node = queue.pop(0)
# 3.2 打印当前节点的内容
print(node.item, end=' ')
# 3.3 判断当前节点是否有左子树, 有就添加到 队列中
if node.lchild is not None:
queue.append(node.lchild)
# 3.4 判断当前节点是否有右子树, 有就添加到 队列中
if node.rchild is not None:
queue.append(node.rchild)
# 2.4 遍历,深度优先 => 前序,即:根,左,右
def preorder_travel(self, root):
if root is not None:
print(root.item, end=' ')
self.preorder_travel(root.lchild)
self.preorder_travel(root.rchild)
# 2.5 遍历,深度优先 => 中序,即:左,根,右
def inorder_travel(self, root): # root表示节点
# 1. 判断根节点是否不为空, 不为空, 就按照 左, 根, 右 顺序逐个获取.
if root is not None:
# 2. 左, 递归获取.
self.inorder_travel(root.lchild)
# 3. 根
print(root.item, end=' ')
# 4. 右, 递归获取.
self.inorder_travel(root.rchild)
# 2.6 遍历,深度优先 => 后序,即:左,右,根
def postorder_travel(self, root): # root表示节点
# 1. 判断根节点是否不为空, 不为空, 就按照 左, 右, 根 顺序逐个获取.
if root is not None:
# 2. 左, 递归获取.
self.postorder_travel(root.lchild)
# 3. 右, 递归获取.
self.postorder_travel(root.rchild)
# 4. 根
print(root.item, end=' ')
# 3. 测试代码1,创建节点 和 二叉树
def test1():
# 3.1 创建节点
node = Node('小林')
# 3.2 打印节点
print(node.item)
# 3.3 创建二叉树对象
bt = BinaryTree(node)
print(bt) # 二叉树
print(bt.root) # 二叉树的根节点
print(bt.root.item) # 二叉树的根节点的元素域
# 4. 测试代码2,演示队列,先进先出
def test2():
queue = []
queue.append('A')
queue.append('B')
queue.append('C')
print(queue.pop(0)) # [A,B,C] => A
print(queue.pop(0)) # [B,C] => B
print(queue.pop(0)) # [C] => C
# 5. 测试代码3,添加元素到二叉树,广度优先遍历
def test3():
# 5.1 创建二叉树
bt = BinaryTree()
# 5.2 添加元素
bt.add('A')
bt.add('B')
bt.add('C')
bt.add('D')
bt.add('E')
bt.add('F')
# 5.3 广度优先遍历, 查看结果
bt.breadth_travel()
print() # 换行美观
# 6. 测试代码4,添加元素到二叉树,深度优先遍历
def test4():
# 6.1 创建二叉树
bt = BinaryTree()
# 6.2 添加元素
bt.add('0')
bt.add('1')
bt.add('2')
bt.add('3')
bt.add('4')
bt.add('5')
bt.add('6')
bt.add('7')
bt.add('8')
bt.add('9')
# 6.3 深度优先, 前序
print('前序: ', end='')
bt.preorder_travel(bt.root)
print()
# 6.4 深度优先, 中序
print('中序: ', end='')
bt.inorder_travel(bt.root)
print()
# 6.5 深度优先, 后序
print('后序: ', end='')
bt.postorder_travel(bt.root)
# 7. 在 main函数中,完成测试
if __name__ == '__main__':
test1()
test2()
test3()
test4()
挑战成功,太棒啦~