C ++ : 점프 테이블 데이터 구조의 실현 원리

  이른바 점프 리스트정렬 된 링크리스트를 기반으로 인덱스 레이어를 추가하는 것으로, 인덱스 레이어를 기반으로 인덱스 레이어를 추가 할 수있어 링크드리스트의 질의 효율을 높일 수있다. 삽입 및 삭제의 효율성도 향상 될 수 있습니다.

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

목차

하나, 점프 테이블의 데이터 구조

둘째, 인덱스를 다시 작성하십시오.

셋, 위치에 따라 데이터 노드 결정

넷째, 요소 데이터 정보에 따라 요소의 위치를 ​​쿼리합니다.

다섯, 삽입 및 삭제


하나, 점프 테이블의 데이터 구조

      점프 테이블은 인덱스 레이어 연결 목록과 데이터 레이어 연결 목록으로 구성되며 데이터 레이어 연결 목록은 다음 포인터 부분과 데이터 부분으로 구성됩니다. 인덱스 레이어 연결 목록은 데이터 부분, 인덱스 포인터 부분, 다음 포인터 부분의 세 부분으로 구성되며 데이터 부분의 값은 인덱스 포인터가 가리키는 노드의 값과 일치합니다. 하단 인덱스 포인터는 데이터 레이어 연결 목록 노드를 가리키고 다른 레이어 인덱스 포인터는 하위 레이어 인덱스 연결 목록 노드를 가리 킵니다.

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_;
    };

둘째, 인덱스를 다시 작성하십시오.

       길이가 n 인 데이터 레이어 링크드리스트 dataLinkList가있는 것으로 알려져 있으며, 레벨 레벨에 대해 설정해야하는 인덱스의 수는 datalistsize / pow (skipstep_, level)이며, 다음까지 모든 스킵 스텝 데이터 노드마다 인덱스가 설정됩니다. 레벨을 설정해야합니다. 노드 수가 0이면 인덱스는 더 이상 키가 아닙니다. 이 과정에서 레벨이 원래 인덱스 레벨보다 크면 인덱스 레벨을 확장해야합니다. 그렇지 않으면 원래 인덱스 레벨이 수정됩니다.

/**
 * <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_;
    }

}

셋, 위치에 따라 데이터 노드 결정

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;
}

넷째, 요소 데이터 정보에 따라 요소의 위치를 ​​쿼리합니다.

/**
 * <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);
    }
}

다섯, 삽입 및 삭제

       삽입 할 노드의 위치를 ​​조회 한 후 일반 정렬 된 연결 목록을 삽입 및 삭제합니다.

추천

출처blog.csdn.net/superSmart_Dong/article/details/111876680