以下是二元搜尋樹教材的分步驟設計,針對每一個步驟提供解釋與相應的 Python 可執行程式碼。最後提供完整的統整程式碼以便檢查整體功能。
(0) 前置作業
在開始建構二元搜尋樹前,先定義樹的基本組成單位——節點 (Node) 和 二元搜尋樹 (Binary Search Tree, BST) 類別。
節點類別和二元搜尋樹的初始設定
# 節點類別,包含值、左連結、右連結
class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
# 二元搜尋樹類別
class BinarySearchTree:
def __init__(self):
self.root = None
(1) 插入 (Insert)
插入操作用來將新數值加入到二元搜尋樹中。每次插入時,從根節點開始,依序比較值的大小,決定向左或向右插入新節點。
插入程式碼
class BinarySearchTree:
# 省略 __init__ 和 Node 類別
def insert(self, value):
if self.root is None:
self.root = Node(value)
else:
self._insert_recursive(self.root, value)
def _insert_recursive(self, node, value):
if value < node.value:
if node.left is None:
node.left = Node(value)
else:
self._insert_recursive(node.left, value)
else:
if node.right is None:
node.right = Node(value)
else:
self._insert_recursive(node.right, value)
測試插入
# 建立並插入數值
bst = BinarySearchTree()
for value in [5, 3, 2, 7, 1, 6, 4]:
bst.insert(value)
(2) 搜尋 (Search)
搜尋操作用來檢查特定數值是否存在於二元搜尋樹中。從根節點開始,依次比較目標值與當前節點值的大小,決定向左或向右尋找,直到找到目標或確認目標不存在。
搜尋程式碼
class BinarySearchTree:
# 省略前面插入程式碼
def search(self, value):
return self._search_recursive(self.root, value)
def _search_recursive(self, node, value):
if node is None:
return False
if node.value == value:
return True
elif value < node.value:
return self._search_recursive(node.left, value)
else:
return self._search_recursive(node.right, value)
測試搜尋
print('搜尋 5:', bst.search(5)) # 輸出 True
print('搜尋 2:', bst.search(2)) # 輸出 True
print('搜尋 8:', bst.search(8)) # 輸出 False
(3) 遍歷 (Traversal)
遍歷是指以特定的順序訪問所有節點。常見的遍歷方法有前序、中序和後序遍歷。
前序遍歷 (Preorder Traversal)
在前序遍歷中,先訪問根節點,然後依次訪問左子節點和右子節點。
class BinarySearchTree:
# 省略前面的插入和搜尋程式碼
def preorder_traversal(self):
result = []
self._preorder_recursive(self.root, result)
return result
def _preorder_recursive(self, node, result):
if node:
result.append(node.value)
self._preorder_recursive(node.left, result)
self._preorder_recursive(node.right, result)
中序遍歷 (Inorder Traversal)
在中序遍歷中,先訪問左子樹,再訪問根節點,最後訪問右子樹。這樣的順序在二元搜尋樹中會得到排序好的節點。
class BinarySearchTree:
# 省略前面的插入、搜尋和前序遍歷程式碼
def inorder_traversal(self):
result = []
self._inorder_recursive(self.root, result)
return result
def _inorder_recursive(self, node, result):
if node:
self._inorder_recursive(node.left, result)
result.append(node.value)
self._inorder_recursive(node.right, result)
後序遍歷 (Postorder Traversal)
在後序遍歷中,先依次訪問左子節點和右子節點,最後訪問根節點。
class BinarySearchTree:
# 省略前面的插入、搜尋和其他遍歷程式碼
def postorder_traversal(self):
result = []
self._postorder_recursive(self.root, result)
return result
def _postorder_recursive(self, node, result):
if node:
self._postorder_recursive(node.left, result)
self._postorder_recursive(node.right, result)
result.append(node.value)
測試遍歷
print('前序遍歷:', bst.preorder_traversal()) # 預期 [5, 3, 2, 1, 4, 7, 6]
print('中序遍歷:', bst.inorder_traversal()) # 預期 [1, 2, 3, 4, 5, 6, 7]
print('後序遍歷:', bst.postorder_traversal()) # 預期 [1, 2, 4, 3, 6, 7, 5]
(4) 樹的高度 (Height)
樹的高度是從根節點到最遠葉節點的層數。計算樹的高度可以用遞迴,分別求出左子樹和右子樹的高度,並取較大值再加上 1。
樹的高度程式碼
class BinarySearchTree:
# 省略前面的插入、搜尋和遍歷程式碼
def height(self):
return self._height_recursive(self.root)
def _height_recursive(self, node):
if node is None:
return 0
else:
left_height = self._height_recursive(node.left)
right_height = self._height_recursive(node.right)
return 1 + max(left_height, right_height)
測試樹高
print('樹的高度:', bst.height()) # 預期 4
(5) 樹的直徑(最大距離)
樹的直徑是樹中兩個節點之間的最長路徑,通常也叫「最大距離」。計算直徑可以使用遞迴,找出每個節點的左子樹和右子樹高度,並比較出最大的距離。
樹的直徑程式碼
class BinarySearchTree:
# 省略前面的插入、搜尋、遍歷和高度程式碼
def diameter(self):
return self._diameter_recursive(self.root)[1]
def _diameter_recursive(self, node):
if node is None:
return 0, 0 # 高度、直徑都為0
left_height, left_diameter = self._diameter_recursive(node.left)
right_height, right_diameter = self._diameter_recursive(node.right)
current_diameter = left_height + right_height
max_diameter = max(current_diameter, left_diameter, right_diameter)
current_height = 1 + max(left_height, right_height)
return current_height, max_diameter
測試樹的直徑
print('樹的直徑(最大距離):', bst.diameter()) # 預期 4
完整統整程式碼
以下為完整的程式碼,將所有步驟統整在一起:
class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
class BinarySearchTree:
def __init__(self):
self.root = None
def insert(self, value):
if self.root is None:
self.root = Node(value)
else:
self._insert_recursive(self.root, value)
def _insert_recursive(self, node, value):
if value < node.value:
if node.left is None:
node.left = Node(value)
else:
self._insert_recursive(node.left, value)
else:
if node.right is None:
node.right = Node(value)
else:
self._insert_recursive(node.right, value)
def search(self, value):
return self._search_recursive(self.root, value)
def _search_recursive(self, node, value):
if node is None:
return False
if node.value == value:
return True
elif value < node.value:
return self._search_recursive(node.left, value)
else:
return self._search_recursive(node.right, value)
def preorder_traversal(self):
result = []
self._preorder_recursive(self.root, result)
return result
def _preorder_recursive(self, node, result):
if node:
result.append(node.value)
self._preorder_recursive(node.left, result)
self._preorder_recursive(node.right, result)
def inorder_traversal(self):
result = []
self._inorder_recursive(self.root, result)
return result
def _inorder_recursive(self, node, result):
if node:
self._inorder_recursive(node.left, result)
result.append(node.value)
self._inorder_recursive(node.right, result)
def postorder_traversal(self):
result = []
self._postorder_recursive(self.root, result)
return result
def _postorder_recursive(self, node, result):
if node:
self._postorder_recursive(node.left, result)
self._postorder_recursive(node.right, result)
result.append(node.value)
def height(self):
return self._height_recursive(self.root)
def _height_recursive(self, node):
if node is None:
return 0
else:
left_height = self._height_recursive(node.left)
right_height = self._height_recursive(node.right)
return 1 + max(left_height, right_height)
def diameter(self):
return self._diameter_recursive(self.root)[1]
def _diameter_recursive(self, node):
if node is None:
return 0, 0
left_height, left_diameter = self._diameter_recursive(node.left)
right_height, right_diameter = self._diameter_recursive(node.right)
current_diameter = left_height + right_height
max_diameter = max(current_diameter, left_diameter, right_diameter)
current_height = 1 + max(left_height, right_height)
return current_height, max_diameter
# 測試
bst = BinarySearchTree()
for value in [5, 3, 2, 7, 1, 6, 4]:
bst.insert(value)
print('搜尋 5:', bst.search(5))
print('搜尋 2:', bst.search(2))
print('前序遍歷:', bst.preorder_traversal())
print('中序遍歷:', bst.inorder_traversal())
print('後序遍歷:', bst.postorder_traversal())
print('樹的高度:', bst.height())
print('樹的直徑(最大距離):', bst.diameter())
這份教材應包含所有基本操作,並可用於學習與練習二元搜尋樹的核心功能。
沒有留言:
張貼留言