跳表--板子题

问题 A: 跳表操作

题目描述

实现跳表数据结构,支持增加、查找和删除操作。为保证程序的可复现性,随机生成布尔结果的函数g()定义如下:
g ( ) = { 1 X t < 8 0 X t > = 8 g()= \begin{cases} 1& X_t<8\\ 0& X_t>=8\\ \end{cases} g()={10Xt<8Xt>=8

其中
t > = 1 t>=1 t>=1 X t = ( X t − 1 ∗ a + c ) X_t = (X_t-1 * a + c) % m Xt=(Xt1a+c) X 0 = 7 , a = 5 , c = 37 , m = 19 X_0 = 7, a=5, c=37, m=19 X0=7,a=5,c=37,m=19

假定跳表的第0层存放所有元素。为决定一个不在现有跳表中且待插入的新元素a,可以上升到第h层(h初始值为0),程序反复调用g(),若g()=1,则上升一层,即++h,若g()=0则停止上升; 因此,元素a将位于0,1,…,h层。

输入

注意 :符号//及其后为注解,不是输入/输出的内容。整数之间有1个空格分隔

48 45 45 59 89  //1)随机输入初值数据,可能存在重复(重复的元素不插入跳表)
75 48 90       	//2)连续插入跳表的3个整数,若跳表中已经有相应元素,则不插入
45 59 30     	//3)在2)之后,从跳表中,连续查找的3个整数,对每个待查整数,输出所在各层的严格下界
45 75 87     	//4)在3) 之后,从跳表中,连续删除的3个整数

输出

48	          	//1+)对应输入1),输出建立的跳表,从最高层到最底层,递增输出每层元素(每层元素不重复)
48 89
48 89
45 48 59 89
48 75         	//2+)对应2),输出插入3个新数据后的跳表
48 75 89
48 75 89
45 48 59 75 89 90
N N N N        	//3+)对于要查找的45,输出每层的严格下界b_i={N,N,N,N}, 满足b_i < 45, N表示无穷小
48 48 48 48     //3+)对于要查找的59,输出b_i={48,48,48,48}, 满足b_i < 59
N N N N
48         		//4)删除3个整数之后的跳表。
48 89
48 89

样例输入

48 45 45 59 89
75 48 90
45 59 30
45 75 87

样例输出

48
48 89
48 89
45 48 59 89
48 75
48 75 89
48 75 89
45 48 59 75 89 90
N N N N
48 48 48 48
N N N N
48
48 89
48 89
48 59 89 90

代码

#include<iostream>
#include<vector>
#define INFINITY 99999
using namespace std;

const int Maxlevel=10;//为了做题,先设为10

struct node
{
    int key;//数值
    node* forward[Maxlevel];//指针数组
};

class skiplist
{
public:
    node* head;
    skiplist()
    {
        head=new node();
        head->key=-1;
        node* temp=new node();
        temp->key=INFINITY;
        for(int i=0;i<Maxlevel;i++){//初始化头节点和尾结点,尾结点的key设为无穷
            head->forward[i]=temp;
            temp->forward[i]=NULL;
        }
    }
    bool g()
    {
        static int x=7;
        x=(x*5+37)%19;
        return x>=8;
    }
    int randomX()
    {
        int sum=0;
        while(g())sum++;
        return sum;
    }
    void add()
    {
        vector<int> s1;
        int b;
        while(cin >> b){
            s1.push_back(b);
            if(cin.get()=='\n')break;
        }
        for(int i=0;i<s1.size();i++){//利用连续插入来初始化
            insert(s1[i]);
        }
    }
    void insert(int key)
    {
        node* p=head;
        node* update[Maxlevel];//路径指针数组
        for(int i=Maxlevel-1;i>=0;i--){
            while((p->forward[i]->key<key))//在i level一直找
                p=p->forward[i];
            update[i]=p;//记录每一层走过的最大结点位置
        }
        if(p->forward[0]->key!=key){//如果key值相同就不用插了
            int newlevel=randomX();//新层数
            p=new node();
            p->key=key;
            for(int i=0;i<=newlevel;i++){//更新指针
                p->forward[i]=update[i]->forward[i];
                update[i]->forward[i]=p;
            }
        }
    }
    node* search(int key)
    {
        node* update[Maxlevel];
        node* p=head;
        for(int i=Maxlevel-1;i>=0;i--){
            while((p->forward[i]->key<key))//在i level一直找
                p=p->forward[i];
            update[i]=p;
        }
        /*退出循环时,无论有没有找到,p指向最靠近key的那个结点*/
        return p;
    }
    void Search()
    {
        vector<int> s1;
        int b;
        while(cin >> b){
            s1.push_back(b);
            if(cin.get()=='\n')break;
        }
        for(int i=0;i<s1.size();i++){
            search_print(s1[i]);
        }
    }
    void search_print(int key)
    {
        node* update[Maxlevel];
        node* p=head;
        for(int i=Maxlevel-1;i>=0;i--){
            while((p->forward[i]->key<key))//在i level一直找
                p=p->forward[i];
            update[i]=p;
        }
        /*退出循环时,无论有没有找到,p指向最靠近key的那个结点*/
        if(p->forward[0]->key!=key){//没找到
            cout << "N N N N" << endl;//这里其实要输出maxlevel个N
        }else{
            for(int i=0;i<4;i++){//i应该<maxlevel
                if(!i){
                    if(update[i]->key==-1)cout << 'N';
                    else cout << update[i]->key;
                }else{
                    if(update[i]->key==-1)cout << ' ' << 'N';
                    else cout << ' ' << update[i]->key;
                }
            }
            cout << endl;
        }
    }
    void print_skiplist()
    {
        for(int i=Maxlevel-1;i>=0;i--){
            bool flag=true;
            for(node* p=head->forward[i];p->key!=INFINITY;p=p->forward[i]){
                if(p==head->forward[i]){
                    cout << p->key;
                    flag=false;
                }
                else cout << ' ' << p->key;
            }
            if(!flag)cout << endl;
        }
    }
    void Delete()
    {
        vector<int> s1;
        int b;
        while(cin >> b){
            s1.push_back(b);
            if(cin.get()=='\n')break;
        }
        for(int i=0;i<s1.size();i++)
            deletex(s1[i]);
    }
    void deletex(int key)
    {
        node* target=search(key)->forward[0];
        if(target->key==key)//skiplist中有要删的key
        {
            node *p,*q;
            int i=Maxlevel-1;
            while(i>=0){
                p=q=head;
                while(p&&p!=target){//p不为空继续
                    q=p;//q为p的前一个结点
                    p=p->forward[i];
                }
                if(p)q->forward[i]=p->forward[i];
                i--;
            }
            delete target;
        }
    }
};

int main()
{
    skiplist task;
    task.add();
    task.print_skiplist();
    task.add();
    task.print_skiplist();
    task.Search();
    task.Delete();
    task.print_skiplist();
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值