【问题标题】:Doubly Linked list with Skip List to insert in sorted way带有跳过列表的双向链接列表以排序方式插入
【发布时间】:2015-04-15 05:16:41
【问题描述】:

我在互联网上阅读了有关跳过列表的信息,我刚刚了解了它如何与不同的数据结构和所有内容一起工作。但我真的想用双向链表实现跳过列表,因为我想在插入时对双向链表进行排序。表示当元素插入时,它应该仅以排序方式插入。

这里我实现了以排序方式在双向链表中插入数据的方法,但是当元素数量非常大时,插入数据并以排序方式制作列表需要很长时间。

请告诉我如何在现有函数中添加跳过列表算法,或者我必须重新重写整个内容?任何有关实施的帮助将不胜感激

代码如下:

void DoubleList::addSorted(int value)
{
    IDoubleNode * tempNode = new DoubleNode();
    tempNode->setValue(value);
    // if double link list is empty 
    if(getHead() == NULL)
    {
        // temp node already has NULL value in next and prev.
        setHead(tempNode);
        setTail(tempNode);
    }
    else if(value <= getHead()->getValue())
    {
        tempNode->setNext(getHead());// set tempnode next as current head.
        tempNode->setPrev(getHead()->getPrev()); // set previous
        getHead()->setPrev(tempNode); // set previous pointer of head to tempnode which we just inserted
        setHead(tempNode); // set head
        getHead()->setPrev(NULL);// for safer side. we already done this.
    }
    else
    {
        int found = 0;
        IDoubleNode *currNode = getHead();
        while(currNode->getNext() != NULL && found == 0)
        {
            if(currNode->getNext()->getValue() > tempNode->getValue())
            {
                found = 1;
            }
            else
            {
                currNode = currNode->getNext();
            }
        }
        if(found)
        {
            tempNode->setNext(currNode->getNext());
            currNode->getNext()->setPrev(tempNode);
            currNode->setNext(tempNode);
            tempNode->setPrev(currNode);
        }
        else
        {
            currNode->setNext(tempNode);
            tempNode->setPrev(currNode);
            tempNode->setNext(NULL);
            setTail(tempNode);
        }
    }
}

