关于跳表及其实现

对于数组,查询访问十分方便,可以通过下标,偏移量进行随机访问,但其插入删除操作效率不高,还需要进行内容的拷贝。链表很好的弥补了数组增删效率低这一点,通过指针来把零散的空间进行逻辑连接,但是由于链表不支持随机访问,所以需要去遍历,访问效率低,时间复杂度O(n)。
跳表对此进行了改进,以空间换取时间,使得时间复杂度可以做到O(logn),相当于链表上实现二分法思想,链表需要有序。那么跳表如何做到这一点的呢,关键就是添加了索引。
如下图,最底层的链表即为所有数据存储的区域,而上面的是每一层的索引值。
在这里插入图片描述

1.查找

例如我们要查找55,如果是纯链表的话要搜索8个结点,而跳表只需要搜索6个结点,因为例子的数据量很小,所以体现的差异不明显,但当数据量达一定程度时,跳表的高效会更明显。
在这里插入图片描述
由于索引值的存在,在查找时可以省去很多索引值中间结点的查询。

2.插入

元素插入后需要往上添加索引,但我们知道索引值越往上层应该是越少的,那么如何确定该节点是否应该往上添加索引,这里用到一个随机数来决定,也就是说插入的节点有50%的概率需要往上添加索引。例如添加15.
在这里插入图片描述

3.删除

同插入,删除的话需要连同上层的索引一起删除。例如删除5
在这里插入图片描述

#include <iostream>
using namespace std;
struct node{ //节点成员
    node* left,*right,*up,*down;
    int data;
    node(int a):data(a) {left = NULL;right = NULL;up = NULL;down = NULL;}
};

class myjumplist{
private:
	//用最上层的一头一尾节点来管理跳表。
    node *head;
    node *tail;
    int maxlevel;//索引层数

public:
    myjumplist(){
    	//为了编程方便,每一层的首位节点值均为最小值和最大值。
        head = new node(INT32_MIN);
        tail = new node(INT32_MAX);
        head->right = tail;
        tail->left = head;
        maxlevel = 0;//最下面一层不算索引
    }

    void append(node* prenode,node *inode){//把inode插入到prenode后
        inode->right = prenode->right;
        prenode->right->left = inode;
        prenode->right = inode;
        inode->left = prenode;
    }

    void insert(int val){//元素插入
        node *serchnode = find(val);//先查找有无该节点,有则返回该节点,无则返回左边第一个比val小的结点。
        if(serchnode->data == val)
        {
            cout<<"this val already exist"<<endl;
            return ;
        }
        node *newnode = new node(val);
        append(serchnode,newnode);//插入新节点
        int curlevel = 0;
        while(rand()%2 == 1)//随机决定是否“晋升”
        {
            if(curlevel == maxlevel)//如果当前索引层为最上层,则增加一层索引
                addlevel();
            while(serchnode->up==NULL)//找到左边第一个向上存在索引节点的结点
                serchnode = serchnode->left;

            node* inode = new node(val);
            serchnode = serchnode->up;
            append(serchnode,inode);
            inode->down = newnode;
            newnode->up = inode;
            newnode = inode;
            curlevel++;
        }
    }

    void addlevel(){
        maxlevel++;
        node *h = new node(INT32_MIN);
        node *t = new node(INT32_MAX);
        h->right = t;
        t->left = h;
        head->up = h;
        h->down = head;
        tail->up = t;
        t->down = tail;
        head = h;
        tail = t;
    }

    node *find(int val){//查找
        node* serchnode = head;
        while(1)
        {
            while(serchnode->right->data!= INT32_MAX && val>=serchnode->right->data)
                serchnode = serchnode->right;

            if(serchnode->down == NULL)
                break;

            serchnode = serchnode->down;
        }
        return serchnode;
    }

  void deletelevel(node *goalnode){
           node *h = goalnode->left;
           node *t = goalnode->right;
           h->down->up = NULL;
           t->down->up =NULL;
           delete h;
           delete t;
   }
   
    void deletenode(int val){
        node *serchnode = find(val);
        if(serchnode->data!=val)
        {
            cout<<"delete fail,no such val"<<endl;
            return ;
        }
        int curlevel = 0;
        while(serchnode!=NULL)
        {
            serchnode->left->right = serchnode->right;
            serchnode->right->left = serchnode->left;
            if(curlevel!=0 && serchnode->left->data==INT32_MIN&&serchnode->right->data==INT32_MAX)
                deletelevel(serchnode);
            else
                curlevel++;

            node *tmp = serchnode;
            serchnode = serchnode->up;
            delete tmp;
        }

    }


    void printflist(){
        node *cur = head;
        while(cur->down!=NULL)
            cur = cur->down;
        while(cur->right->data!=INT32_MAX)
        {
            cout<<cur->right->data<<" ";
            cur = cur->right;
        }
        cout<<endl;
    }

    ~myjumplist(){
        node *cur = head;
        node *dcur;
        while(cur=NULL)
        {

            dcur = cur->down;
            while(cur!=NULL)
            {
                  node *tmp = cur->right;
                  delete cur;
                  cur = tmp;
            }
            cur = dcur;
        }

    }
};

int main()
{
    myjumplist p;
    p.insert(1);
    p.insert(1);
    p.insert(5);
    p.insert(43);
    p.insert(2);
    p.insert(200);
    p.insert(35);
    p.printflist();
    p.deletenode(200);
    p.deletenode(5);
    p.printflist();
    return 0;
}

在这里插入图片描述
参考文章:https://zhuanlan.zhihu.com/p/200815425

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值