码迷,mamicode.com
首页 > 其他好文 > 详细

跳转表

时间:2018-09-10 17:54:22      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:lis   skiplist   plist   实施   oid   cti   name   --   修改   

Dictionary.hpp

#ifndef Dictionary_hpp
#define Dictionary_hpp

#define N_CHAR (0x80 - 0x20)  //只考虑可打印字符

//词典Dictionary模版类
template <typename K,typename V> struct Dictionary {
public:
    virtual int size() const = 0;  //当前词条总数
    virtual bool put(K,V) = 0;  //插入词条(禁止雷同词条时可能失败)
    virtual V* get(K k) = 0;  //读取词条
    virtual bool remove(K k) = 0; //删除词条
};


#endif /* Dictionary_hpp */

QuadlistNode.hpp

#ifndef QuadlistNode_hpp
#define QuadlistNode_hpp


#include <iostream>

#define QlistNodePosi(T) QuadlistNode<T>*   //跳转表节点位置


template <typename T> struct QuadlistNode {
    T entry; //所存词条
    QlistNodePosi(T) pred;  //前驱
    QlistNodePosi(T) succ;  //后继
    QlistNodePosi(T) above;  //上邻
    QlistNodePosi(T) below;  //下邻
    
    QuadlistNode(T e = T(),QlistNodePosi(T) p = NULL,QlistNodePosi(T) s = NULL,QlistNodePosi(T) a = NULL,QlistNodePosi(T) b = NULL)
    : entry(e),pred(p),succ(s),above(a),below(b) {}
    
    QlistNodePosi(T) insertAsSuccAbove(T const& e,QlistNodePosi(T) b = NULL); //插入新节点,以当前节点为前驱,以节点b为下邻
    
};

template <typename T> QlistNodePosi(T) QuadlistNode<T>::insertAsSuccAbove(const T &e,QlistNodePosi(T) b ) {
    QlistNodePosi(T) x = new QuadlistNode<T>(e, this, succ, NULL, b);
    succ->pred = x;
    succ = x;    //设置水平逆向链接
    if (b) {
        b -> above = x;   //设置垂直逆向链接
    }
    
    return x; //返回新节点的位置
}

#endif /* QuadlistNode_hpp */

 Quadlist.hpp

#ifndef Quadlist_hpp
#define Quadlist_hpp

#include "QuadlistNode.hpp"
#include "ListNode.hpp"

template <typename T> class Quadlist {
private:
    //规模,头哨兵,尾哨兵
    int _size;
    QlistNodePosi(T) header;
    QlistNodePosi(T) trailer;
    
protected:
    void init();
    int clear();
    
public:
    Quadlist() {
        init();
    }
    
    ~Quadlist() {
        clear();
        delete header;
        delete trailer;
    }
    
    //只读访问接口
    Rank size() const {
        return _size;
    }
    
    bool empty() const {
        return _size <= 0;
    }
    
    QlistNodePosi(T) first() {
        return header -> succ;
    }
    
    QlistNodePosi(T) last() {
        return trailer -> pred;
    }
    
    bool valid(QlistNodePosi(T) p) {
        return p && (trailer != p) && (header != p);
    }
    
    //可写访问接口
    T remove(QlistNodePosi(T) p); //删除(合法)位置p处的节点,返回被删除节点的数值
    QlistNodePosi(T) insertAfterAbove(T const& e,QlistNodePosi(T) p,QlistNodePosi(T) b = NULL);
    
    //遍历
    void traverse(void (*)(T&)); //遍历各节点,一次实施指定操作(函数指针,只读或局部修改)
    template <typename VST> void traverse(VST&); //操作器
    
};


template <typename T> void Quadlist<T>::init() {
    header = new QuadlistNode<T>;
    trailer = new QuadlistNode<T>;
    header->succ = trailer;
    header->pred = NULL;
    
    trailer->pred = header;
    trailer->succ = NULL;
    
    header->above = trailer->above = NULL;
    header->below = trailer->below = NULL;
    
    _size = 0;
}

template <typename T> QlistNodePosi(T) Quadlist<T>::insertAfterAbove(const T &e, QlistNodePosi(T) p,QlistNodePosi(T) b) {
    _size++;
    return p -> insertAsSuccAbove(e, b);
}

template <typename T> T Quadlist<T>::remove(QlistNodePosi(T) p) {
    //assert: p为Quadlist中的合法位置
    p -> pred -> succ = p -> succ;
    p -> succ -> pred = p -> pred;
    _size--;
    
    T e = p -> entry;
    delete p;  //备份词条,释放节点
    return e; //返回词条
}

template <typename T> int Quadlist<T>::clear() {
    //清空Quadlist
    int oldSize = _size;
    while (0 < _size) {
        remove(header -> succ);  //逐个删除所有节点
    }
    
    return oldSize;
}

#endif /* Quadlist_hpp */

 

 

 

Skiplist.hpp

#ifndef Skiplist_hpp
#define Skiplist_hpp


#include "Quadlist.hpp"
#include "Dictionary.hpp"
#include "Entry.hpp"
#include "List.hpp"


