5.数据结构-树

数据结构中的树是一种抽象数据类型,它是由节点组成的层次结构。树的每个节点可以包含零个或多个子节点,但只能有一个父节点(除了根节点,它没有父节点)。以下是树的一些基本概念和特性:

基本概念

  1. 节点(Node):树中的每个元素称为节点,它包含数据和指向其子节点的链接。
  2. 根节点(Root):树的顶部节点,没有父节点。
  3. 子节点(Child):直接连接到另一个节点的节点。
  4. 父节点(Parent):有一个或多个子节点的节点。
  5. 叶子节点(Leaf):没有子节点的节点。
  6. 边(Edge):连接两个节点的链接。
  7. 路径(Path):从根节点到任何节点的一系列边。
  8. 深度(Depth):从根节点到节点的路径长度。
  9. 高度(Height):从节点到最远叶子节点的路径长度。

树的类型

  1. 二叉树(Binary Tree):每个节点最多有两个子节点的树。
  2. 二叉搜索树(Binary Search Tree, BST):一种特殊的二叉树,其中每个节点的值大于其左子树中所有节点的值,小于其右子树中所有节点的值。
  3. 平衡二叉树(Balanced Binary Tree):保证树的高度尽可能小的二叉树,如AVL树。
  4. B树和B+树:用于数据库和文件系统中的多路搜索树。
  5. 堆(Heap):一种特殊的树,可以是最大堆或最小堆,其中父节点的值总是大于(或小于)其子节点的值。
  6. 前缀树(Trie):一种用于快速检索字符串的数据结构,也称为字典树。

树的操作

  1. 插入(Insertion):向树中添加新的节点。
  2. 删除(Deletion):从树中移除节点。
  3. 搜索(Search):在树中查找特定值的节点。
  4. 遍历(Traversal) :按特定顺序访问树的所有节点,常见的遍历方式有:
    • 前序遍历(Pre-order)
    • 中序遍历(In-order)
    • 后序遍历(Post-order)
    • 层序遍历(Level-order)

应用场景

  • 文件系统:树结构用于表示文件和目录的层次关系。
  • 组织结构:公司或组织的层级结构。
  • 网络结构:表示网络中的路由器和交换机的连接。
  • 数据索引:如B树和B+树在数据库中的应用。

树的操作可以通过多种编程语言实现。以下是使用Python语言实现的树的一些基本操作的示例代码。我们将以二叉树为例,展示如何创建树节点、插入节点、搜索节点、删除节点以及遍历树。

树节点的定义

python 复制代码
class TreeNode:
    def __init__(self, key):
        self.left = None
        self.right = None
        self.val = key

插入节点

python 复制代码
def insert(root, key):
    if root is None:
        return TreeNode(key)
    else:
        if root.val < key:
            root.right = insert(root.right, key)
        else:
            root.left = insert(root.left, key)
    return root

搜索节点

python 复制代码
def search(root, key):
    if root is None or root.val == key:
        return root
    if root.val < key:
        return search(root.right, key)
    return search(root.left, key)

删除节点

删除节点是树操作中较为复杂的部分,需要考虑多种情况,这里给出一个简化的版本:

python 复制代码
def minValueNode(node):
    current = node
    while current.left is not None:
        current = current.left
    return current

def deleteNode(root, key):
    if root is None:
        return root
    if key < root.val:
        root.left = deleteNode(root.left, key)
    elif key > root.val:
        root.right = deleteNode(root.right, key)
    else:
        if root.left is None:
            temp = root.right
            root = None
            return temp
        elif root.right is None:
            temp = root.left
            root = None
            return temp
        temp = minValueNode(root.right)
        root.val = temp.val
        root.right = deleteNode(root.right, temp.val)
    return root

遍历树

前序遍历
python 复制代码
def preorderTraversal(root):
    if root:
        print(root.val)
        preorderTraversal(root.left)
        preorderTraversal(root.right)
中序遍历
python 复制代码
def inorderTraversal(root):
    if root:
        inorderTraversal(root.left)
        print(root.val)
        inorderTraversal(root.right)
后序遍历
python 复制代码
def postorderTraversal(root):
    if root:
        postorderTraversal(root.left)
        postorderTraversal(root.right)
        print(root.val)
