C++: The realization principle of the jump table data structure

  The so-called jump list is to add an index layer on the basis of an ordered linked list , and an index layer can be added on the basis of the index layer, thereby improving the query efficiency of the linked list. In general, the efficiency of inserting and deleting can also be improved.

-----------------------------------------------------------------------

table of Contents

One, the data structure of the jump table

Second, rebuild the index

Three, determine the data node according to the location

Fourth, query the position of the element according to the element data information

Five, insert and delete


One, the data structure of the jump table

      The jump table is composed of an index layer linked list and a data layer linked list, and the data layer linked list is composed of a next pointer part and a data part. The index layer linked list consists of three parts: data part, index pointer part, and next pointer part, in which the value of the data part and the value of the node pointed to by the index pointer are consistent. The bottom index pointer points to the data layer linked list node, and the other layer index pointers point to the lower layer index linked list node.

template<class ElemType>
 class SkipList {
    public:
        class IndexStruct{
        public:
            ElemType position() const;
            void position(ElemType position);

            bool operator <(IndexStruct a);
            bool operator ==(IndexStruct a);
            bool operator >(IndexStruct a);
            IndexStruct& operator =(const IndexStruct & a);
            IndexStruct(ElemType position, const boost::shared_ptr<LinkList<ElemType>> &pointer);
            IndexStruct(){}
          
          public: 
            struct U{
                boost::shared_ptr<LinkList<IndexStruct>> indexPointer;
                boost::shared_ptr<LinkList<ElemType>> dataPointer;
            }pointer_;
            const U &pointer() const;
            void pointer(const U &pointer);
            ElemType position_;      //datalist的索引位

        };
        explicit SkipList(Integer skipstep = 2):skipstep_(skipstep+1){}

    public:
        int findIndexListPosition(int indexlevel,ElemType dataPos,boost::shared_ptr<LinkList<IndexStruct>>& idxlist);
        void rebuildIndex(ElemType startElem );
        int findPosByElem(ElemType elem);
        void removeByPos(Size pos);
        boost::shared_ptr<LinkList<ElemType>> findNodeByPos(Size pos);
        void removeByElem(ElemType e);
        void insertElem(ElemType e,bool isRebuildIndex = false);
        boost::shared_ptr<LinkList<ElemType>>findDataNode(ElemType elem,bool isAccurate = true);
        boost::shared_ptr<LinkList<IndexStruct>> findIndexNode(int indexlevel,ElemType dataPos);
        const std::vector<boost::shared_ptr<LinkList<IndexStruct>>> &indexLinklist() const{
            return indexLinklist_;
        };
        void indexLinklist(const std::vector<boost::shared_ptr<LinkList<IndexStruct>>> &indexLinklist){
            indexLinklist_=indexLinklist;
        };
        const boost::shared_ptr<LinkList<ElemType>> &dataLinklist() const{
            return  dataLinklist_;
        };
        void dataLinklist(const boost::shared_ptr<LinkList<ElemType>> &dataLinklist){
            dataLinklist_=dataLinklist;
            if (dataLinklist_ ->next){
                rebuildIndex(dataLinklist_->next->data);
            }else{
                indexLinklist_.clear();
            }
        };

    private:
        std::vector< boost::shared_ptr<LinkList<IndexStruct>>> indexLinklist_;//索引链表,数据是地址
        boost::shared_ptr<LinkList<ElemType>> dataLinklist_; //有序数据链表
        LinkListUtil<ElemType> dataListUtil_;
        LinkListUtil<IndexStruct> indexListUtil_;

        const Integer  skipstep_;
    };

Second, rebuild the index

       It is known that there is a data layer linked list dataLinkList with length n, then the number of indexes that need to be established for the level level is datalistsize /pow(skipstep_,level), and an index is established every skipstep data nodes until the level needs to be established If the number of nodes is 0, the index is no longer key. In this process, if the level is larger than the original index level, the index level needs to be expanded, otherwise the original index level is modified.

/**
 * <p>从第数据链表的startElem开始重建立链表
 * @tparam ElemType
 * @param startElem
 */