//跳转表
template <typename K,typename V> class Skiplist : public Dictionary<K, V>, public List<Quadlist<Entry<K,V>> *> {
protected:
    bool skipSearch(ListNode<Quadlist<Entry<K,V>>* > *qlist, QuadlistNode<Entry<K,V>> * &p,K& k);
    
public:

    int size() const {
        return this->empty() ? 0 : this->last()->data->size(); //底层Quadlist的规模
    }
    int level() {
        return List<Quadlist<Entry<K,V>> *>::size();  //层高==#Quadlist,不一定要开放
    }
    bool put(K,V); //插入(注意与map有区别----Skiplist允许词条重复,故必然成功)
    V* get(K k); //读取
    bool remove(K k); //删除
    
    Skiplist() {}
    
    
};


template <typename K,typename V> V* Skiplist<K,V>::get(K k) {
    if (this->empty()) {
        return NULL;
    }
    
    ListNode<Quadlist<Entry<K, V>> *> *qlist = this->first();
    QuadlistNode<Entry<K, V>> *p = qlist->data->first(); //首节点开始
    return skipSearch(qlist, p, k) ? &(p -> entry.value) : NULL;
}

template <typename K,typename V> bool Skiplist<K,V>::skipSearch(ListNode<Quadlist<Entry<K, V> > *> *qlist, QuadlistNode<Entry<K, V> > *&p, K &k) {
    //从指定层qlist的首节点p出发,向右,向下查找目标关键码k
    while (true) { //在每一层
        while (p->succ && (p->entry.key <= k)) { //从前向后查找
            p = p->succ; //知道出现更大的key或溢出至trailer
        }
        
        p = p -> pred; //此时倒回一步,即可判断是否命中,否则转入下一层
        if (p -> pred && (k == p->entry.key)) {
            return true;
        }
        
        qlist = qlist -> succ;
        if (!qlist -> succ) {
            return false;  //若已到穿透底层,则意味着失败
        }
        
        p = (p -> pred) ? p -> below : qlist -> data -> first(); //否则转至当前塔的下一节点
    }
}

template <typename K,typename V> bool Skiplist<K,V>::put(K k, V v) {
    Entry<K, V> e = Entry<K, V>(k, v); //待插入的词条(将被随机的插入多个副本)
    if (this->empty()) {
        this->insertAsFirst(new Quadlist<Entry<K, V>>); //插入首个Entry
    }
    
    ListNode<Quadlist<Entry<K, V>> *> *qlist = this->first(); //从顶层四联表的首节点出发
    QuadlistNode<Entry<K, V>> *p = qlist->data->first();
    
    if (skipSearch(qlist, p, k)) {
        while (p->below) { //查找适当的插入位置(不大于关键码k的最后一个节点p)
            p = p -> below; //若已有雷同词条,则需强制转至塔底
        }
    }
    
    qlist = this->last(); //以下,紧邻与p的右侧,一座新塔将自底而上逐层生长
    
    QuadlistNode<Entry<K, V>> *b = qlist->data->insertAfterAbove(e, p);
    
    while (rand() & 1) {  //经投掷硬币,若确定新塔需要在长高一层,则找出不低于此高度的最近前驱
        while (qlist->data->valid(p) && !p->above) {
            p = p -> pred;
        }
        
        if (!qlist->data->valid(p)) {
            //若该前驱是header
            if (qlist == this->first()) {
                //且当前已是最顶层,则意味着必须首先创建新的一层,然后将p转至上一层Skiplist的header
                this->insertAsFirst(new Quadlist<Entry<K, V>>);
            }
            
            p = qlist->pred->data->first()->pred;
        }else{
            //否则可径自 将p提高至该高度
            p = p -> above;
        }
        
        qlist = qlist -> pred;  //上升一层,并在该层
        b = qlist ->data->insertAfterAbove(e, p, b); //将新节点插入p之后、b之上
    }
    
    return true;
    
}

//跳转表词条删除算法
template <typename K,typename V> bool Skiplist<K,V>::remove(K k) {
    if (this->empty()) {
        return false; //空表情况
    }
    
    ListNode<Quadlist<Entry<K, V>> *> *qlist = this->first();
    QuadlistNode<Entry<K, V>> *p = qlist->data->first();
    
    if (!skipSearch(qlist, p, k)) {
        return false;  //目标词条不存在,直接返回
    }
    
    do{
        //若目标词条不存在,则逐层拆除与之对应的塔
        QuadlistNode<Entry<K, V>> *lower = p->below;
        qlist->data->remove(p);
        p = lower;            //删除当前层节点,再
        qlist = qlist -> succ;  //转入下一层
        
    }while(qlist->succ);
    
    while (!this->empty() && this->first()->data->empty()) {
        //逐一的清除已可能不含词条的顶层Quadlist
        List<Quadlist<Entry<K,V>> *>::remove(this->first());
    }
    
    return true;  //删除操作成功完成
}

#endif /* Skiplist_hpp */

 

跳转表

标签:lis   skiplist   plist   实施   oid   cti   name   --   修改   

原文地址:https://www.cnblogs.com/gkp307/p/9621114.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!