数据结构与算法 —— 树的基本操作以及实现(python实现)

目录

前言

1. 实现一个通用节点类

1.1 import及声明泛型类型变量

1.2 定义类

1.3 定义__init__ 方法 

1.4 获取和设置节点的值

1.5  获取节点的父节点

1.6 获取和设置节点的子树大小

1.7 添加子节点和获取子节点列表及个数

1.8 判断内部/外部节点 

1.9 判断根节点

2. 实现一个通用树类

2.1 import及声明泛型类型变量

2.2 定义类和__init__ 方法 

2.3 获取根节点以及节点数量

2.6  判断是否为空树以及节点是否为根节点

2.7 判断是否有子节点

2.8 添加节点和移除节点

2.9 先序和后序遍历

3. 结尾


前言

树是由节点和边组成的非线性数据结构。其结构可以用来表示层次关系,例如文件系统的目录结构、公司的组织架构等。本文用python来实现一颗通用树,可以用于构建任何类型的树,如二叉树、多叉树等。


1. 实现一个通用节点类

1.1 import及声明泛型类型变量

from typing import Generic, TypeVar, List
T = TypeVar('T')

typing 模块导入了 GenericTypeVarList。其中,Generic 是一个泛型基类,可以用来定义泛型类型,TypeVar 则用于定义类型变量,List 是一个泛型类型,表示列表。 

接着,定义了一个类型变量 T,用于表示节点存储的值的类型。

1.2 定义类

class Node(Generic[T]):
    _value: int
    _parent: 'Node[T]'
    _children: List['Node[T]']
    _subtree_size: int

定义了一个类 Node,并使用 Generic[T] 表示它是一个泛型类,类型参数为 T

在类中定义了四个属性,分别是 _value_parent_children_subtree_size。其中,_value 用于存储节点的值,_parent 用于存储节点的父节点,_children 用于存储节点的子节点列表,_subtree_size 用于存储节点的子树大小。

1.3 定义__init__ 方法 

def __init__(self, value: T) -> None:
        self._value = value
        self._parent = None
        self._children = []
        self._subtree_size = 1

用于初始化节点实例。该方法接收一个参数 value,用于设置节点的值。在方法中,将节点的值、父节点、子节点列表和子树大小都设置为默认值。 

1.4 获取和设置节点的值

    def get_value(self) -> T:
        return self._value

    def set_value(self, value: T) -> None:
        self._value = value

1.5  获取节点的父节点

    def get_parent(self) -> 'Node[T]':
        return self._parent

1.6 获取和设置节点的子树大小

    def get_subtree_size(self) -> int:
        return self._subtree_size

    def set_subtree_size(self, value: int) -> None:
        self._subtree_size = value

1.7 添加子节点和获取子节点列表及个数

    def add_child(self, child: 'Node[T]') -> None:
        self._children.append(child)
        child._parent = self
    
    def get_children(self) -> List['Node[T]']:
        return self._children

    def num_children(self) -> int:
        return len(self._children)

1.8 判断内部/外部节点 

    def is_internal(p: 'Node[T]') -> bool:
        return len(p._children) != 0 # 有子节点
        
    def is_external(p: 'Node[T]') -> bool:
        return len(p._children) == 0 # 无子节点

1.9 判断根节点

    def is_root(p: 'Node[T]') -> bool:
        return p._parent == None

2. 实现一个通用树类

2.1 import及声明泛型类型变量

from node import Node
from typing import Generic, TypeVar, List

T = TypeVar('T')

2.2 定义类和__init__ 方法 

class Tree(Generic[T]):
    _size: int
    _root: Node[T]

    def __init__(self, root: 'Node[T]') -> None:
        self._root = root
        self._size = 0
        if root != None:
            self._size = 1

在类中定义了两个属性,分别是 _size_root。其中,_size 用于存储树的节点数,_root 用于存储树的根节点。

在__init__ 方法中接收一个参数 root,用于设置树的根节点。在方法中,将根节点和节点数都设置为默认值。如果根节点不为空,则将节点数设置为 1。 

2.3 获取根节点以及节点数量

    def get_root(self) -> 'Node[T]':
        return self._root
    
    def get_size(self) -> int:
        return self._size

2.6  判断是否为空树以及节点是否为根节点

    def is_empty(self) -> bool:
        return self._root == None  

    def is_root(self, p: 'Node[T]') -> bool:
        if p is None:
            return False
        return p.get_parent() == None

2.7 判断是否有子节点

def is_leaf(self, p: 'Node[T]') -> bool:
    if p is None:
        return False
    return p.is_external()

2.8 添加节点和移除节点

    def add_node(self, p: 'Node[T]', parent: 'Node[T]') -> None:
        if self._root is None and p != None and parent is None:
            self._root = p
            self._size += 1
            
        elif (p is None) or (parent is None):
            return
        
        else:
            parent.add_child(p)
            self._size += 1

        # Update subtree size for parent and all its ancestors.
        while p.get_parent() != None:
            p = p.get_parent()
            p_subtree = p.get_subtree_size()
            p.set_subtree_size(p_subtree + 1)

    def remove_node(self, p: 'Node[T]') -> None:
        if p is None:
            return

        if p.is_root():
            self._root = None
            self._size = 0
        else:
            current = p
            subtree_size = p.get_subtree_size()
            while p.get_parent() != None:
                p = p.get_parent()
                p.set_subtree_size(p.get_subtree_size() - subtree_size)
            parent = current.get_parent()
            parent.get_children().remove(current)
            self._size -= subtree_size

add_node用于添加节点。它接受两个参数 pparent,将节点 p 添加为 parent 的子节点。如果树为空,则将 p 设置为根节点。如果 pparent 为空,则不进行任何操作。添加节点后,会更新其父节点及其所有祖先节点的子树大小(即 _subtree_size 属性)。

remove_node用于删除节点。它接受一个参数 p,表示要删除的节点。如果节点 p 为空,则不进行任何操作。如果节点 p 是根节点,则将树清空。否则,删除节点并更新其父节点及其所有祖先节点的子树大小。 

2.9 先序和后序遍历

    def preorder(self, p: 'Node[T]', ls: List['Node[T]']) -> None:
        if p is None:
            return

        ls.append(p)
        for child in p._children:
            self.preorder(child, ls)
    
    def postorder(self, p: 'Node[T]', ls: List['Node[T]']) -> None:
        if p is None:
            return
        
        for child in p._children:
            self.postorder(child,ls)
        ls.append(p)

3. 结尾

这是一个基本的树的实现,可以基于这个树实现有具体要求的树。

如果文中有什么错误欢迎大家留言指出,如果帮助到你的话可以小小的三连一波!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值