【发布时间】:2018-02-18 23:32:23
【问题描述】:
我正在尝试使用这篇文章Skip List 来实现跳过列表。
代码:
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<limits>
using namespace std;
template<class T>
class SkipList{
private:
class SkipNode{
public:
T* key; //Pointer to the key
SkipNode** forward; //Forward nodes array
int level; //Node level
//SkipNode constructor
SkipNode(T* key, int maxlvl, int lvl){
forward = new SkipNode*[maxlvl];
this->key=key;
level=lvl;
}
//Method that print key and level node
print(){
cout << "(" << *key << "," << level << ") ";
}
};
SkipNode *header,*NIL; //Root and End pointers
float probability; //Level rate
int level; //Current list level
int MaxLevel; //Maximum list levels number
//Function that returns a random level between 0 and MaxLevel-1
int randomLevel(){
int lvl = 0;
while( (float(rand())/RAND_MAX < probability) && (lvl < MaxLevel-1) )
lvl++;
return lvl;
}
public:
//SkipList constructor
SkipList(float probability, int maxlvl){
this->probability = probability;
MaxLevel = maxlvl;
srand(time(0));
header=new SkipNode(NULL,MaxLevel,0); //Header initialization
T* maxValue = new T;
*maxValue = numeric_limits<T>::max(); //Assign max value that T can reach
NIL = new SkipNode(maxValue,0,0); //NIL initialization
level=0; //First level
for(int i=0; i<MaxLevel; i++){ //Every header forward node points to NIL
header->forward[i]=NIL;
}
}
//SkipList destructor
~SkipList(){
delete header;
delete NIL;
}
//Method that search for a key in the list
SkipNode* search(T* key){
SkipNode* cursor = header;
//Scan the list
for(int i=level; i>=0; i--)
while(*(cursor->forward[i]->key) < (*key))
cursor=cursor->forward[i];
cursor=cursor->forward[0];
if(*(cursor->key) == *key)
return cursor;
return NULL;
}
//Method that insert a key in the list
SkipList* insert(T* key){
SkipNode* cursor = header;
SkipNode* update[MaxLevel]; //Support array used for fixing pointers
//Scan the list
for(int i=level; i>=0; i--){
while(*(cursor->forward[i]->key) < *(key))
cursor=cursor->forward[i];
update[i]=cursor;
}
cursor=cursor->forward[0];
if(*(cursor->key) == *(key)){ //Node already inserted
return this;
}
int lvl = randomLevel(); //New node random level
if(lvl > level){ //Adding missing levels
for(int i=level+1; i<=lvl; i++)
update[i]=header;
level=lvl;
}
SkipNode* x = new SkipNode(key,MaxLevel,lvl); //New node creation
for(int i=0; i<=lvl; i++){ //Fixing pointers
x->forward[i] = update[i]->forward[i];
update[i]->forward[i] = x;
}
return this;
}
//Method that delete a key in the list
SkipList* erase(T* key){
SkipNode* cursor = header;
SkipNode* update[MaxLevel]; //Support array used for fixing pointers
//Scan the list
for(int i=level; i>=0; i--){
while(*(cursor->forward[i]->key) < *(key))
cursor=cursor->forward[i];
update[i]=cursor;
}
cursor=cursor->forward[0];
if(*(cursor->key) == *(key)){ //Deletetion of the founded key
for(int i=0; i<=level && update[i]->forward[i] == cursor; i++){
update[i]->forward[i] = cursor->forward[i];
}
delete cursor;
while(level>0 && header->forward[level]==NIL){
level=level-1;
}
}
return this;
}
//Method that print every key with his level
SkipList* print(){
SkipNode* cursor = header->forward[0];
int i=1;
while (cursor != NIL) {
cursor->print();
cursor = cursor->forward[0];
if(i%15==0) cout << endl; i++;
}
cout << endl;
return this;
}
};
main(){
SkipList<int>* list = new SkipList<int>(0.80, 8);
int v[100];
for(int i=0; i<100; i++){
v[i]=rand()%100;
list->insert(&v[i]);
}
list->print();
cout << endl << "Deleting ";
for(int i=0; i<10; i++){
int h = rand()%100;
cout << v[h] << " ";
list->erase(&v[h]);
}
cout << endl;
list->print();
cout << endl;
for(int i=0; i<10; i++){
int h = rand()%100;
cout << v[h] << " ";
if(list->search(&v[h]))
cout << " is in the list" << endl;
else
cout << " isn't in the list" << endl;
}
delete list;
}
它在第 59 行(插入的 for 循环)上给了我分段错误,但我不明白为什么。你能帮帮我吗?我会接受您建议的任何其他改进。我的截止日期是两天,这就是我寻求帮助的原因。
编辑: 我已经用 bebidek 建议更正了代码(谢谢)。现在第一级为 0。它似乎可以正常工作,但有时某些节点未正确插入,搜索结果不佳。
最后编辑: 可以了,谢谢大家
更多编辑: 在代码中添加了 cmets,如果您有任何建议,欢迎您
【问题讨论】:
-
你调试了吗?
-
请解释一下,这是什么:
NIL=new SkipNode(numeric_limits<T*>::max());应该做什么?您创建了一个指针数组,指向某个无效值,然后,在插入时,您尝试取消引用该值,并惊讶于它向您咆哮(以段错误的形式),因为它? -
是的,我尝试调试它,但我无法理解我的错误。我已经更正了 NIL 节点,它包含 T 可以假设的最大值。
-
你可以写出你最后修改的内容,因为我在你的新代码中发现了三个问题,但其中只有一个会给你错误的答案。
-
我在插入中的 for 中添加了“+1”,并在搜索中取出“+1”。现在它似乎工作了。我只需要修复析构函数
标签: c++ skip-lists