• 跳表


    性质

    1. 由很多层结构组成
    2. 每一层都是一个有序的链表
    3. 最底层(Level 1)的链表包含所有元素
    4. 如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现。
    5. 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

    查找

    1. 比较 21, 比 21 大,往后面找
    2. 比较 37,   比 37大,比链表最大值小,从 37 的下面一层开始找
    3. 比较 71,  比 71 大,比链表最大值小,从 71 的下面一层开始找
    4. 比较 85, 比 85 大,从后面找
    5. 比较 117, 等于 117, 找到了节点。

    插入

      先确定该元素要占据的层数 K(采用丢硬币的方式,这完全是随机的)然后在 Level 1 ... Level K 各个层的链表都插入元素。例子:插入 119, K = 2

      如果 K 大于链表的层数,则要添加新的层。例子:插入 119, K = 4

    跳表的高度

      n 个元素的跳表,每个元素插入的时候都要做一次实验,用来决定元素占据的层数 K,跳表的高度等于这 n 次实验中产生的最大 K,待续。。。

    跳表的空间复杂度分析

      根据上面的分析,每个元素的期望高度为 2, 一个大小为 n 的跳表,其节点数目的,期望值是 2n。

    跳表的删除

      在各个层中找到包含 x 的节点,使用标准的 delete from list 方法删除该节点。例子:删除 71

    code

    skiplist.h

    #ifndef SKIPLIST_H_INCLUDED
    #define SKIPLIST_H_INCLUDED
    
    #include <cstdlib>
    #include <ctime>
    #include "entry.h"
    
    using namespace std;
    
    //跳表结构
    template <typename T>
    class SkipList
    {
    private:
        typedef struct Entry_H//跳表头结点
        {
            Entry_H *up;
            Entry_H *down;
            Entry<T> *right;
            Entry_H()
            {
                up=nullptr;
                down=nullptr;
                right=nullptr;
            }
        }Entry_H;
    
        Entry_H *head;
        int level;
    
        unsigned int seed;
        bool random();
    public:
        SkipList():level(1),seed(time(NULL))//初始化为1层
        {
            head=new Entry_H();
        }
        void inserts(Entry<T> *e);
        bool searchs(Entry<T> *e) const;
        void removes(Entry<T> *e);
    };
    //SkipList的函数
    template <typename T>
    bool SkipList<T>::random()
    {
        srand(seed);
        int res=rand()%2;
        seed=rand();
        return res==0?true:false;
    }
    
    template <typename T>
    extern void SkipList<T>::inserts(Entry<T>* e)
    {
        //先找到第一层:L1
        Entry_H *cur_head=head;
        while(cur_head->down!=nullptr)
            cur_head=cur_head->down;
    
        //L1层肯定要插入数据,上面是否插入数据根据random决定
        int cur_level=0;
        Entry<T> *temp_entry=nullptr;//保存一个已完成插入的结点
        Entry<T> *cur_entry=new Entry<T>(*e);//拷贝要复制的对象
        do
        {
            //层数超过了表中的最大层,创建新的头结点
            ++cur_level;
            if(level<cur_level)
            {
                ++level;
                Entry_H *new_head=new Entry_H();
                new_head->down=cur_head;
                cur_head->up=new_head;
                head=new_head;
            }
    
            if(cur_level>1)//层数大于1,向上依次添加
            {
                cur_head=cur_head->up;
                cur_entry->down()=temp_entry;
            }
    
            temp_entry=cur_entry;
            //添加对象
            if(cur_head->right==nullptr)
            {
                cur_head->right=cur_entry;
                break;
            }
            else//一个简单的在单链表中的插入操作
            {
                Entry<T> *cursor=cur_head->right;//指向当前结点的指针
                Entry<T> *pre=cur_head->right;//指向当前节点的前一节点的指针
    
                //如果要插入的结点小于第一个结点---同一层的结点升序排列
                if(*cur_entry<*cursor)
                {
                    cur_entry->next()=cursor;
                    cur_head->right=cur_entry;
                }
                else
                {
                    bool flag=true;
                    cursor=cursor->next();
                    while(cursor!=nullptr)
                    {
                        if(*cur_entry<*cursor)
                        {
                            cur_entry->next()=cursor;
                            pre->next()=cur_entry;
                            flag=false;
                            break;
                        }
                        cursor=cursor->next();
                        pre=pre->next();
                    }
                    if(flag)//记录是由什么原因跳出while循环
                        cursor->next()=cur_entry;
                }
            }
        }
        while(random());
        delete cur_entry;
    }
    
    template <typename T>
    extern bool SkipList<T>::searchs(Entry<T>* e) const
    {
        if(head==nullptr)
            return false;
    
        Entry_H *cur_head=head;
        for(int i=0; i<level; ++i) //先找一个接入点
        {
            if(*e<*cur_head->right)
                cur_head=cur_head->down;
            else
            {
                Entry<T> *cursor=cur_head->right;
                while(cursor->down()!=nullptr)
                {
                    while(cursor->next()!=nullptr)
                    {
                        if(*e<=cursor->next())
                            break;
                        cursor=cursor->next();
                    }
                    cursor=cursor->down();
                }
                while(cursor!=nullptr)
                {
                    if(*e<*cursor)
                        cursor=cursor->next();
                    else if(*e==*cursor)
                        return true;
                }
                return false;
            }
        }
        return false;//找不到接入点
    }
    template <typename T>
    extern void SkipList<T>::removes(Entry<T>* e)
    {
        if(head->right==nullptr)
            return;
    
        Entry_H *cur_head=head;
        int cur_level=level;
    
        for(int i=0; i<level; ++i)
        {
            if(*e==*cur_head->right)
            {
                Entry<T> *t=cur_head->right;
                cur_head->right=cur_head->right->next();
                delete t;
                //   break;
            }
            else
            {
                Entry<T> *cursor=cur_head->right;
                while(cursor)
                {
                    if(*e==*cursor)
                    {
                        Entry<T> *t=cursor;
                        cursor=cursor->next();
                        delete t;
                        break;
                    }
                    cursor=cursor->next();
                }
            }
    
            if(cur_head->right==nullptr)
            {
                Entry_H *t=head;
                cur_head=cur_head->down;
                head=cur_head;
                delete t;
                --level;
            }
            else
                cur_head=cur_head->down;
    
        }
    }
    #endif // SKIPLIST_H_INCLUDED

    entry.h

    #ifndef ENTRY_H_INCLUDED
    #define ENTRY_H_INCLUDED
    
    template <typename T>
    class Entry//结点类型
    {
    private:
        int key;
        T value;
        Entry *Next;
        Entry *Down;
    public:
        Entry(int k,T v):key(k),value(v),Next(nullptr),Down(nullptr){}
        Entry(const Entry &e):key(e.key),value(e.value),Next(nullptr),Down(nullptr){}
        bool operator <(const Entry &e);
        bool operator <=(const Entry &e);
        bool operator >(const Entry &e);
        bool operator >=(const Entry &e);
        bool operator ==(const Entry &e);
        Entry*& next()
        {
            return Next;
        }
        Entry*& down()
        {
            return Down;
        }
    };
    
    //Entry的函数
    template <typename T>
    bool Entry<T>::operator<(const Entry& e)
    {
        return key<e.value;
    }
    
    template <typename T>
    bool Entry<T>::operator<=(const Entry& e)
    {
        return key<=e.value;
    }
    
    template <typename T>
    bool Entry<T>::operator>(const Entry& e)
    {
        return key>e.value;
    }
    
    template <typename T>
    bool Entry<T>::operator>=(const Entry& e)
    {
        return key>=e.value;
    }
    
    template <typename T>
    bool Entry<T>::operator==(const Entry& e)
    {
        return key==e.value;
    }
    
    #endif

    main.cpp

    #include <iostream>
    #include "skiplist.h"
    
    int main()
    {
        Entry<int> *e=new Entry<int>(1,2);
        SkipList<int> sk;
        sk.inserts(e);
        return 0;
    }
  • 相关阅读:
    bzoj3996
    bzoj3157 3516
    bzoj1937
    bzoj1532
    bzoj3572
    bzoj1453
    bzoj3205
    bzoj2595
    关于高斯消元解决xor问题的总结
    linux查找和替换命令
  • 原文地址:https://www.cnblogs.com/tianzeng/p/10584726.html
Copyright © 2020-2023  润新知