本文介绍了二叉树入门知识,涵盖了二叉树的基本概念、特性、表示方法和遍历方法。此外,文章还详细讲解了二叉树的常见操作,如插入和删除节点,并提供了二叉树在实际应用中的实例。
二叉树的基本概念二叉树的定义
二叉树是一种特殊的树形数据结构,每个节点最多有两个子节点,分别被称为左子节点和右子节点。这使得二叉树结构在很多算法中都有广泛的应用。二叉树的定义可以通过递归的方式来描述:一个节点和两个互不相交的二叉树的集合,这两棵二叉树分别称为该节点的左子树和右子树。
二叉树的特性
- 最多有两个子节点:每个节点最多有两个子节点,分别称为左子节点和右子节点。
- 根节点:一棵二叉树必须有一个根节点,它是树的最高层级节点。
- 叶子节点:叶子节点是没有任何子节点的节点。
- 深度与高度:根节点到叶子节点的最长路径的边数称为二叉树的深度或高度。
- 满二叉树:所有叶子节点都在同一层,且每个非叶子节点都有两个子节点的二叉树。
- 完全二叉树:除了最后一层外,每一层都是满的,且最后一层的节点尽可能靠近左边。
二叉树的表示方法
二叉树可以通过多种方式表示,常见的表示方法有以下几种:
-
数组表示:使用数组来表示二叉树,通常通过以下公式来确定每个节点的子节点和父节点的索引:
- 左子节点索引:
2 * index + 1
- 右子节点索引:
2 * index + 2
- 父节点索引:
(index - 1) // 2
下面是一个数组表示的示例:# 代表以下二叉树: # 1 # / \ # 2 3 # / \ / \ # 4 5 6 7 tree_array = [1, 2, 3, 4, 5, 6, 7]
- 左子节点索引:
- 链表表示:使用链表来表示二叉树,每个节点包含数据、左子节点指针和右子节点指针。
class TreeNode: def __init__(self, value): self.value = value self.left = None self.right = None
二叉树的遍历方法
遍历二叉树是访问树中每个节点的过程。常见的遍历方法有:
- 前序遍历:先访问根节点,然后递归地前序遍历左子树,最后前序遍历右子树。
- 中序遍历:递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。
- 后序遍历:递归地后序遍历左子树和右子树,最后访问根节点。
- 层次遍历:通过层次遍历,从根节点开始,逐层访问树的节点。
前序遍历
前序遍历的递归实现如下:
def preorder_traversal(node):
if node is None:
return
print(node.value)
preorder_traversal(node.left)
preorder_traversal(node.right)
中序遍历
中序遍历的递归实现如下:
def inorder_traversal(node):
if node is None:
return
inorder_traversal(node.left)
print(node.value)
inorder_traversal(node.right)
后序遍历
后序遍历的递归实现如下:
def postorder_traversal(node):
if node is None:
return
postorder_traversal(node.left)
postorder_traversal(node.right)
print(node.value)
后序遍历的非递归实现
def postorder_traversal_iterative(root):
if root is None:
return
stack = [root]
result = []
while stack:
node = stack.pop()
result.append(node.value)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
for value in reversed(result):
print(value)
层序遍历
层序遍历可以通过广度优先搜索(BFS)或队列来实现,代码如下:
from collections import deque
def level_order_traversal(root):
if root is None:
return
queue = deque()
queue.append(root)
while queue:
node = queue.popleft()
print(node.value)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
二叉树的常见操作
插入节点
插入节点的操作通常涉及找到适当的位置插入新的节点,这里以插入一个左子节点为例:
def insert_left_child(node, value):
new_node = TreeNode(value)
new_node.left = node.left
node.left = new_node
插入节点的非递归实现
def insert_non_recursive(root, value):
new_node = TreeNode(value)
if root is None:
return new_node
current = root
while True:
if value < current.value:
if current.left is None:
current.left = new_node
break
else:
current = current.left
else:
if current.right is None:
current.right = new_node
break
else:
current = current.right
return root
删除节点
删除节点的操作比较复杂,要考虑删除节点是否是叶子节点、是否只有一个子节点、是否有两个子节点等情况:
def delete_node(root, value):
if root is None:
return root
if value < root.value:
root.left = delete_node(root.left, value)
elif value > root.value:
root.right = delete_node(root.right, value)
else:
if root.left is None:
return root.right
elif root.right is None:
return root.left
temp = find_min_value_node(root.right)
root.value = temp.value
root.right = delete_node(root.right, temp.value)
return root
def find_min_value_node(node):
current = node
while current.left is not None:
current = current.left
return current
删除节点的非递归实现
def delete_non_recursive(root, value):
if root is None:
return root
current = parent = None
while root and root.value != value:
parent = root
root = root.left if value < root.value else root.right
if root is None:
return root
if root.left is None:
if root == parent.left:
parent.left = root.right
else:
parent.right = root.right
else:
temp = root.left
while temp.right:
temp = temp.right
temp.right = root.right
if root == parent.left:
parent.left = root.left
else:
parent.right = root.left
return root
查找节点
查找节点是通过二叉树的遍历找寻指定值的节点,下面给出递归实现:
def find_node(root, value):
if root is None or root.value == value:
return root
if root.value < value:
return find_node(root.right, value)
return find_node(root.left, value)
查找节点的非递归实现
def find_node_non_recursive(root, value):
while root:
if value < root.value:
root = root.left
elif value > root.value:
root = root.right
else:
return root
return None
二叉树的应用实例
二叉搜索树
二叉搜索树是一种特殊的二叉树,其每个节点的左子树上的所有节点值小于该节点值,右子树上的所有节点值大于该节点值。
def insert_bst(root, value):
if root is None:
return TreeNode(value)
if value < root.value:
root.left = insert_bst(root.left, value)
else:
root.right = insert_bst(root.right, value)
return root
def find_bst(root, value):
if root is None or root.value == value:
return root
if root.value < value:
return find_bst(root.right, value)
return find_bst(root.left, value)
平衡二叉树
平衡二叉树是指任何节点的左右子树的高度差不超过1的二叉树。AVL树是平衡二叉树的一种实现。
class AVLNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
self.height = 1
def insert_avl(root, value):
if root is None:
return AVLNode(value)
if value < root.value:
root.left = insert_avl(root.left, value)
else:
root.right = insert_avl(root.right, value)
root.height = 1 + max(get_height(root.left), get_height(root.right))
balance = get_balance(root)
if balance > 1 and value < root.left.value:
return rotate_right(root)
if balance < -1 and value > root.right.value:
return rotate_left(root)
if balance > 1 and value > root.left.value:
root.left = rotate_left(root.left)
return rotate_right(root)
if balance < -1 and value < root.right.value:
root.right = rotate_right(root.right)
return rotate_left(root)
return root
def rotate_right(z):
y = z.left
T2 = y.right
y.right = z
z.left = T2
z.height = 1 + max(get_height(z.left), get_height(z.right))
y.height = 1 + max(get_height(y.left), get_height(y.right))
return y
def rotate_left(z):
y = z.right
T2 = y.left
y.left = z
z.right = T2
z.height = 1 + max(get_height(z.left), get_height(z.right))
y.height = 1 + max(get_height(y.left), get_height(y.right))
return y
def get_height(node):
if node is None:
return 0
return node.height
def get_balance(node):
if node is None:
return 0
return get_height(node.left) - get_height(node.right)
二叉堆
二叉堆是一种特殊的完全二叉树,它维护了一种堆的性质。最小堆要求,父节点的值小于等于左右子节点的值,最大堆要求,父节点的值大于等于左右子节点的值。
class HeapNode:
def __init__(self, value):
self.value = value
def insert_heap(heap, value):
new_node = HeapNode(value)
heap.append(new_node)
node_index = len(heap) - 1
while node_index > 0 and heap[node_index].value < heap[(node_index - 1) // 2].value:
heap[node_index], heap[(node_index - 1) // 2] = heap[(node_index - 1) // 2], heap[node_index]
node_index = (node_index - 1) // 2
删除节点
def delete_bst(root, value):
if root is None:
return root
if value < root.value:
root.left = delete_bst(root.left, value)
elif value > root.value:
root.right = delete_bst(root.right, value)
else:
if root.left is None:
return root.right
elif root.right is None:
return root.left
temp = find_min_value_node(root.right)
root.value = temp.value
root.right = delete_bst(root.right, temp.value)
return root
def find_min_value_node(node):
current = node
while current.left is not None:
current = current.left
return current
二叉树的编码实现
Python实现示例
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def preorder_traversal(self, root):
if root is None:
return
print(root.value)
self.preorder_traversal(root.left)
self.preorder_traversal(root.right)
def inorder_traversal(self, root):
if root is None:
return
self.inorder_traversal(root.left)
print(root.value)
self.inorder_traversal(root.right)
def postorder_traversal(self, root):
if root is None:
return
self.postorder_traversal(root.left)
self.postorder_traversal(root.right)
print(root.value)
def level_order_traversal(self, root):
if root is None:
return
queue = deque()
queue.append(root)
while queue:
node = queue.popleft()
print(node.value)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
Java实现示例
public class TreeNode {
int value;
TreeNode left;
TreeNode right;
TreeNode(int value) {
this.value = value;
}
void preorderTraversal(TreeNode root) {
if (root == null) {
return;
}
System.out.println(root.value);
preorderTraversal(root.left);
preorderTraversal(root.right);
}
void inorderTraversal(TreeNode root) {
if (root == null) {
return;
}
inorderTraversal(root.left);
System.out.println(root.value);
inorderTraversal(root.right);
}
void postorderTraversal(TreeNode root) {
if (root == null) {
return;
}
postorderTraversal(root.left);
postorderTraversal(root.right);
System.out.println(root.value);
}
void levelOrderTraversal(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
System.out.println(node.value);
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
}
二叉树的学习资源推荐
在线教程
图书推荐
- 《算法导论》(Introduction to Algorithms):虽然没有具体推荐某一章节,但该书对数据结构和算法做了全面且深入的讲解。
- 《数据结构与算法分析》(Data Structures and Algorithm Analysis):侧重于分析数据结构和算法的性能。