层序遍历
python 复制代码
from collections import deque

def levelOrderTraversal(root):
    if root is None:
        return
    queue = deque([root])
    while queue:
        node = queue.popleft()
        print(node.val)
        if node.left:
            queue.append(node.left)
        if node.right:
            queue.append(node.right)

树的类型

树的类型多种多样,每种树都有其特定的应用场景和特性。以下是一些常见的树类型及其详细介绍:

  1. 普通树(General Tree)

    • 普通树是最基本的树结构,每个节点可以有多个子节点。
    • 普通树通常用于表示具有层次结构的数据,如组织结构图。
  2. 二叉树(Binary Tree)

    • 每个节点最多有两个子节点,通常称为左子节点和右子节点。
    • 二叉树的特点是每个节点的子节点数量有限制,这使得二叉树的操作更加高效。
  3. 二叉搜索树(Binary Search Tree, BST)

    • 特殊的二叉树,其中每个节点的值大于其左子树中所有节点的值,小于其右子树中所有节点的值。
    • 这种性质使得在BST中进行搜索、插入和删除操作非常高效。
  4. 平衡二叉树(Balanced Binary Tree)

    • 为了保持树的高度最小化,平衡二叉树通过旋转操作来调整树的结构。
    • AVL树和红黑树是两种常见的平衡二叉树。
  5. AVL树(Adelson-Velsky and Landis Tree)

    • 一种自平衡的二叉搜索树,其中任何节点的两个子树的高度最大差异为1。
    • AVL树通过旋转操作保持其平衡,确保操作的效率。
  6. 红黑树(Red-Black Tree)

    • 另一种自平衡的二叉搜索树,它通过确保树的任何路径上黑色节点的数量大致相同来保持平衡。
    • 红黑树的每个节点都有一个颜色属性,可以是红色或黑色。
  7. B树(B-Tree)

    • 一种多路搜索树,用于数据库和文件系统。
    • B树的每个节点可以有多个子节点,通常用于存储大量数据。
  8. B+树(B±Tree)

    • B树的变种,所有值都存储在叶子节点,并且叶子节点之间通过链表相连。
    • B+树适合于范围查询和顺序访问。
  9. 堆(Heap)

    • 一种特殊的树,可以是最大堆或最小堆。
    • 在最大堆中,父节点的值总是大于或等于其子节点的值;在最小堆中,父节点的值总是小于或等于其子节点的值。
    • 堆常用于实现优先队列。
  10. 前缀树(Trie,又称字典树)

    • 用于存储字符串集合或关联字符串与值的数据结构。
    • 每个节点代表一个字符,从根到某一节点的路径表示一个字符串。
  11. 后缀树(Suffix Tree)

    • 一种特殊的树,用于表示给定字符串的所有后缀。
    • 后缀树在文本搜索、模式匹配等领域有广泛应用。
  12. 四叉树(Quadtree)

    • 用于将二维空间划分成四个象限,常用于地理信息系统(GIS)和图像处理。
    • 每个节点代表一个区域,并且可以进一步划分为四个子区域。
  13. 八叉树(Octree)

    • 三维空间的四叉树,用于三维空间的划分。
    • 常用于三维图形学、机器人路径规划等领域。

B树是一种自平衡的多路搜索树,它能够保持数据有序,并且支持高效的查找、插入和删除操作。B树的设计特别适合于那些需要频繁访问磁盘存储的系统,如数据库和文件系统。以下是B树的一些关键特性和实现细节:

B树的关键特性

  1. 节点的子节点数量:B树的每个内部节点可以有多个子节点,通常是m个,并且每个节点至少有⌈m/2⌉个子节点,其中m是树的阶数。
  2. 有序性:B树中的所有键值都是有序的,对于任意节点,其左子节点的所有键值都小于该节点的键值,右子节点的所有键值都大于该节点的键值。
  3. 平衡性:B树通过分裂操作保持平衡,确保所有叶子节点的高度大致相同。
  4. 搜索效率:由于B树的平衡性,搜索操作的时间复杂度为O(log n)。
  5. 磁盘友好:B树的设计使得它在读取和写入时能够减少磁盘I/O操作的次数。

B树的实现

B树的实现相对复杂,因为它涉及到节点的分裂和合并操作。以下是Python语言实现B树的一个简化版本:

