Python中的树形数据结构: 2-3-4树
2-3-4树是一种平衡树,也称为多路查找树。它的特点是每个节点可以存储两条、三条或四条数据和三个、四个或五个子节点,使得树保持平衡。以下是该数据结构的详细介绍和代码演示实现。
2-3-4树定义:
- 节点包含k-1个数据和k个子节点,其中2 <= k <= 4,且k为偶数。
- 节点的数据必须按顺序排列。(如二叉搜索树中的节点)
- 所有叶子节点必须在同一层,即具有相同深度。
- 非叶子节点包含的数据与子节点数维持以下规则:
- 若包含一条数据,则有两个子节点。
- 若包含两条数据,则有三个子节点。
- 若包含三条数据,则有四个子节点。
2-3-4树的插入操作:
- 将数据插到叶子节点上。如果插入之后,节点达到了四条数据,则需要进行分裂操作。
- 若该节点为根节点,则直接分裂,新根节点为原节点的中间元素,左右子节点为原节点的两半。
- 否则,将原节点中间元素上移至父节点,若父节点已有四个数据,则递归进行分裂操作。
- 递归寻找插入位置时,遇到满子节点也需要进行分裂操作,直到到达叶子节点。
2-3-4树的删除操作:
- 删除节点时,若该节点不是叶子节点,则用它的后继节点的值替换,然后删除后继节点。
- 在叶子节点中删除该值,如果该节点元素的数量少于2,则考虑以下情况:
- 如果一个兄弟节点有一个额外的字符,则转移一个字符以保持平衡。
- 如果所有的兄弟节点仅包含2个字符,则删除一个元素并合并为一个节点。
- 如果父节点仅包含2个元素,则可以将一个兄弟节点合并到父节点中。
Python代码演示实现:
class Node: # 2-3-4树的节点类 def __init__(self): self.data = [] # 该节点包含的数据 self.child = [] # 该节点的子节点 def is_leaf(self): # 是否为叶子节点 return not self.child def is_full(self): # 是否已满 return len(self.data) >= 3 def insert_data(self, value): # 插入值 # 插入数据并排序 self.data.append(value) self.data.sort() # 若该节点满了,则进行分裂操作 if self.is_full(): return self.split() return None def split(self): if not self.is_full(): return None # 新建一个节点,作为当前节点的右兄弟节点 right = Node() # 移动两个最大的值(中间值和最大值)到右节点 right.data = self.data[2:] right.child = self.child[2:] # 新构建一个节点,作为新子节点,新子节点包括原来节点最小值的子节点 new_node = Node() new_node.data.append(self.data[1]) new_node.child.append(self.child[0]) new_node.child.append(self.child[1]) # 删除当前节点的最大值和中间值,并将右节点挂在新父节点上 del self.data[1:] del self.child[1:] self.child.append(new_node) self.child.append(right) return self class Tree234: # 2-3-4树类 def __init__(self): self.root = Node() # 根节点 def insert(self, value): # 插入节点 # 获取根节点 node = self.root # 寻找插入点 while True: # 遍历孩子节点 i = len(node.data) - 1 while i >= 0 and value < node.data[i]: i -= 1 # 若找到了插入位置,则插入 if node.is_leaf(): return node.insert_data(value) # 若未找到插入位置,则移到孩子节点 child = node.child[i + 1] if child.is_full(): node.split() if value > node.data[-1]: child = node.child[-1] else: child = node.child[i] node = child def search(self, value): # 查找值是否存在 # 获取根节点 node = self.root # 遍历节点,直到找到叶子节点 while node: # 遍历节点中的数据,查找目标值 for x in node.data: if value == x: return True elif value < x: break # 找到对应的孩子节点,继续遍历 if node.is_leaf(): return False else: i = 0 while i < len(node.data) and value > node.data[i]: i += 1 node = node.child[i] return False def test_tree(): tree = Tree234() # 插入值 for value in ["pandabuy", "pandabuyit", "pandabuymore", "pandabuyabc", "python"]: tree.insert(value) # 查找值 assert tree.search("pandabuy") == True assert tree.search("pandabuyit") == True assert tree.search("pandabuymore") == True assert tree.search("pandabuyabc") == True assert tree.search("python") == True assert tree.search("pandabu") == False assert tree.search("java") == False test_tree() # 运行测试
相关文章