Exemple #1
0
 def splay(self, v: BinNode) -> BinNode:
     # v为最近访问需要伸展的节点
     if not v:
         return None
     while v.parent and v.parent.parent:  # 短路,父节点不存在直接跳出
         # 父节点,祖父节点都存在时进行一次调整
         # 将节点v上移两层,并同时有可能缩减三个节点的高度
         p: BinNode = v.parent
         g: BinNode = p.parent
         gg: BinNode = p.parent  # 记录g的父节点,调整后接入该节点
         if v.IsLChild():
             if p.IsLChild():  # zig-zig
                 attach_as_lchild(g, p.rc)
                 attach_as_lchild(p, v.rc)
                 attach_as_rchild(p, g)
                 attach_as_rchild(v, p)
             else:  # zig-zag
                 attach_as_lchild(p, v.rc)
                 attach_as_rchild(g, v.lc)
                 attach_as_lchild(v, g)
                 attach_as_rchild(v, p)
         else:
             if p.IsRChild():  # zag-zag
                 attach_as_rchild(g, p.lc)
                 attach_as_rchild(p, v.lc)
                 attach_as_lchild(v, g)
                 attach_as_rchild(v, p)
             else:  # zag-zig
                 attach_as_rchild(p, v.lc)
                 attach_as_lchild(g, v.rc)
                 attach_as_rchild(v, g)
                 attach_as_lchild(v, p)
         if gg is None:  # gg不存在时,v为根节点
             v.parent = None
         else:  # 根据原来节点g的位置接入当前子树
             if g == gg.lc:
                 attach_as_lchild(gg, v)
             else:
                 attach_as_rchild(gg, v)
         self.updateHeight(g)  # 更新相关节点高度
         self.updateHeight(p)
         self.updateHeight(v)
     p: BinNode = v.parent
     if p is not None:
         # 上面的调整是三层一组进行调整
         # 如果v只有父节点,进行一次两层的调整
         if v.IsLChild():
             attach_as_lchild(p, v.rc)
             attach_as_rchild(v, p)
         else:
             attach_as_rchild(p, v.lc)
             attach_as_lchild(v, p)
         self.updateHeight(p)
         self.updateHeight(v)
     v.parent = None  # 调整后v为根节点
     return v
Exemple #2
0
 def rotate_at(self, v: BinNode):
     """根据中序遍历结果确定3代节点顺序以及4棵子树顺序"""
     p: BinNode = v.parent  # 父节点
     g: BinNode = p.parent  # 祖父节点
     if p.IsLChild():
         if v.IsLChild():
             p.parent = g.parent  # 重构后子树与原来avl树连接
             return self.connect34(v, p, g, v.lc, v.rc, p.rc, g.rc)
         else:
             v.parent = g.parent
             return self.connect34(p, v, g, p.lc, v.lc, v.rc, g.rc)
     else:
         if v.IsRChild():
             p.parent = g.parent
             return self.connect34(g, p, v, g.lc, p.lc, v.lc, v.rc)
         else:
             v.parent = g.parent
             return self.connect34(g, v, p, g.lc, v.lc, v.rc, p.rc)
Exemple #3
0
 def insert(self, e):
     """插入节点,返回插入后节点"""
     node = self.search(e)
     if node:
         # 约定不含重复元素,故元素重复是不做操作直接返回
         return node
     node = BinNode(data=e, parent=self._hot)  # 插入节点,空树也可正常处理
     self._size += 1
     self.updateHeightAbove(node)  # 更新x历代祖先高度
     return node
Exemple #4
0
 def insert(self, e) -> BinNode:
     if self._root is None:  # 处理空树的情况
         self._size += 1
         self._root = BinNode(e)
         return self._root
     node = self.search(e)
     if node.data == e:  # 约定不含重复元素,已有该元素是直接返回该节点
         return self._root
     t = self._root
     if self._root.data < e:  # 判断新节点的插入位置
         t.parent = self._root = BinNode(e, None, t, t.rc)
         if t.HasRChild():
             t.rc.parent = self._root
             t.rc = None
     else:
         t.parent = self._root = BinNode(e, None, t.lc, t)
         if t.HasLChild():
             t.lc.parent = self._root
             t.lc = None
     self._size += 1
     self.updateHeight(t)
     return self._root
Exemple #5
0
 def removeAt(self, x: BinNode):
     """实际移除节点方法"""
     remove_node = x  # 实际摘除的节点,初始值为x
     succ = None  # 实际被删除节点的接替者
     if not x.HasLChild():  # 没有左节点,直接用右节点代替
         succ = x = x.rc
     elif not x.HasRChild():
         succ = x = x.lc
     else:
         remove_node = remove_node  # 寻找移除节点的后继节点
         # 后继节点是当前节点右子树左侧分支的末端,一定没有左孩子
         x.data, remove_node.data = remove_node.data, x.data
         # 移除节点与后继节点交换,可以只交换数据
         # 待删除节点交换后至多只有一个右孩子
         u = remove_node.parent  # 获取后继节点的父节点
         if u == x:  # 只有当移除节点是后继节点的父节点时,删除后插入右分支
             u.rc = succ = remove_node.rc
         else:  # 其他情况都是插入左分支
             u.lc = succ = remove_node.rc
     self._hot = remove_node.parent  # 可能需要更新高度的最低节点
     if succ:  # succ不为None时需指定父节点
         succ.parent = self._hot
     del remove_node
     return succ