【问题讨论】:

    标签: c++ list sorting linked-list skip-lists


    【解决方案1】:

    skiplist 的美妙之处在于它对数据项进行排序,并且还提供了 o(log n) 的插入和删除时间复杂度。为了使它更容易理解,假设您的链表有捷径或锚点,这样您就不必遍历整个列表来找到插入项目的位置。您只需跟随锚点,因此它是一个具有快速访问锚点的双链表。

    至于实现,如果你不打算使用skip-list进行多线程访问,那么实现就变得微不足道了。没有理由将skip-list与双链表结合起来,但是你可以将skiplist实现为双链表

    看看 http://www.sanfoundry.com/cpp-program-implement-skip-list/

    【讨论】:

    • 感谢您的回复。我想在双向链表中设置每个节点的 prev 会有问题。我们如何在跳过列表中管理那件事
    • 在跳过列表中有 prev 指针的动机是什么?
    • 我正在实现双向链表,所以它应该有 prev 指针,因为我的单元测试也会检查它的反向顺序。正确与否。
    • 您可以查看这个带有反向指针的跳过列表示例实现。 coderslexicon.com/…希望它可以提供帮助,它不会增加太多复杂性,但是您将不得不在每次删除或插入节点时处理更多的指针。
    【解决方案2】:

    希望对你有帮助。

    #ifndef SkipList_h
    #define SkipList_h
    ///////////////////////////////////////////////////////////////////////////////
    
    template<typename K, typename V, int MAXLEVEL>
    class SkipListNode
    {
    
    public:
        SkipListNode()
        {
            for(int i=1; i<=MAXLEVEL;i++){
                next[i] = nullptr;
                prev[i] = nullptr;
            }
        }
    
        SkipListNode(K searchKey):key(searchKey)
        {
            for(int i=1; i<=MAXLEVEL;i++){
                next[i] = nullptr;
                prev[i] = nullptr;
            }
        }
    
        SkipListNode(K searchKey, V val):key(searchKey),value(val)
        {
            for(int i=1; i<=MAXLEVEL;i++){
                next[i] = nullptr;
                prev[i] = nullptr;
            }
        }
    
        // custom memory management
       // static void * operator new(size_t size);
    
      //  static void operator delete( void *deadObject, size_t size );
    
    
        K key;
        V value;
        SkipListNode<K, V, MAXLEVEL>* next[MAXLEVEL+1];
        SkipListNode<K, V, MAXLEVEL>* prev[MAXLEVEL+1];
    private:
       // static MemoryPool<SkipListNode> memPool; // memory pool for SkipListNode
    };
    
    // template<typename K, typename V, int MAXLEVEL>
    // MemoryPool< SkipListNode<K, V, MAXLEVEL> > SkipListNode<K, V, MAXLEVEL>::memPool;
    
    // template<typename K, typename V, int MAXLEVEL>
    // inline void * SkipListNode<K, V, MAXLEVEL>::operator new ( size_t size )
    // {
    //     return memPool.allocate();
    // }
    
    // template<typename K, typename V, int MAXLEVEL>
    // inline void SkipListNode<K, V, MAXLEVEL>::operator delete( void *p, size_t size )
     //{
     //    memPool.deallocate( static_cast<SkipListNode<K, V, MAXLEVEL> *>(p) );
     //}
    
    
    ///////////////////////////////////////////////////////////////////////////////
    
    template<typename K, typename V, int MAXLEVEL = 16>
    class SkipList
    {
    public:
        typedef K keyType;
        typedef V ValueType;
        typedef SkipListNode<K, V, MAXLEVEL> NodeType;
        const int maxLevel;
    
        SkipList(K min_key, K max_key)
                                    :pHeader(nullptr), pTail(nullptr),
                                    maxCurrLevel(1), maxLevel(MAXLEVEL),
                                    minKey(min_key), maxKey(max_key)
        {
            pHeader = new NodeType(minKey);
            pTail = new NodeType(maxKey);
    
            for( int i = 1; i<=MAXLEVEL; i++){
                pHeader->next[i] = pTail;
                pTail->prev[i] = pHeader;
            }
        }
    
        virtual ~SkipList()
        {
    
            delete pHeader;
            delete pTail;
        }
    
        void removeAll()
        {
            NodeType* curNode = pHeader->next[1];
            while(curNode != pTail){
                NodeType* temp = curNode;
                curNode = curNode->next[1];
                delete temp;
            }
        }
    
        std::string printList()
        {
            std::stringstream sstr;
            NodeType* currNode = pHeader->next[1];
            while ( currNode != pTail ) {
                sstr << "(" << currNode->key << "," << currNode->value << ")" << std::endl;
                currNode = currNode->next[1];
            }
            return sstr.str();
        }
    
        NodeType* insert( K searchKey, V newValue );
    
        void removeKey( K searchKey );
        void removeKey( NodeType* curNode );
    
        NodeType* search(const K& key, NodeType** prev   );
    
    private:
        K minKey;
        K maxKey;
        int maxCurrLevel;
        SkipListNode<K, V, MAXLEVEL>* pHeader;
        SkipListNode<K, V, MAXLEVEL>* pTail;
    
        double uniformRandom()
        {
            return rand() / double(RAND_MAX);
        }
    
        int randomLevel() {
            int level = 1;
            double p = 0.5;
            while ( uniformRandom() < p && level < MAXLEVEL ) {
                level++;
            }
            return level;
        }
    };
    
    template<typename K, typename V, int MAXLEVEL>
    typename SkipList<K, V, MAXLEVEL>::NodeType* SkipList<K, V, MAXLEVEL>::search(const K& searchKey, NodeType** prev )
    {
        NodeType* currNode = nullptr;
    
        currNode = pHeader;
        for (int level=maxCurrLevel; level>=1; level--) {
            // Start our search at previous level's predecessor
    
            while (currNode->next[level]->key < searchKey) {
                currNode = currNode->next[level];
    
            }
            if ( prev != nullptr) {
                prev[level] = currNode;
            }
    
            //currNode = currNode->next[level];
            /*
            if ( next != nullptr) {
                next[level] = currNode;
            }*/
        }
    
        currNode = currNode->next[1];
        return currNode;
    }
    
    template<typename K, typename V, int MAXLEVEL>
    typename SkipList<K, V, MAXLEVEL>::NodeType*  SkipList<K, V, MAXLEVEL>::insert( K searchKey, V newValue )
    {
        SkipListNode<K, V, MAXLEVEL>** next = nullptr;
        SkipListNode<K, V, MAXLEVEL>* prev[MAXLEVEL];
    
        auto foundNode = search(searchKey, prev);
    
    
        int newLevel = randomLevel();
        //std::cout<< "Level: "<<newLevel<< std::endl;
    
        if ( newLevel > maxCurrLevel ) {
            for ( int level = maxCurrLevel+1; level <= newLevel; level++ ) {
                prev[level] = pHeader;
            }
    
            maxCurrLevel = newLevel;
        }
    
        NodeType* curNode = new NodeType(searchKey, newValue);
    
        for ( int level = 1; level<=maxCurrLevel; level++ ) {
            curNode->next[level] = prev[level]->next[level];
            curNode->prev[level] = prev[level];
            prev[level]->next[level]->prev[level] = curNode;
            prev[level]->next[level] = curNode;
        }
        return curNode;
    }
    
    template<typename K, typename V, int MAXLEVEL>
    void SkipList<K, V, MAXLEVEL>::removeKey( K searchKey)
    {
    
        SkipListNode<K, V, MAXLEVEL>** prev1 = nullptr;
    
        auto curNode = search(searchKey, prev1);
    
    
        //std::cout<<curNode <<" -> "<< curNode->key<< std::endl;
        if ( curNode && curNode->key == searchKey ) {
    
            auto prev = curNode->prev;
    
            for ( int level = 1; level<=maxCurrLevel; level++ ) {
    
                if ( prev[level]->next[level] != curNode ) {
                    break;
                }
    
                prev[level]->next[level] = curNode->next[level];
                curNode->next[level]->prev[level] = prev[level];
            }
    
            delete curNode;
    
            while ( maxCurrLevel > 1 && pHeader->next[maxCurrLevel] == pTail) {
                maxCurrLevel--;
            }
    
            //std::cout << "maxCurrLevel: "<<maxCurrLevel<<std::endl;
        }
    
    }
    
    
    template<typename K, typename V, int MAXLEVEL>
    void SkipList<K, V, MAXLEVEL>::removeKey( typename SkipList<K, V, MAXLEVEL>::NodeType* curNode )
    {
        if ( curNode && curNode == curNode->next[1]->prev[1] && curNode == curNode->prev[1]->next[1] ) {
           // std::cout<<curNode <<" -> "<< curNode->key<< std::endl;
    
            auto prev = curNode->prev;
    
            for ( int level = 1; level<=maxCurrLevel; level++ ) {
    
                if ( prev[level]->next[level] != curNode ) {
                    break;
                }
    
                prev[level]->next[level] = curNode->next[level];
                curNode->next[level]->prev[level] = prev[level];
            }
    
            delete curNode;
    
            while ( maxCurrLevel > 1 && pHeader->next[maxCurrLevel] == pTail ) {
                maxCurrLevel--;
            }
        }
    }
    
    
    #endif
    

    【讨论】:

      猜你喜欢
      • 2019-12-05
      • 2018-11-04
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 2018-12-25
      • 1970-01-01
      相关资源
      最近更新 更多