数据结构与算法 —— 树的基本操作以及实现(python实现)
目录
前言
树是由节点和边组成的非线性数据结构。其结构可以用来表示层次关系,例如文件系统的目录结构、公司的组织架构等。本文用python来实现一颗通用树,可以用于构建任何类型的树,如二叉树、多叉树等。
1. 实现一个通用节点类
1.1 import及声明泛型类型变量
from typing import Generic, TypeVar, List
T = TypeVar('T')
从
typing模块导入了Generic、TypeVar和List。其中,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用于添加节点。它接受两个参数
p和parent,将节点p添加为parent的子节点。如果树为空,则将p设置为根节点。如果p或parent为空,则不进行任何操作。添加节点后,会更新其父节点及其所有祖先节点的子树大小(即_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. 结尾
这是一个基本的树的实现,可以基于这个树实现有具体要求的树。
如果文中有什么错误欢迎大家留言指出,如果帮助到你的话可以小小的三连一波!
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)