【问题标题】:Algorithm: Insertion in skip list算法:在跳过列表中插入
【发布时间】:2016-10-16 18:45:50
【问题描述】:

跳过列表的插入算法是怎样的?

在 google 上搜索时,通常会弹出 this 之类的内容,但奇怪的是,我似乎在我的书或互联网上找不到任何有用的东西。

我唯一能找到的是关于跳过列表如何工作的解释。

【问题讨论】:

    标签: algorithm computation-theory skip-lists


    【解决方案1】:

    首先,我们需要为新元素找到一个位置(我称之为键)。

    我们这样做:

    1. 让我们从最高级别开始,看看链接将我们引向何方。如果它导致列表的末尾或大于键的数字,我们需要向下一层。否则,我们点击此链接并针对此链接引导我们到达的节点重复该过程。

    2. 每次我们无法跳转时,级别都会降低,并且每次可以跳转时列表中的位置都会增加,因此在有限数量的步骤后,我们将达到级别零和一个从数字开始的链接那个小于一个key的那个数字就是大于那个key的。这正是应该插入密钥的位置。

    现在是时候插入它了。

    1. 让我们随机生成新节点的“高度”。

    2. 当我们在搜索过程中遍历列表时,我们可以保留一个数组来存储每个给定高度的最右边的链接。

    3. 对于从 0 到“高度”的每个级别,我们创建一个从该节点到最右边链接指向的节点的链接,并将最右边的链接重定向到新创建的节点。

    我没有提到如何处理相等的元素。我们既可以插入密钥(如果我们想存储重复项),也可以忽略它。

    下面是插入函数的伪代码:

    class Node {
        // an array of links for levels from 0 to the height of this node
        Node[] next; 
        int key; 
    
        Node(int height, int key) {
            key = key;
            next = new Node[height + 1];
        }
    }
    
    // I assume that the list always has two nodes: head and tail, which do not
    // hold any values
    
    void insert(int newKey) {
        // The rightmost node for each level such that the node itself has a key 
        // less than newKey but the node which the link points to has a larger key. 
        rightMostForLevel = new Node[maxLevel + 1]
        fill(leftMostForLevel, head)
        curLevel = maxLevel
        curNode = head
        // We need to find a node with the largest key such that its key is less
        // than or equal to the newKey, but the next node in the list is either 
        // equal to the tail or a has a greater key. 
        // We are done when the level is equal to zero and the next node has 
        // a key greater than newKey.
        while (curLevel != 0 
                or (curNode.next[curLevel] != tail and curNode.next[curLevel] <= key)) {
            if (curNode.next[curLevel] == tail or curNode.next[curLevel].key > key) {
                // We cannot make the jump (its too "long")
                // So we go one level lower
                curLevel--
            } else {
                // Otherwise, we make the jump
                curNode = curNode.next[curLevel]
                // And update the rightmost node for the current level
                rightMostForLevel[curLevel] = curNode
            }
        }  
        // Now we know where the new node should be inserted 
        newHeight = random height
        newNode = new Node(newHeight, newKey)
        // All we need to do is to update the links
        for (level = 0; level <= newHeight; level++) {
            // We "cut" the links that go through the new node
            newNode.next[level] = rightMostForLevel[level].next[level] 
            rightMostForLevel[level].next[level] = newNode  
        }
    }
    

    【讨论】:

    • 你知道伪代码在跳过列表中的插入是什么样的吗?
    • @Labbiqa 我已经添加了伪代码并更正了算法的描述(唯一的变化是最左边实际上是最右边)。
    猜你喜欢
    • 2014-12-03
    • 1970-01-01
    • 2016-07-30
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-17
    相关资源
    最近更新 更多