2-3-4树
2-3-4树称为(2,4)树,满足两点:
·大小属性:每个内部节点最多有4个孩子
·深度属性:所有外部结点具有相同的深度
2-3-4树如图:
对2-3-4树的详细方法不进行叙述。
在树中使用单个结点搭建上图结构,令h3位_root,h1和h4非别为各自的_head结点。
单个结点图:
每个结点有四个指针
大致结构图:
保证每个节点的四个指针都指向其他结点或None
添加结点:
对应代码中的_up_split方法
如果添加结点后导致不满足大小属性时进行分裂操作:
如图此时k1,k2,k3,k4以k1为head,但此时不满足大小属性,将k3分裂添加到h1后。
分裂后:
删除结点:
对应代码中的_down_split方法
如果删除后导致外部结点不在同一深度时,有两种情况。
Case1: 兄弟结点不为单结点
此时将被删除结点、父节点、兄弟结点进行如下交换:
交换后为:
Case2 兄弟结点为单结点
此时将结点14和15做如下结点交换并合并连接:
操作后,在将结点11与原15结点位置交换,再将两结点合并连接:
结果为:
代码(附有操作方法)
class TreeMap2_3_4:
BLANK=object() # in down_split method, substitute other node
class Position:
''' position class'''
def __init__(self,node,container):
self._node=node
self._container=container
def element(self):
''' return value of position '''
return self._node._value
def key(self):
return self._node._key
def __eq__(self,other):
return type(self)==type(other) and self._node is other._node
#
class _Node:
''' creat the link node,'''
def __init__(self,k,v,before=None,after=None,parent=None,child=None):
self._key=k
self._value=v
self._before=before
self._after=after
self._parent=parent
self._child=child
#--------------------------convennient the node------------------------
def __eq__(self,k):
''' return true, if k==self._key'''
if type(k) ==int:
return self._key==k
elif isinstance(k,type(self)):
return self._key==k._key
def __nq__(self,k):
return not self==k
def __lt__(self,k):
''' return true if k < self._key'''
if type(k) ==int:
return self._key<k
elif isinstance(k,type(self)):
return self._key<k._key
def __gt__(self,k):
return not self<k and self!=k
def __le__(self,k):
return self<k or self == k
def __ge__(self, k):
return self>k or self ==k
#--------------------------------
def __init__(self):
''' root return the first node'''
self._root=None
self._size=0
def _validate(self,p):
''' Return associated node, if position is valid.'''
if not isinstance(p, self.Position):
raise TypeError('p must be proper Position type')
if p._container is not self:
raise ValueError('p does not belong to this container')
if p._node._parent is p._node: # convention for deprecated nodes
raise ValueError('p is no longer valid')
return p._node
def _make_position(self,node):
''' return position of node '''
return self.Position(node,self) if node != None else None
def _add_after(self,p,temp,head_node=None):
''' add a node after p,p is Position class;
reconect node's after,before parent,without child.
'''
node=self._validate(p)
# temp's before is node,after is node's after
#,parent is node's parent
temp._before=node
temp._after=node._after
temp._parent=node._parent
node._after = temp
if temp._after is not None:
temp._after._before=temp
if head_node is not None:
while temp is not None: # repoint child's parent,_add_beofre method can't repoint
subnode = temp._child
while subnode is not None:
subnode._parent = head_node
subnode = subnode._after
temp = temp._after
return self._make_position(temp)
def _add_before(self,p,temp,head_node=None):
''' this method can only be used for p which before node is none;
add a node before p,p is Position and head node;
temp is a _Node;
head_node is _Node class;
reconnect node's child,parent'before and after.
'''
node=self._validate(p)
# temp's before is node._before,after is node,
#parent is node._parent
if temp._before is not None and temp._child is None: # in case 2.1 of down_split method
temp._child=node._before
else:
temp._before=node._before
temp._after=node
temp._parent=node._parent
node._before=temp
parent=self.parent(p)
if parent is None:
self._root=temp
else:
parent=self._validate(parent)
if parent._before is node:
parent._before = temp
if parent._child is node:
parent._child = temp
tempnode=temp
if head_node is not None:
while tempnode is not None: # repoint child's parent,
subnode = tempnode._child
while subnode is not None:
subnode._parent = head_node
subnode = subnode._after
tempnode = tempnode._after
return self._make_position(temp) # now temp is the head
def _add(self,p,k,v,head):
''' add a node in a proper posiiton '''
node=self._validate(p)
temp=self._Node(k,v)
self._size+=1
if node < k:
self._add_after(p,temp)
self._up_split(head)
else:
self._up_split(self._add_before(p,temp,temp))
def _search(self,k,head=None,node=None):
''' return the proper Position and head if chain's child is None;
find begin of root if node is None
head and node are _Node class
'''
if node is None:
node=self._root
head=node
#print(node,k,self._root)
if node>k: # recursion to node's before
if node._before is None:# break the cursion if there is none child
return self._make_position(node),self._make_position(head)
return self._search(k,node._before,node._before)
if node==k: # break the cursion
return self._make_position(node),self._make_position(head)
if node<k: # recursion to node's after
if node._after is not None: # if there is item after node
if k<node._after: # node<k<node._after
if node._child is None: # node is the last node
return self._make_position