Exemple #6
0
 def connect34(self, a: BinNode, b: BinNode, c: BinNode, t0: BinNode,
               t1: BinNode, t2: BinNode, t3: BinNode):
     """3+4重构,根据中序遍历结果确定的顺序,直接重构子树,不进行zig,zag旋转"""
     a.lc = t0
     if t0: t0.parent = a
     a.rc = t1
     if t1:
         t1.parent = a
         self.updateHeight(a)
     c.lc = t2
     if t2: t2.parent = c
     c.rc = t3
     if t3:
         t3.parent = c
         self.updateHeight(c)
     b.lc = a
     a.parent = b
     b.rc = c
     c.parent = b
     self.updateHeight(b)
     return b
Exemple #7
0
class Splay(BST):
    def search(self, e) -> BinNode:
        # 调整搜索结果到树根,查找失败时也将_hot节点调整至树根
        p = self.serrch_in(self._root, e)
        self._root = self.splay(p if p else self._hot)
        return self._root

    def insert(self, e) -> BinNode:
        if self._root is None:  # 处理空树的情况
            self._size += 1
            self._root = BinNode(e)
            return self._root
        node = self.search(e)
        if node.data == e:  # 约定不含重复元素,已有该元素是直接返回该节点
            return self._root
        t = self._root
        if self._root.data < e:  # 判断新节点的插入位置
            t.parent = self._root = BinNode(e, None, t, t.rc)
            if t.HasRChild():
                t.rc.parent = self._root
                t.rc = None
        else:
            t.parent = self._root = BinNode(e, None, t.lc, t)
            if t.HasLChild():
                t.lc.parent = self._root
                t.lc = None
        self._size += 1
        self.updateHeight(t)
        return self._root

    def remove(self, e):
        if self._root is None or self.search(e).data != e:
            # 空树或者待删除节点不存在,则无法删除
            return False
        w = self._root
        if self._root.HasLChild():
            # 没有左子树直接删除
            self._root = self._root.rc
            if self._root is not None:
                self._root.parent = None
        elif self._root.HasRChild():
            # 没有右子树直接删除
            self._root = self._root.lc
            if self._root is not None:
                self._root.parent = None
        else:  # 两个子树都存在
            l_tree = self._root.lc
            l_tree.parent = None
            self._root.lc = None  # 暂时摘除左子树
            self._root = self._root.rc  # 右子树保留
            self._root.parent = None
            self.search(w.data)
            # 在右子树中查找原来根节点,查找失败,但是会将最小节点伸展至根节点
            # 该节点最小,故其左子树肯定是空
            self._root.lc = l_tree  # 空的左子树接入原来的左子树
            l_tree.parent = self._root
        self.size -= 1
        if self._root is not None:
            # 更新根节点高度,其他节点高度在伸展过车工中已经更新过
            self.updateHeight(self._root)
        return True

    def splay(self, v: BinNode) -> BinNode:
        # v为最近访问需要伸展的节点
        if not v:
            return None
        while v.parent and v.parent.parent:  # 短路,父节点不存在直接跳出
            # 父节点,祖父节点都存在时进行一次调整
            # 将节点v上移两层,并同时有可能缩减三个节点的高度
            p: BinNode = v.parent
            g: BinNode = p.parent
            gg: BinNode = p.parent  # 记录g的父节点,调整后接入该节点
            if v.IsLChild():
                if p.IsLChild():  # zig-zig
                    attach_as_lchild(g, p.rc)
                    attach_as_lchild(p, v.rc)
                    attach_as_rchild(p, g)
                    attach_as_rchild(v, p)
                else:  # zig-zag
                    attach_as_lchild(p, v.rc)
                    attach_as_rchild(g, v.lc)
                    attach_as_lchild(v, g)
                    attach_as_rchild(v, p)
            else:
                if p.IsRChild():  # zag-zag
                    attach_as_rchild(g, p.lc)
                    attach_as_rchild(p, v.lc)
                    attach_as_lchild(v, g)
                    attach_as_rchild(v, p)
                else:  # zag-zig
                    attach_as_rchild(p, v.lc)
                    attach_as_lchild(g, v.rc)
                    attach_as_rchild(v, g)
                    attach_as_lchild(v, p)
            if gg is None:  # gg不存在时,v为根节点
                v.parent = None
            else:  # 根据原来节点g的位置接入当前子树
                if g == gg.lc:
                    attach_as_lchild(gg, v)
                else:
                    attach_as_rchild(gg, v)
            self.updateHeight(g)  # 更新相关节点高度
            self.updateHeight(p)
            self.updateHeight(v)
        p: BinNode = v.parent
        if p is not None:
            # 上面的调整是三层一组进行调整
            # 如果v只有父节点,进行一次两层的调整
            if v.IsLChild():
                attach_as_lchild(p, v.rc)
                attach_as_rchild(v, p)
            else:
                attach_as_rchild(p, v.lc)
                attach_as_lchild(v, p)
            self.updateHeight(p)
            self.updateHeight(v)
        v.parent = None  # 调整后v为根节点
        return v
Exemple #8
0
def attach_as_rchild(p: BinNode, rc: BinNode) -> None:
    p.rc = rc
    if rc is not None:
        rc.parent = p
Exemple #9
0
def attach_as_lchild(p: BinNode, lc: BinNode) -> None:
    p.lc = lc
    if lc is not None:
        lc.parent = p