📌  相关文章
📜  Proto Van Emde蟒蛇树|套装6 |查询:继任者和前任者(1)

📅  最后修改于: 2023-12-03 14:45:40.513000             🧑  作者: Mango

Proto Van Emde蟒蛇树

Proto Van Emde蟒蛇树是一种用于支持数值集合的数据结构。它可以支持向集合中插入元素、删除元素以及查询元素是否存在等操作,以及维护一些集合特性,如前驱、后继、最小值、最大值等。Proto Van Emde蟒蛇树的时间复杂度为$O(\log\log M)$,其中M是集合中元素的最大值。

继任者和前任者

在Proto Van Emde蟒蛇树中,我们需要支持查找某个元素的继任者和前任者。继任者指的是集合中比某个元素大的最小元素,前任者指的是集合中比某个元素小的最大元素。我们可以使用Proto Van Emde蟒蛇树中的高层结构来实现这两个操作。

查找后继者

对于查找后继者操作,我们可以从根节点开始递归向下遍历Proto Van Emde蟒蛇树。如果待查找元素x比当前节点的最大元素小,则该节点的最小元素就是x的后继者;否则我们需要递归调用其子节点来查找。具体地,假设当前节点的最大元素为max,最小元素为min,其子节点的最大元素为$max'$,最小元素为$min'$。若x小于等于$max'$,则我们在对应子节点$child_i$中递归查找;否则我们需要查找下一个子节点$j$,使得$max_j > x$,然后在子节点$j$中查找其最小元素。最终我们得到的就是x的后继者。

查找前任者

对于查找前任者操作,思路类似于查找后继者,但是我们从根节点开始遍历,检查当前节点的最小元素。如果待查找元素x比当前节点的最小元素大,则该节点的最大元素就是x的前任者。否则我们需要递归调用其祖先节点来查找。具体地,我们找到第一个不包含x的祖先节点$id$,并返回节点$id$的最大元素$max$。如果没有这样的祖先节点,则返回空值。

示例代码

下面是查找后继者和前任者的Python代码实现:

class VEB:
    def __init__(self, size):
        self.min = None
        self.max = None
        self.summary = None
        self.cluster = [None] * size

    def high(self, x):
        """
        Get the cluster index of x.
        """
        return x // int(math.sqrt(len(self.cluster)))

    def low(self, x):
        """
        Get the index of x in the corresponding cluster.
        """
        return x % int(math.sqrt(len(self.cluster)))

    def index(self, x, y):
        """
        Map 2D index to 1D index.
        """
        return x * int(math.sqrt(len(self.cluster))) + y

    def member(self, x):
        """
        Check if x is in the set.
        """
        if x == self.min or x == self.max:
            return True
        elif self.min is None or self.max is None or x < self.min or x > self.max:
            return False
        else:
            return self.cluster[self.high(x)].member(self.low(x))

    def insert(self, x):
        """
        Insert x into the set.
        """
        if self.min is None:
            self.min = x
            self.max = x
        else:
            if x < self.min:
                x, self.min = self.min, x
            if self.max < x:
                self.max = x
            if len(self.cluster) > 2:
                hi = self.high(x)
                lo = self.low(x)
                if self.cluster[hi] is None:
                    self.cluster[hi] = VEB(int(math.sqrt(len(self.cluster))))
                if self.summary is None:
                    self.summary = VEB(int(math.sqrt(len(self.cluster))))
                if self.cluster[hi].min is None:
                    self.summary.insert(hi)
                    self.cluster[hi].min = lo
                    self.cluster[hi].max = lo
                else:
                    self.cluster[hi].insert(lo)

    def delete(self, x):
        """
        Delete x from the set.
        """
        if self.min == self.max:
            self.min = self.max = None
        elif self.min is None or self.max is None or x < self.min or x > self.max:
            pass
        else:
            if x == self.min:
                if self.summary is None:
                    self.min = self.max
                else:
                    hi = self.summary.min
                    lo = self.cluster[hi].min
                    x = self.min = self.index(hi, lo)
            hi = self.high(x)
            lo = self.low(x)
            self.cluster[hi].delete(lo)
            if self.cluster[hi].min is None:
                self.summary.delete(hi)
                if x == self.max:
                    if self.summary is None:
                        self.max = self.min
                    else:
                        hi = self.summary.max
                        lo = self.cluster[hi].max
                        self.max = self.index(hi, lo)
            elif x == self.max:
                hi = self.high(x)
                lo = self.cluster[hi].max
                self.max = self.index(hi, lo)

    def successor(self, x):
        """
        Find the successor of x in the set.
        """
        if self.max is not None and x < self.max:
            if self.min is None or x < self.min:
                return self.min
            else:
                hi = self.high(x)
                lo = self.low(x)
                if self.cluster[hi] is not None and self.cluster[hi].max is not None and self.cluster[hi].max > lo:
                    offset = self.cluster[hi].successor(lo)
                    return self.index(hi, offset)
                else:
                    succ_cluster = None
                    if self.summary is not None and self.summary.max is not None and hi < self.summary.max:
                        succ_cluster = self.summary.successor(hi)
                    else:
                        return None
                    if succ_cluster is None:
                        return None
                    else:
                        offset = self.cluster[succ_cluster].min
                        return self.index(succ_cluster, offset)
        else:
            return None

    def predecessor(self, x):
        """
        Find the predecessor of x in the set.
        """
        if self.min is not None and x > self.min:
            if self.max is None or x > self.max:
                return self.max
            else:
                hi = self.high(x)
                lo = self.low(x)
                if self.cluster[hi] is not None and self.cluster[hi].min is not None and self.cluster[hi].min < lo:
                    offset = self.cluster[hi].predecessor(lo)
                    return self.index(hi, offset)
                else:
                    pred_cluster = None
                    if self.summary is not None and self.summary.min is not None and hi > self.summary.min:
                        pred_cluster = self.summary.predecessor(hi)
                    else:
                        return None
                    if pred_cluster is None:
                        if self.min is not None and x > self.min:
                            return self.min
                        else:
                            return None
                    else:
                        offset = self.cluster[pred_cluster].max
                        return self.index(pred_cluster, offset)