【数据结构】——1.1树

数据结构——1.1树

单纯记录,代码都是python



术语

  • 根节点:无前驱(双亲)
  • 节点的度:拥有的子树的个数
  • 树的度:所有节点度的最大值
  • 叶子节点/终端节点:度=0,没有后继(孩子)
  • 分支节点/内部节点:其他的,度≠0
  • 树的深度:最大的层次
  • 前后层级:双亲和孩子
  • 同一层级:同一个双亲-兄弟节点,不同双亲-堂兄弟节点

  • 有序树,无序树
  • 森林(一堆不相交的树),如果删除一棵树的根节点,所有子树构成森林,一棵树是特殊的森林

二叉树

每个节点最多两个子节点,所有树都可以和二叉树相互转换

  • 子树有左右之分,不能颠倒,只有一个子树,则不用区分(显然)
  • 第i层,最多有 2^(i-1) 个节点,至少有1 个节点

  • 深度为k的二叉树,最多有2^k-1个节点,至少有k个节点

  • 任何二叉树,叶子数为a,度为2的节点数为b,则a=b+1

满二叉树

所有内部节点都有两个子节点,即深度为k有2^k-1个节点
叶子节点全在最后一层

完全二叉树

定义:深度为k有n个节点,当且仅当某个节点都和深度为k的满二叉树中编号为1~n的节点一一对应

理解:从上至下,从左至右编号,完全二叉树是满二叉树移除最后一个,最后两个这样的二叉树,就是只能队伍最后一个或者连续几个没了,前面必须和满二叉树一样

  • n个节点的完全二叉树深度为log2(n)取下整+1

在这里插入图片描述

  • 父子节点编号关系

在这里插入图片描述

存储和遍历+代码

  • 顺序存储:
    按编号,没有的位置用0代替,浪费空间,适合满二叉树和完全二叉树
class ArrayBinaryTree:
    def __init__(self, capacity):
        # 初始化一个定长数组用于存储二叉树的节点,容量为capacity
        self.tree = [None] * capacity
        self.capacity = capacity

    # 添加元素到树中
    def add(self, value):
        # 检查树是否满了
        for i in range(self.capacity):
            if self.tree[i] is None:
                self.tree[i] = value
                return
        print("树已满,无法添加新元素")

    # 访问指定位置的节点
    def get(self, index):
        if 0 <= index < self.capacity:
            return self.tree[index]
        else:
            return None

    # 获取左子节点
    def get_left_child(self, index):
        left_index = 2 * index + 1
        if left_index < self.capacity:
            return self.tree[left_index]
        return None

    # 获取右子节点
    def get_right_child(self, index):
        right_index = 2 * index + 2
        if right_index < self.capacity:
            return self.tree[right_index]
        return None

    # 获取父节点
    def get_parent(self, index):
        if index == 0:
            return None  # 根节点没有父节点
        parent_index = (index - 1) // 2
        return self.tree[parent_index]

    # 展示整个树的数组表示
    def display(self):
        print(self.tree)


# 示例:构建一个容量为 7 的顺序存储二叉树
tree = ArrayBinaryTree(7)

# 添加元素(按顺序添加,模拟完全二叉树)
tree.add(1)  # 根节点
tree.add(2)  # 根的左子节点
tree.add(3)  # 根的右子节点
tree.add(4)  # 2的左子节点
tree.add(5)  # 2的右子节点
tree.add(6)  # 3的左子节点
tree.add(7)  # 3的右子节点

# 打印整个二叉树数组表示
tree.display()

# 获取节点
print("索引 0 处的节点值:", tree.get(0))  # 根节点 1
print("索引 1 处的左子节点值:", tree.get_left_child(1))  # 4
print("索引 1 处的右子节点值:", tree.get_right_child(1))  # 5
print("索引 5 处的父节点值:", tree.get_parent(5))  # 3


  • 链式存储
    左子节点|数据|右子节点,

