跳表实现

要求
实现并分析跳表结构
构造并实现跳表ADT,跳表ADT包括如下操作:

初始化跳表
查找跳表内是否存在元素x
向跳表插入元素x
删除跳表内元素x,若不存在则抛出异常
删除跳表内关键字最小的元素
删除跳表内关键字最大的元素
其他根据需要实现,注意数据的可访问性
格式
输入格式
输入包含 1+n+m 行数据
第一行包含两个数字 n, m (0 \leq n \leq 1000, 0 \leq m \leq 10000≤n≤1000,0≤m≤1000)
之后的 n 行,每行包含一个数字与一个字符串,表示一个元素,数字为跳表的关键字(0\leq key \leq 1,000,000,000)(0≤key≤1,000,000,000),字符串为元素的值。
之后的 m 行表示 m 个跳表ADT操作。每行第一个数字 a 用来区别操作。

a 为 1 时,表示查找操作,其后的一个数字 b 为要查询的元素的关键字, 输出 该元素的值,不存在则输出 -1。
a 为 2 时,表示插入操作,其后的一个数字 b 为要插入的元素,一个字符串 c 为对应的值, 不输出 。
a 为 3 时,表示删除操作,其后的一个数字 b 为要删除的关键字, 输出 该关键字与其对应的元素值,若删除关键字不存在或删除失败,输出 -1。
a 为 4 时,表示删除最小元素操作。 输出 跳表内最小关键字 c 与其对应的元素值,并将对应元素在跳表内部删除
a 为 5 时,表示删除最大元素操作。 输出 跳表内最大关键字 c 与其对应的元素值,并将对应元素在跳表内部删除
输出格式
请根据输入描述,完成跳表的相应操作,输出正确的信息

样例
输入

3 6
10 apple
1 mi
5 oops
1 10
2 7 oppo
3 4
3 5
4
5

输出

apple
-1
5 oops
1 mi
10 apple

可能出现的问题:
删除时不是指删除找到的第一个元素
要继续下一层查找 元素会同时存在多层

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream> 
using namespace std;
typedef int Key;
int maxlevel=20;
struct item{Key key;
};
typedef struct sknode* link;
struct sknode{//建结构
	item it;//元素->用来排序
	string str;//元素值
	link *next;//指向下一个节点
	int s;//连接数
};

link head;//头指针
link endd;//尾指针

int allnode;//节点总数
int highlevel;//层数

struct item NULLit;//判断空
string NULLstr="-1";//判断空
Key key(item it){
	return it.key;
}

link NEW(item it,string str,int s){
	link x=new sknode;//使用new使得string分配到空间
	//x->next=new sknode*;//若值不为string类型可用
	x->next=(link *)malloc(s*sizeof(link));
	x->it=it;
	x->s=s;
    if(str!="-1"){x->str=str;
	}
	for(int i=0;i<s;i++){
		x->next[i]=endd;
	}
	return x;
}

void skinit(){//初始化
	allnode=0;highlevel=0;
	endd=NEW(NULLit,NULLstr,1000);
	head=NEW(NULLit,NULLstr,maxlevel+1);
}

int randnode(){//随机数生成
	int i,j,t=rand();
	for(i=1,j=2;i<maxlevel;i++,j+=j){
		if(t>RAND_MAX/j){break;
		}
	}
	if(i>highlevel){
			highlevel=i;
		}
		return i;
}

void insert(link t,link x,int s){//t:原跳表 x:插入元素 s:层数 
	Key v=key(x->it),u=key(t->next[s]->it);
	if(v<u||u==0){
		if(s<x->s){
			x->next[s]=t->next[s];
			t->next[s]=x;
		}
		if(s==0){return;
		}
		insert(t,x,s-1);return;//这层不应该被插入 从下一层开始找
}
	}
	insert(t->next[s],x,s);//下一个元素

void skinsert(item it,string str){
	insert(head,NEW(it,str,randnode()),highlevel);
	allnode++;
}

void deletenode(link t,Key k,int s){//t:原跳表 k:插入元素 s:层数
    if(t==endd){cout<<-1<<endl;return;
	}
	link x=t->next[s];
	if(!(key(x->it)<k)||key(x->it)==0){
		if(k==key(x->it)){//找到元素
			t->next[s]=x->next[s];//链表删除
			if(s==0){cout<<k<<' '<<x->str<<endl;return;
			}
			
		} 
		if(s==0){cout<<"-1"<<endl;return;//层数归零
		}
		deletenode(t,k,s-1);return;//这层未找到元素 从下一层开始找
	}
	deletenode(t->next[s],k,s);//下一个元素
}

void skdelete(Key k){
	deletenode(head,k,highlevel);
	allnode--;
}
void search(link t,Key k,int s){//查找
	if(t==endd){cout<<-1<<endl;return;
	}
	if(k==key(t->it)){cout<<t->str<<endl;return ;
	}
	Key u=key(t->next[s]->it);
	if(k<u||u==0){
		if(s==0){cout<<"-1"<<endl;return;
		}else{search(t,k,s-1);return;//下一层
		}
	}
	search(t->next[s],k,s);//下一个元素
} 

void sksearch(Key k){
	search(head,k,highlevel);
}

void searchsmall(){//头结点的下一个为最小元素
    link t= head;
	skdelete(key(t->next[0]->it));return;
}
void searchbig(){//第0层节点遍历后的最后一个为最大元素
	link t = head ;
	while(t->next[0] !=endd){
		if(t->next[0]->next[0]==endd){skdelete(key(t->next[0]->it));return;
		}
 		t = t->next[0];
	 }
}
void p(){//遍历所有元素 
 	link t = head ;
 	while(t->next[0] !=endd){
 		cout<<t->next[0]->it.key<<' '<<t->next[0]->str<<endl;
 		t = t->next[0];
	 }
	 cout<<endl;
 }
int main(){
	int n,m;
	skinit();//初始化
	int a;
	string st;
	item nu;
	cin>>n>>m;
	for(int i=0;i<n;i++){//插入
		cin>>nu.key>>st;
		skinsert(nu,st);
	}
	for(int i=0;i<m;i++){
		cin>>a;
	    if(a==1){//查找
	    	cin>>a;
	    	sksearch(a);
		}else if(a==2){//插入元素
			cin>>nu.key>>st;
			skinsert(nu,st);
		}else if(a==3){//删除指定元素
			cin>>a;
			skdelete(a);
		}else if(a==4){//删除最小
			searchsmall();
		}else if(a==5){//删除最大
			searchbig();
		}
	} 
	//p();
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值