python 复制代码
class BTreeNode:
    def __init__(self, leaf=False):
        self.keys = []  # 存储键值
        self.child = []  # 存储子节点
        self.leaf = leaf  # 是否是叶子节点

class BTree:
    def __init__(self, t):
        self.root = BTreeNode(leaf=True)
        self.t = t  # 树的阶数

    def search(self, k, x=None):
        # 搜索键值k
        if x is None:
            x = self.root
        if x.leaf:
            for i in range(len(x.keys)):
                if x.keys[i] == k:
                    return x, i
                elif x.keys[i] > k:
                    return None
        else:
            for i in range(len(x.keys)):
                if x.keys[i] == k:
                    return self.search(k, x.child[i])
                elif x.keys[i] > k:
                    return self.search(k, x.child[i])

    def insert(self, k):
        root = self.root
        if len(root.keys) == (2 * self.t) - 1:
            temp = BTreeNode()
            self.root = temp
            temp.child.insert(0, root)
            self.split_child(temp, 0)
            self.insert_non_full(temp, k)
        else:
            self.insert_non_full(root, k)

    def insert_non_full(self, x, k):
        i = len(x.keys) - 1
        if x.leaf:
            x.keys.append((None, -1))
            for i in range(len(x.keys) - 1, -1, -1):
                if x.keys[i] < k:
                    x.keys[i + 1] = x.keys[i]
                else:
                    x.keys[i + 1] = k
                    return
            x.keys[0] = k
        else:
            for i in range(len(x.keys)):
                if x.keys[i] > k:
                    if len(x.child[i].keys) == (2 * self.t) - 1:
                        self.split_child(x, i)
                        if x.keys[i] > k:
                            i -= 1
                    break
            self.insert_non_full(x.child[i], k)

    def split_child(self, x, i):
        t = self.t
        y = x.child[i]
        z = BTreeNode(y.leaf)
        x.child.insert(i + 1, z)
        x.keys.insert(i, y.keys[t - 1])
        z.keys = y.keys[t: (3 * t) // 2]
        y.keys = y.keys[:t - 1]
        if not y.leaf:
            z.child = y.child[t:2 * t]
            y.child = y.child[:t]

    # 其他方法,如删除操作,可以根据需要实现

树在软件开发中有着广泛的应用,以下是一些常见的项目实践以及相应的代码示例:

1. 文件系统的目录结构

在文件系统中,树结构通常用于表示文件和目录的层次结构。以下是一个简单的文件系统实现,使用Python的类来表示文件和目录:

python 复制代码
class File:
    def __init__(self, name, size):
        self.name = name
        self.size = size

class Directory:
    def __init__(self, name):
        self.name = name
        self.files = {}
        self.directories = {}

    def add_file(self, file):
        self.files[file.name] = file

    def add_directory(self, directory):
        self.directories[directory.name] = directory

    def __str__(self):
        dirs = ", ".join(self.directories.keys())
        files = ", ".join([f"{file.name} ({file.size} bytes)" for file in self.files.values()])
        return f"Directory: {self.name}\nDirectories: [{dirs}]\nFiles: [{files}]"

2. 组织结构图

组织结构图通常使用树形结构来表示公司的层级关系。以下是一个简单的组织结构图实现:

python 复制代码
class Employee:
    def __init__(self, name, title):
        self.name = name
        self.title = title
        self.subordinates = []

    def add_subordinate(self, employee):
        self.subordinates.append(employee)

    def __str__(self):
        subordinates = "\n".join([str(emp) for emp in self.subordinates])
        return f"Employee: {self.name}, Title: {self.title}\nSubordinates:\n{subordinates}"

3. 二叉搜索树(BST)实现

二叉搜索树是一种常见的数据结构,用于快速查找、插入和删除操作。以下是一个简单的BST实现:

python 复制代码
class TreeNode:
    def __init__(self, key):
        self.left = None
        self.right = None
        self.val = key

class BinarySearchTree:
    def __init__(self):
        self.root = None

    def insert(self, key):
        if self.root is None:
            self.root = TreeNode(key)
        else:
            self._insert(self.root, key)

    def _insert(self, node, key):
        if key < node.val:
            if node.left is None:
                node.left = TreeNode(key)
            else:
                self._insert(node.left, key)
        else:
            if node.right is None:
                node.right = TreeNode(key)
            else:
                self._insert(node.right, key)

    def inorder_traversal(self):
        result = []
        self._inorder(self.root, result)
        return result

    def _inorder(self, node, result):
        if node:
            self._inorder(node.left, result)
            result.append(node.val)
            self._inorder(node.right, result)

4. 哈夫曼编码(Huffman Coding)

哈夫曼编码是一种用于数据压缩的算法,它使用二叉树来构建最优的前缀编码。以下是一个简单的哈夫曼编码实现:

python 复制代码
import heapq
from collections import defaultdict

class HuffmanCoding:
    def __init__(self):
        self.codes = {}

    def build_tree(self, freq):
        priority_queue = [[weight, [symbol, ""]] for symbol, weight in freq.items()]
        heapq.heapify(priority_queue)
        while len(priority_queue) > 1:
            lo = heapq.heappop(priority_queue)
            hi = heapq.heappop(priority_queue)
            for pair in lo[1:]:
                pair[1] = '0' + pair[1]
            for pair in hi[1:]:
                pair[1] = '1' + pair[1]
            heapq.heappush(priority_queue, [lo[0] + hi[0]] + lo[1:] + hi[1:])
        self.codes = sorted(heapq.heappop(priority_queue)[1:], key=lambda p: (len(p[-1]), p))

    def get_codes(self):
        return {symbol: code for symbol, code in self.codes}

1. 社交网络的好友关系图

在社交网络中,用户之间的好友关系可以构成一个图,其中用户是节点,好友关系是边。这里我们使用树来表示一个用户的所有直接和间接好友。

python 复制代码
class User:
    def __init__(self, username):
        self.username = username
        self.friends = []

    def add_friend(self, user):
        if user not in self.friends:
            self.friends.append(user)
            # 双向好友关系
            user.friends.append(self)

    def get_all_friends(self):
        # 使用 BFS 来找到所有好友
        all_friends = set()
        queue = [self]
        while queue:
            current = queue.pop(0)
            for friend in current.friends:
                if friend not in all_friends:
                    all_friends.add(friend)
                    queue.append(friend)
        return all_friends

# 示例
user1 = User("Alice")
user2 = User("Bob")
user3 = User("Charlie")
user1.add_friend(user2)
user1.add_friend(user3)
print(user1.get_all_friends())  # 应该返回包含 Bob 和 Charlie 的集合

2. 表达式树(用于计算和优化)

表达式树是一种特殊的树结构,用于表示和计算表达式。这种树可以用于优化表达式,例如,合并常数。

python 复制代码
class Expression:
    def evaluate(self):
        pass

class ValueExpression(Expression):
    def __init__(self, value):
        self.value = value

    def evaluate(self):
        return self.value

class BinaryExpression(Expression):
    def __init__(self, left, right, operator):
        self.left = left
        self.right = right
        self.operator = operator

    def evaluate(self):
        if self.operator == '+':
            return self.left.evaluate() + self.right.evaluate()
        elif self.operator == '-':
            return self.left.evaluate() - self.right.evaluate()
        elif self.operator == '*':
            return self.left.evaluate() * self.right.evaluate()
        elif self.operator == '/':
            return self.left.evaluate() / self.right.evaluate()

# 示例
expr = BinaryExpression(
    ValueExpression(10),
    BinaryExpression(ValueExpression(5), ValueExpression(2), '*'),
    '+'
)
print(expr.evaluate())  # 输出 20

3. 决策树算法实现

决策树是一种常用的机器学习算法,用于分类和回归任务。这里我们使用一个简单的ID3算法来构建决策树。

python 复制代码
class Node:
    def __init__(self, feature=None, threshold=None, left=None, right=None, *, value=None):
        self.feature = feature
        self.threshold = threshold
        self.left = left
        self.right = right
        self.value = value

def entropy(data):
    values, counts = np.unique(data['label'], return_counts=True)
    p = counts / counts.sum()
    return -sum(p * np.log2(p))

def gini(data):
    values, counts = np.unique(data['label'], return_counts=True)
    p = counts / counts.sum()
    return 1 - sum(p ** 2)

def split(data, feature, threshold):
    return data[data[feature] < threshold]

def build_tree(data, features, min_size=1):
    # 基础条件
    if len(data) <= min_size or len(np.unique(data['label'])) == 1:
        leaf_value = data['label'].value_counts().index[0]
        return Node(value=leaf_value)

    best_feature, best_threshold = None, None
    best_score = 1  # 用1代替无穷大

    for feature in features:
        for idx, row in data.iterrows():
            split_data = split(data, feature, row[feature])
            score = entropy(split_data) if data['label'][0] == 'entropy' else gini(split_data)
            if score < best_score:
                best_feature = feature
                best_threshold = row[feature]
                best_score = score

    left = build_tree(split(data, best_feature, best_threshold), features, min_size)
    right = build_tree(data[~data[best_feature].apply(lambda x: x < best_threshold)], features, min_size)

    return Node(best_feature, best_threshold, left, right)

# 示例
# 假设 data 是一个包含特征和标签的 DataFrame
features = data.columns[:-1]  # 假设最后一列是标签
tree = build_tree(data, features)

1. 构建和查询索引的B树

B树是数据库索引和文件系统索引常用的数据结构。以下是一个简化的B树实现,包括插入和查询功能:

python 复制代码
class BTree:
    def __init__(self, t):
        self.t = t  # 树的阶数
        self.root = None

    def search(self, k, x=None):
        # 搜索给定键值k
        if x is None:
            x = self.root
        if x.is_leaf:
            idx = 0
            while idx < len(x.keys) and k > x.keys[idx]:
                idx += 1
            return (x, idx)
        else:
            idx = 0
            while idx < len(x.keys) and k > x.keys[idx]:
                idx += 1
            return self.search(k, x.children[idx])

    def insert(self, k):
        if not self.root:
            self.root = BTreeNode(self.t, [k], [], True)
        else:
            self.root.insert_non_full(k, self.t)

    class BTreeNode:
        # B树节点类
        def __init__(self, t, keys, children, is_leaf):
            self.keys = keys
            self.children = children
            self.is_leaf = is_leaf
            self.t = t

        def insert_non_full(self, k, t):
            # 插入键值k到非满节点
            idx = len(self.keys) - 1
            while idx >= 0 and k <= self.keys[idx]:
                idx -= 1
            self.keys = self.keys[:idx + 1] + [k] + self.keys[idx + 1:]
            fix = 0
            if 2 * t <= len(self.keys) - 1:
                if self.is_leaf:
                    self.keys.pop(t - 1)
                else:
                    self.children.insert(t, None)
                self.split_child(t, self.children[t])
                fix = 1
            if fix:
                if self == self.tree.root:
                    self.tree.root = BTree.BTreeNode(self.t, [self.keys.pop(0)], [self], False)
                else:
                    self.tree.root.insert_non_full(self.keys.pop(0), t)

        def split_child(self, t, child):
            # 将子节点拆分
            new_child = BTree.BTreeNode(self.t, self.keys[t:t+self.t-1], self.children[t+1:], self.is_leaf)
            self.keys = self.keys[:t-1]
            self.children = self.children[:t]
            self.children.append(new_child)
            self.children.append(child)

# 使用示例
btree = BTree(3)  # 创建一个阶数为3的B树
btree.insert(5)
btree.insert(7)
btree.insert(9)
btree.insert(1)
btree.insert(3)

2. 哈夫曼编码的压缩和解压

哈夫曼编码是一种高效的数据压缩方法。以下是一个使用哈夫曼树进行压缩和解压的示例:

python 复制代码
import heapq
from collections import defaultdict

class HuffmanCoding:
    def __init__(self):
        self.heap = []
        self.codes = {}
        self.reverse_mapping = {}

    def build_frequency(self, data):
        # 构建频率字典
        frequency = defaultdict(int)
        for char in data:
            frequency[char] += 1
        for char, freq in frequency.items():
            heapq.heappush(self.heap, (freq, char))

    def build_codes(self, root):
        # 构建哈夫曼编码
        if not root:
            return
        current_code = ""
        if root[1] != "":
            self.codes[root[1]] = current_code
            self.reverse_mapping[current_code] = root[1]
        self.build_codes(root[2])
        self.build_codes(root[3])

    def huffman_compress(self, data):
        self.build_frequency(data)
        if not self.heap:
            return "", {}
        while len(self.heap) > 1:
            freq1, char1 = heapq.heappop(self.heap)
            freq2, char2 = heapq.heappop(self.heap)
            merged = (freq1 + freq2, "", char1, char2)
            heapq.heappush(self.heap, merged)
        self.build_codes(heapq.heappop(self.heap))
        compressed_data = ''.join(self.codes[char] for char in data)
        return compressed_data, self.codes

    def decompress(self, data, codes):
        # 哈夫曼解压
        decompressed_data = []
        current_code = ""
        for bit in data:
            current_code += bit
            if current_code in self.reverse_mapping:
                decompressed_data.append(self.reverse_mapping[current_code])
                current_code = ""
        return ''.join(decompressed_data)

# 使用示例
huffman = HuffmanCoding()
data = "this is an example for huffman encoding"
compressed_data, codes = huffman.huffman_compress(data)
print("Compressed:", compressed_data)
decompressed_data = huffman.decompress(compressed_data, codes)
print("Decompressed:", decompressed_data)

3. 基于树的推荐系统

推荐系统可以使用树结构来组织和推荐项目。例如,一个基于类别的产品推荐系统:

python 复制代码
class Product:
    def __init__(self, id, name, category_id):
        self.id = id
        self.name = name
        self.category_id = category_id

class Category:
    def __init__(self, id, name):
        self.id = id
        self.name = name
        self.products = []

    def add_product(self, product):
        self.products.append(product)

    def recommend_products(self, n=5):
        # 推荐n个产品
        return sorted(self.products, key=lambda x: x.id)[:n]

class RecommendationSystem:
    def __init__(self):
        self.categories = {}

    def add_category(self, category):
        self.categories[category.id] = category

    def recommend(self, category_id, n=5):
        # 根据类别ID推荐n个产品
        category = self.categories.get(category_id)
        if category:
            return category.recommend_products(n)
        return []

# 使用示例
system = RecommendationSystem()
electronics = Category(1, "Electronics")
clothing = Category(2, "Clothing")

system.add_category(electronics)
system.add_category(clothing)

electronics.add_product(Product(101, "Laptop", 1))
electronics.add_product(Product(102, "Smartphone", 1))
clothing.add_product(Product(201, "T-Shirt", 2))
clothing.add_product(Product(202, "Jeans", 2))

print(system.recommend(1))  # 推荐电子产品
print(system.recommend(2))  # 推荐服装

1. 文件系统索引(使用B+树)

文件系统中的索引通常使用B+树来实现,以优化磁盘I/O操作。以下是一个简化的B+树实现:

python 复制代码
class BPlusTreeNode:
    def __init__(self, leaf=False):
        self.keys = []
        self.children = []
        self.leaf = leaf

class BPlusTree:
    def __init__(self, degree):
        self.root = BPlusTreeNode(leaf=True)
        self.degree = degree

    def search(self, key):
        # 搜索键值
        node = self.root
        while True:
            for index, k in enumerate(node.keys):
                if key < k:
                    node = node.children[index]
                    break
            else:
                if node.leaf:
                    return node, key
                node = node.children[-1]
                break

    # 插入、分裂、删除等操作需要根据B+树的特性实现
    # ...

# 使用示例
bplus_tree = BPlusTree(3)  # 假设每个节点最多有3个孩子
# 插入和搜索操作...

2. 浏览器的DOM树

浏览器将HTML文档解析为一个DOM树,每个节点可以是元素、属性或文本。以下是一个简单的DOM节点类:

python 复制代码
class DOMNode:
    def __init__(self, tag_name, attributes=None):
        self.tag_name = tag_name
        self.attributes = attributes or {}
        self.children = []

    def append_child(self, node):
        self.children.append(node)

    def __str__(self):
        attrs = ' '.join(f'{key}="{value}"' for key, value in self.attributes.items())
        return f"<{self.tag_name} {attrs}>{''.join(str(child) for child in self.children)}</{self.tag_name}>"

# 使用示例
html = DOMNode("html")
body = DOMNode("body")
p = DOMNode("p", {"class": "intro"})
html.append_child(body)
body.append_child(p)
print(html)  # 输出DOM树结构

3. 表达式求值(使用四则运算表达式树)

表达式树允许我们以树形结构存储和求值四则运算表达式。以下是一个简单的实现:

python 复制代码
class ExpressionTree:
    def __init__(self, root):
        self.root = root

    def evaluate(self):
        result = self.root.evaluate()
        return result

class ValueNode:
    def __init__(self, value):
        self.value = value

    def evaluate(self):
        return self.value

class OperatorNode:
    def __init__(self, left, operator, right):
        self.left = left
        self.operator = operator
        self.right = right

    def evaluate(self):
        left_val = self.left.evaluate()
        right_val = self.right.evaluate()
        if self.operator == '+':
            return left_val + right_val
        elif self.operator == '-':
            return left_val - right_val
        elif self.operator == '*':
            return left_val * right_val
        elif self.operator == '/':
            return left_val / right_val

# 使用示例
expr_tree = ExpressionTree(
    OperatorNode(
        ValueNode(10),
        '+',
        OperatorNode(ValueNode(5), '*', ValueNode(2))
    )
)
print(expr_tree.evaluate())  # 输出 20

4. 构建决策树(分类问题)

决策树是一种常用的机器学习算法,用于分类和回归问题。以下是一个简单的决策树构建示例:

python 复制代码
class DecisionNode:
    def __init__(self, feature=None, threshold=None, left=None, right=None, value=None):
        self.feature = feature
        self.threshold = threshold
        self.left = left
        self.right = right
        self.value = value

def calculate_gini(data, feature, threshold):
    # 计算Gini不纯度
    left = [row for row in data if row[feature] < threshold]
    right = [row for row in data if row[feature] >= threshold]
    gini_left = gini(left)
    gini_right = gini(right)
    return (len(left) / len(data)) * gini_left + (len(right) / len(data)) * gini_right

def gini(data):
    # 计算Gini不纯度
    labels = [row['class'] for row in data]
    return 1 - sum((p * p) for p in [labels.count(label) / len(labels) for label in labels])

def build_tree(data, features):
    remaining_features = features.copy()
    best_feature, best_threshold = None, None
    best_gini = 1

    for feature in remaining_features:
        for row in data:
            threshold = row[feature]
            gini_index = calculate_gini(data, feature, threshold)
            if gini_index < best_gini:
                best_gini = gini_index
                best_feature, best_threshold = feature, threshold

    left = [row for row in data if row[best_feature] < best_threshold]
    right = [row for row in data if row[best_feature] >= best_threshold]

    remaining_features.remove(best_feature)

    node = DecisionNode(best_feature, best_threshold)
    if not left and not right:
        node.value = majority_vote(data)
    else:
        node.left = build_tree(left, remaining_features)
        node.right = build_tree(right, remaining_features)

    return node

def majority_vote(data):
    labels = [row['class'] for row in data]
    return max(set(labels), key=labels.count)

# 使用示例
# 假设 data 是一个包含特征和类标签的列表
features = ['feature1', 'feature2', 'feature3']
tree = build_tree(data, features)

请注意,这些代码示例仅用于说明树结构在实际应用中的使用方式,并不是完整的项目代码。在实际项目中,你需要根据具体需求进行调整和完善。

相关推荐
wheeldown3 小时前
【数据结构】选择排序
数据结构·算法·排序算法
躺不平的理查德7 小时前
数据结构-链表【chapter1】【c语言版】
c语言·开发语言·数据结构·链表·visual studio
阿洵Rain8 小时前
【C++】哈希
数据结构·c++·算法·list·哈希算法
Leo.yuan8 小时前
39页PDF | 华为数据架构建设交流材料(限免下载)
数据结构·华为
半夜不咋不困8 小时前
单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构
数据结构·链表
忘梓.9 小时前
排序的秘密(1)——排序简介以及插入排序
数据结构·c++·算法·排序算法
y_m_h11 小时前
leetcode912.排序数组的题解
数据结构·算法
1 9 J11 小时前
数据结构 C/C++(实验三:队列)
c语言·数据结构·c++·算法
921正在学习编程11 小时前
数据结构之二叉树前序,中序,后序习题分析(递归图)
c语言·数据结构·算法·二叉树
毕竟秋山澪12 小时前
岛屿数量 广搜版BFS C#
数据结构·算法·宽度优先