目录
前言
树是由节点和边组成的非线性数据结构。其结构可以用来表示层次关系,例如文件系统的目录结构、公司的组织架构等。本文用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. 结尾
这是一个基本的树的实现,可以基于这个树实现有具体要求的树。
如果文中有什么错误欢迎大家留言指出,如果帮助到你的话可以小小的三连一波!