template<class ElemType>
void SmartDongLib::SkipList<ElemType>::rebuildIndex(ElemType startElem) {
    //获取数据总数
    int datalistsize = dataListUtil_.listLenth(dataLinklist_);
    //要重建数据索引的个数
//    int rebuldDataCount =  datalistsize - startIndex +1;
    //索引层应建立索引的节点数
    int indexlevelCount = datalistsize / skipstep_;
    int indexlevel=0;
    while (indexlevelCount !=0){
        //如果层级要大于 indexLinklist_.size(),需要扩充indexList,否则再原来的基础上修改,还需要判断是不是第0索引层
        if(indexlevel >= indexLinklist_.size()){
            boost::shared_ptr<LinkList<IndexStruct>> currentIndexList (new LinkList<IndexStruct>());
            //头指针也进行关联
            if (indexlevel ==0){
                currentIndexList->data.pointer_.dataPointer = dataLinklist_;
//                currentIndexList->data.position_ =dataLinklist_->data;
            }else{
                currentIndexList->data.pointer_.indexPointer = indexLinklist_[indexlevel-1];
//              currentIndexList->data.position_ =indexLinklist_[indexlevel-1]->data.position_;

            }
            bool  isfirst = true;
            boost::shared_ptr<LinkList<ElemType>> linkdataNode;
            boost::shared_ptr<LinkList<IndexStruct>>  linkindexNode;
            //扩展 indexlevel 层的后面的索引
            for (int i = 1; i <=indexlevelCount; ++i) {
//                boost::shared_ptr<LinkList<IndexStruct>> currentIndexNode (new LinkList<IndexStruct>);
                IndexStruct currentIndexNode;
                //第0索引层指向data数据,其他指向下层索引数据。优化:第一次从头节点确定指向的位置,之后再此基础上在+上skipstep_
                if (indexlevel == 0) {
                    if (isfirst){
                        linkdataNode = dataListUtil_.listGetNode(dataLinklist_,i  * skipstep_);
                        isfirst= false;
                    }else{
                        linkdataNode = dataListUtil_.listGetNode(linkdataNode, skipstep_);
                    }
                    currentIndexNode.position_ =linkdataNode->data;
                    currentIndexNode.pointer_.dataPointer = linkdataNode;
                }else{
                    if (isfirst){
                        linkindexNode =indexListUtil_.listGetNode(indexLinklist_[indexlevel - 1], i * skipstep_);
                        isfirst= false;
                    }else{
                        linkindexNode =indexListUtil_.listGetNode(linkindexNode,  skipstep_);
                    }
                    currentIndexNode.position_ =linkindexNode->data.position_;
                    currentIndexNode.pointer_.indexPointer = linkindexNode;
                }
                indexListUtil_.listOrderInsert(currentIndexList,currentIndexNode);
            }
            indexLinklist_.push_back(currentIndexList);
        } else{
            //如果在原来的索引层上进行修改,那么确认要修改的索引节点进行重建
            boost::shared_ptr<LinkList<IndexStruct>> currentIndexList=indexLinklist_[indexlevel];
            //找到startElem前一个元素的位置
            boost::shared_ptr<LinkList<IndexStruct>>  startIndexNode;
            int startIdx = findIndexListPosition(indexlevel, startElem,startIndexNode);
            //重键startIndexNode之后的索引
            startIndexNode->next = NULL;
            boost::shared_ptr<LinkList<ElemType>> linkdataNode;
            boost::shared_ptr<LinkList<IndexStruct>>  linkindexNode;
            bool  isfirst = true;
            //第indexlevel层从startIdx开始重建索引
            for (int i = startIdx+1; i <=indexlevelCount; ++i){
//                boost::shared_ptr<LinkList<IndexStruct>> currentIndexNode (new LinkList<IndexStruct>);
//                LinkList<IndexStruct> currentIndexNode;
                 IndexStruct  currentIndexNode;
                //优化:第0索引层指向data数据,其他指向下层索引数据,第一次从头节点确定指向的位置,之后再此基础上在+上skipstep_
                if (indexlevel == 0) {
                    if (isfirst){
                        linkdataNode = dataListUtil_.listGetNode(dataLinklist_,i  * skipstep_);
                        isfirst= false;
                    }else{
                        linkdataNode = dataListUtil_.listGetNode(linkdataNode, skipstep_);
                    }
                    currentIndexNode.position_ =linkdataNode->data;
                    currentIndexNode.pointer_.dataPointer = linkdataNode;
                }else{
                    if (isfirst){
                        linkindexNode =indexListUtil_.listGetNode(indexLinklist_[indexlevel - 1], i * skipstep_);
                        isfirst= false;
                    }else{
                        linkindexNode =indexListUtil_.listGetNode(linkindexNode,  skipstep_);
                    }
                    currentIndexNode.position_ =linkindexNode->data.position_;
                    currentIndexNode.pointer_.indexPointer = linkindexNode;
                }
                indexListUtil_.listOrderInsert(currentIndexList,currentIndexNode);
            }

        }
        indexlevel++;
        indexlevelCount /= skipstep_;
    }

}

