- 滿二叉樹(full binary tree)
如果二叉樹的高度為 h,樹的節點數為 2^h-1,h≥0,就稱此樹為滿二叉樹。 - 完全二叉樹(complete binary tree)
如果二叉樹的高度為 h,樹的節點數小於 2^h-1,編號從上到下、從左到右一一對應(如果只有一個子樹,必須是左子樹。不能只有右子樹,沒有左子樹)。如果有N個節點,那么此二叉樹的層數 h 為⌊log(N+1)⌋。 - 斜二叉樹(skewed binary tree)
完全沒有右節點,左斜二叉樹。
完全沒有做節點,右斜二叉樹。 - 嚴格二叉樹(strictly binary tree)
二叉樹中每一個非終端節點均有非空的左右子樹。
用數組實現二叉樹
使用有序的一維數組表示二叉樹,首先可將此二叉樹想成滿二叉樹,且第k層具有2^(k-1)個節點,按序放在一維數組中。
- 左子樹索引值是父節點索引值*2
- 右子樹索引值是父節點索引值*2+1
- 二叉查找樹的特點
可以是空集合,若不是空集合,則節點上一定要有一個鍵值。
每一個樹根的值需大於左子樹的值。
每一個樹根的值需小於右子樹的值。
左右子樹也是二叉查找樹。
樹的每個節點值都不相同。
"""
按序輸入一顆二叉樹節點的數據,分別是0,6,3,5,4,7,8,9,2,
並建立一顆查找樹,最后輸出存儲此二叉樹的一維數組。
"""
def btree_create(btree, data, length):
for i in range(1, length):
level = 1
while btree[level] != 0: # 0不參與爭斗,用來補位
if data[i] > btree[level]: # 如果原始數組內的值大於樹根,則往右子樹比較
level = level * 2 + 1
else: # 小於等於樹根,則往左子樹比較
level = level * 2
btree[level] = data[i] # 把數組值放進二叉樹
length = 9
data = [0, 6, 3, 5, 4, 7, 8, 9, 2]
btree = [0] * 16
print("原始數組內容為:")
for i in range(length):
print("[%2d] " % data[i], end='')
print('')
btree_create(btree, data, length)
print("二叉樹內容為:")
for i in range(1, 16):
print("[%2d] " % btree[i], end='')
print()
用鏈表實現二叉樹
對於節點的添加與刪除容易,但是難找到父節點,除非在每一個節點增加一個父字段
- 二叉樹類聲明
class Tree:
def __init__(self):
self.data = 0
self.left = None
self.right = None
- 以鏈表建立二叉樹:
def create_tree(root, val):
newnode = Tree()
newnode.data = val
newnode.left = None
newnode.right = None
if root == None:
root = newnode
return root
else:
current = root # 父節點
# 判斷左右子樹走向
while current != None:
backup = current
if current.data > val:
current = current.left
else:
current = current.right
# 把尾節點值和新增節點值比較,把節點放進鏈表
if backup.data > val:
backup.left = newnode
else:
backup.right = newnode
return root
data = [5, 6, 24, 8, 12, 3, 17, 1, 9]
ptr = None
root = None
for i in range(9):
ptr = create_tree(ptr, data[i])
print("樹根左邊:")
root = ptr.left
while root != None:
print("%d" % root.data)
root = root.left or root.right
print('-----')
print("樹根右邊:")
root = ptr.right
while root != None:
print("%d" % root.data)
root = root.right or root.left
print()
左邊:
3
1
-----
右邊:
6
24
8
12
17
二叉樹遍歷
- 中序遍歷(Inorder):左子樹-樹根-右子樹
def inorder(ptr):
if ptr != None:
inorder(ptr.left)
print("[%2d] " % ptr.data, end='')
inorder(ptr.right)
前序遍歷(Preorder):樹根-左子樹-右子樹
def preorder(ptr):
if ptr != None:
print("[%2d] " % ptr.data, end='')
preorder(ptr.left)
preorder(ptr.right)
后序遍歷(Postorder):左子樹-右子樹-樹根
def postorder(ptr):
if ptr != None:
postorder(ptr.left)
postorder(ptr.right)
print("[2d] " % ptr.data, end='')
二叉樹節點的查找
二叉樹在建立時,是根據左子樹 < 樹根 < 右子樹的原則建立的,因此只需從樹根出發比較鍵值,如果比樹根大就往右,否則往左而下。
def search(ptr, val):
while True:
if ptr == None:
return None
if ptr.data == val:
return ptr
elif ptr.data > val:
ptr = ptr.left
else:
ptr = ptr.right
二叉樹節點的插入
if search(ptr, data) != None:
print("二叉樹中有此節點了")
else:
ptr = create_tree(ptr, data)
inorder(ptr)
二叉樹節點的刪除
刪除的節點為樹葉,只要將其相連的父節點指向 None 即可
刪除的節點只有一棵子樹
刪除的節點有兩棵子樹
- 中序立即先行者(inorder immediate predecessor):將欲刪除節點的左子樹中最大者向上提。簡單來說,就是在該節點的左子樹,往右尋找,知道右指針為None,這個節點就是中序立即先行者。
- 中序立即后繼者(inorder immediate successor):把要刪除節點的右子樹中最小者向上提。簡單來說,就是在該節點的右子樹,往左尋找,知道左指針為None,這個節點就是中序立即后繼者。
堆積樹(heap tree)排序算法
選擇排序的改進,可以減少在選擇排序算法中的比較次數。堆積樹是一種特殊的二叉樹,可分為最大堆積樹和最小堆積樹。
- 最大堆積樹滿足:
它是一個完全二叉樹。
所有節點的值都大於或等於它左右子節點的值。
樹根是堆積樹中最大的。 - 最小堆積樹滿足:
它是一個完全二叉樹。
所有節點的值都小於或等於它左右子節點的值。
樹根是堆積樹中最小的。
def heap(data, size):
for i in range(int(size / 2), 0, -1): # 建立堆積樹節點
ad_heap(data, i, size - 1)
print("\n堆積的內容:", end='')
for i in range(1, size):
print("[%2d ]" % data[i], end='')
print("\n")
for i in range(size - 2, 0, -1): # 堆積排序
data[i + 1], data[1] = data[1], data[i + 1] # 頭尾節點交換
ad_heap(data, 1, i) # 處理剩余節點
print("處理過程:", end='')
for j in range(1, size):
print("[%2d ]" % data[j], end='')
print()
def ad_heap(data, i, size):
j = 2 * i
tmp = data[i]
post = 0
while j <= size and post == 0:
if j < size:
if data[j] < data[j + 1]: # 找出最大節點
j += 1
if tmp >= data[j]: # 若樹根較大,則繼續比較
post = 1
else: # 若樹根較小,則繼續比較
data[int(j / 2)] = data[j]
j = 2 * j
data[int(j / 2)] = tmp # 指定樹根為父節點
def main():
data = [0, 5,6,4,8,3,2,7,1]
size = len(data)
print('原始數組為:', end='')
for i in range(1, size):
print('[%2d]' % data[i], end='')
heap(data, size)
print('排序結果為:')
for i in range(1, size):
print('[%2d]' % data[i], end='')
main()
原始數組為:[ 5][ 6][ 4][ 8][ 3][ 2][ 7][ 1]
堆積的內容:[ 8 ][ 6 ][ 7 ][ 5 ][ 3 ][ 2 ][ 4 ][ 1 ]
處理過程:[ 7 ][ 6 ][ 4 ][ 5 ][ 3 ][ 2 ][ 1 ][ 8 ]
處理過程:[ 6 ][ 5 ][ 4 ][ 1 ][ 3 ][ 2 ][ 7 ][ 8 ]
處理過程:[ 5 ][ 3 ][ 4 ][ 1 ][ 2 ][ 6 ][ 7 ][ 8 ]
處理過程:[ 4 ][ 3 ][ 2 ][ 1 ][ 5 ][ 6 ][ 7 ][ 8 ]
處理過程:[ 3 ][ 1 ][ 2 ][ 4 ][ 5 ][ 6 ][ 7 ][ 8 ]
處理過程:[ 2 ][ 1 ][ 3 ][ 4 ][ 5 ][ 6 ][ 7 ][ 8 ]
處理過程:[ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][ 6 ][ 7 ][ 8 ]
排序結果為:
[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8]