資料結構學習之樹結構

freephp發表於2024-08-06

前段時間剛好在學習機器學習中的決策樹,想起多年前學習樹這個資料結構的場景,剛好藉此機會迴歸一下知識點。
樹是一種非常常見的資料結構,它由節點(Node)和邊(Edge)構成。它有如下的一些特徵:
1. 根結點(Root Node):樹有且只有一個根結點,它是樹的頂端結點。
2. 結點(Node):每個結點包含一個值或資訊,除了根結點,每個結點都有一個父結點和零個或多個子結點。
3. 邊(Edge):連線兩個結點的連線,表示結點之間的關係。
4. 葉結點(Leaf Node):沒有子結點的結點。
5. 子結點(Child Node):直接連線在某結點下的結點。
6. 父結點(Parent Node):直接連線在某結點上的結點。
7. 子樹(Subtree):由一個結點及其所有子結點組成的樹。

根據樹的節點情況,主要有下面的分類:
1. 二叉樹(Binary Tree):每個結點最多有兩個子結點,稱為左子結點和右子結點。
2. 完全二叉樹(Complete Binary Tree):除了最後一層,其他層的結點都填滿了,最後一層的結點靠左排列。
3. 滿二叉樹(Full Binary Tree):每個結點要麼是葉結點,要麼有兩個子結點。
4. 平衡二叉樹(Balanced Binary Tree):左右子樹的高度差不超過1的二叉樹。
5. 二叉搜尋樹(Binary Search Tree, BST):左子結點的值小於父結點的值,右子結點的值大於父結點的值。

樹的真實應用很多,比如LInux系統中的檔案系統結構就是樹結構。
我用Python實現了這個檔案系統的樹結構,程式碼如下:

class FileSystemNode:
    def __init__(self, name, is_directory=False):
        self.name = name
        self.is_directory = is_directory
        self.children = []

    def add_child(self, child_node):
        if self.is_directory:
            self.children.append(child_node)
        else:
            raise ValueError("Cannot add child to a file node")

    def __repr__(self, level=0):
        ret = "\t" * level + repr(self.name) + "\n"
        for child in self.children:
            ret += child.__repr__(level + 1)
        return ret

# 建立檔案系統根目錄
root = FileSystemNode("/", is_directory=True)

# 建立子目錄和檔案
home = FileSystemNode("home", is_directory=True)
var = FileSystemNode("var", is_directory=True)
etc = FileSystemNode("etc", is_directory=True)

user1 = FileSystemNode("user1", is_directory=True)
user2 = FileSystemNode("user2", is_directory=True)

documents = FileSystemNode("documents", is_directory=True)
pictures = FileSystemNode("pictures", is_directory=True)

file1 = FileSystemNode("file1.txt")
photo1 = FileSystemNode("photo1.jpg")

# 構建檔案系統樹
root.add_child(home)
root.add_child(var)
root.add_child(etc)

home.add_child(user1)
home.add_child(user2)

user1.add_child(documents)
user1.add_child(pictures)

documents.add_child(file1)
pictures.add_child(photo1)

# 列印檔案系統樹
print(root)

執行程式碼,可以得到輸出如下所示:

'/'
	'home'
		'user1'
			'documents'
				'file1.txt'
			'pictures'
				'photo1.jpg'
		'user2'
	'var'
	'etc'

可以看出這個資料夾結構是一個多叉樹,一個父節點可以有多個子節點。
最開始說到的決策樹也是一種樹結構的應用。下面是用Python實現的樹的定義和三種遍歷演算法:

class TreeNode:
    def __init__(self, value=0, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right


# 建立一個簡單的二叉樹
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)


# 前序遍歷
def pre_order_traversal(node):
    if not node:
        return
    print(node.value, end=' ')
    pre_order_traversal(node.left)
    pre_order_traversal(node.right)

# 中序遍歷
def mid_order_traversal(node):
    if not node:
        return
    mid_order_traversal(node.left)
    print(node.value, end=' ')
    mid_order_traversal(node.right)

# 後序遍歷
def post_order_traversal(node):
    if not node:
        return
    post_order_traversal(node.left)
    post_order_traversal(node.right)
    print(node.value, end=' ')

# 呼叫前序遍歷
pre_order_traversal(root)  # 輸出:1 2 4 5 3
print("-------------------------\r\n")
mid_order_traversal(root)
print("-------------------------\r\n")
post_order_traversal(root)

明天在繼續學習樹的其他案例,日拱一卒,不負年華。

相關文章