Three, determine the data node according to the location

Move the data layer node number corresponding to next once in the level layer to increase the position of pow(skipstep_, currentIndexlevel).

/**
 * <p>获取节点(已优化)
 * @tparam ElemType
 * @param pos data的位置
 * @return 获取pos对应的元素节点
 */
template<class ElemType>
boost::shared_ptr<SmartDongLib::LinkList<ElemType>> SmartDongLib::SkipList<ElemType>::findNodeByPos(Size pos) {
    int indexlistsize = indexLinklist_.size();
    int currentIndexlevel = indexlistsize-1;
    boost::shared_ptr<LinkList<IndexStruct>> currentIndexNode  = indexLinklist_[currentIndexlevel];
    int currentPos = 0;
    int posIncrement =1;
    boost::shared_ptr<LinkList<ElemType>> ret  = dataLinklist_;
    while(currentPos  <= pos && currentIndexlevel >=0){
        posIncrement = std::pow(skipstep_,currentIndexlevel + 1);
        if ( currentIndexNode->next!=NULL  && currentPos + posIncrement <=pos ){
            //如果查在后面
            currentIndexNode=currentIndexNode->next;
            currentPos +=posIncrement;
        }else{
            //如果当前层确定了位置,就下一层直到第indexlevel结束
            if (  currentIndexlevel == 0 ){
                ret = currentIndexNode->data.pointer_.dataPointer;
                currentIndexlevel --;
                break;
            }else{
                currentIndexNode  = currentIndexNode->data.pointer_.indexPointer;
                currentIndexlevel --;
            }
        }
    }
    while (pos - currentPos >0 && currentIndexlevel<0){
        ret = ret->next;
        currentPos ++ ;
    }
    return ret;
}

Fourth, query the position of the element according to the element data information

/**
 * <p>根据元素寻找在datalinklist中的位置(已优化)
 * @tparam ElemType
 * @param elem
 * @return 位找到是-1 ,头节点是第0个位置
 */
template<class ElemType>
int SmartDongLib::SkipList<ElemType>::findPosByElem(ElemType elem) {
    int indexlistsize = indexLinklist_.size();
    int currentIndexlevel = indexlistsize-1;
    boost::shared_ptr<LinkList<IndexStruct>> idxlist=indexLinklist_[currentIndexlevel];
    int pos = 0;
    while (currentIndexlevel >= 0){
        if ( idxlist->next  && idxlist->next->data.position() <= elem ){
            //如果查在后面
            idxlist=idxlist->next;
            pos =pos + std::pow(skipstep_,currentIndexlevel +1 );
        }else{
            //如果当前层确定了位置,就下一层直到第indexlevel结束
            if ( currentIndexlevel == 0 ){
                break;
            }else{
                idxlist  = idxlist->data.pointer_.indexPointer;
                currentIndexlevel --;
            }
        }
    }
    boost::shared_ptr<LinkList<ElemType>> dataNode = idxlist->data.pointer_.dataPointer;
    if (dataNode ->data == elem){
        return pos;
    } else{
        int rslt =dataListUtil_.listGetIndex(dataNode,elem);
        if (rslt == -1 )
            return  -1;
        else
            return  pos + dataListUtil_.listGetIndex(dataNode,elem);
    }
}

Five, insert and delete

       After querying the position of the node to be inserted, insert and delete the ordinary ordered linked list.

Guess you like

Origin blog.csdn.net/superSmart_Dong/article/details/111876680