n个节点,有n+1个空指针域
一共2n个,每个节点一个父节点,n-个有存放,2n-n+1

  • 三叉链表
  • 左子节点|数据|父节点|右子节点,
class TreeNode:
    def __init__(self, value):
        self.value = value        # 节点值
        self.left = None          # 左子节点
        self.right = None         # 右子节点

class BinaryTree:
    def __init__(self):
        self.root = None          # 初始化根节点为空

    # 插入元素,按照二叉树的规则插入(这里以二叉搜索树为例)
    def insert(self, value):
        new_node = TreeNode(value)
        if self.root is None:
            self.root = new_node   # 如果根节点为空,直接插入为根节点
        else:
            self._insert_recursive(self.root, new_node)

    # 递归插入节点
    def _insert_recursive(self, current_node, new_node):
        if new_node.value < current_node.value:
            # 如果新节点的值小于当前节点,插入到左子树
            if current_node.left is None:
                current_node.left = new_node
            else:
                self._insert_recursive(current_node.left, new_node)
        else:
            # 如果新节点的值大于或等于当前节点,插入到右子树
            if current_node.right is None:
                current_node.right = new_node
            else:
                self._insert_recursive(current_node.right, new_node)

    # 先序遍历 (根 -> 左 -> 右)
    def preorder_traversal(self, node):
        if node:
            print(node.value, end=" ")  # 访问根节点
            self.preorder_traversal(node.left)   # 递归访问左子树
            self.preorder_traversal(node.right)  # 递归访问右子树

    # 中序遍历 (左 -> 根 -> 右)
    def inorder_traversal(self, node):
        if node:
            self.inorder_traversal(node.left)    # 递归访问左子树
            print(node.value, end=" ")           # 访问根节点
            self.inorder_traversal(node.right)   # 递归访问右子树

    # 后序遍历 (左 -> 右 -> 根)
    def postorder_traversal(self, node):
        if node:
            self.postorder_traversal(node.left)  # 递归访问左子树
            self.postorder_traversal(node.right) # 递归访问右子树
            print(node.value, end=" ")           # 访问根节点

# 示例:构建一棵二叉树
tree = BinaryTree()

# 插入节点
tree.insert(5)
tree.insert(3)
tree.insert(7)
tree.insert(2)
tree.insert(4)
tree.insert(6)
tree.insert(8)

# 遍历树结构
print("先序遍历:")
tree.preorder_traversal(tree.root)  # 输出:5 3 2 4 7 6 8
print("\n中序遍历:")
tree.inorder_traversal(tree.root)   # 输出:2 3 4 5 6 7 8
print("\n后序遍历:")
tree.postorder_traversal(tree.root) # 输出:2 4 3 6 8 7 5

如果所有节点的值都没有相同的,、前中后序列唯一

前+中,或者后+中可以确定唯一的二叉树

表达式计算的代码——后序遍历(Post-order Traversal):

 3 + (5 * 2)
 
     +
    / \
   3   *
      / \
     5   2

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

# 判断是否为运算符
def is_operator(c):
    return c in ['+', '-', '*', '/']

# 递归计算表达式树的值
def evaluate_expression_tree(node):
    if node is None:
        return 0

    # 如果当前节点是叶节点(操作数),直接返回其值
    if node.left is None and node.right is None:
        return int(node.value)

    # 递归计算左子树和右子树的值
    left_value = evaluate_expression_tree(node.left)
    right_value = evaluate_expression_tree(node.right)

    # 根据当前节点的运算符执行计算
    if node.value == '+':
        return left_value + right_value
    elif node.value == '-':
        return left_value - right_value
    elif node.value == '*':
        return left_value * right_value
    elif node.value == '/':
        return left_value / right_value

# 示例构建表达式树: 3 + (5 * 2)
root = TreeNode('+')
root.left = TreeNode('3')
root.right = TreeNode('*')
root.right.left = TreeNode('5')
root.right.right = TreeNode('2')

# 计算表达式的值
result = evaluate_expression_tree(root)
print(f"表达式的值为: {result}")


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_43507078

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值