插入到跳过列表中
Inserting into a skiplist
我正在开发自己的skiplist模板类。Iterator
类保存单个跳跃表的副本。头迭代器和尾迭代器始终为空,尾迭代器的尾值设置为TRUE
。
class RandomHeight
{
public:
RandomHeight(int maxLvl, float prob);
~RandomHeight() {}
int newLevel(void);
private:
int maxLevel;
float probability;
};
RandomHeight::RandomHeight
(int maxLvl, float prob)
{
srand (time(NULL));
maxLevel = maxLvl;
probability = prob;
}
int RandomHeight::newLevel(void)
{
int tmpLvl = 1;
// Develop a random number between 1 and
// maxLvl (node height).
while ((((rand()%1000000)*1.0/1000000) < probability) &&
(tmpLvl < maxLevel))
tmpLvl++;
return tmpLvl;
}
template <typename Key_T, typename Mapped_T, size_t MaxLevel> class SkipList;
template <typename Key, typename Obj>
class Iterator
{
typedef std::pair<Key, Obj> ValueType;
template <typename Key1, typename Obj1, size_t MaxLevel1> friend class SkipList;
public:
// Iterator(const Iterator &);
//virtual Iterator& operator=(const Iterator &);
Iterator &operator++();
Iterator operator++(int);
//virtual ValueType &operator*() const;
//virtual ValueType *operator->() const;
Iterator(Key, Obj, int,bool);
Iterator(int,bool);
~Iterator();
Key getKey(void) {return key;};
Obj getObj(void) {return obj;};
int getHgt(void) {return nodeHeight;};
bool isTail(void) {return tail;};
private:
int nodeHeight;
Key key;
Obj obj;
bool tail; // holds non null value
Iterator<Key,Obj>** fwdNodes;
};
template <typename Key, typename Obj>
Iterator<Key,Obj>::~Iterator()
{
delete [] fwdNodes;
}
template <typename Key, typename Obj>
Iterator<Key,Obj>::Iterator(Key k,Obj o, int h,bool t = false) : nodeHeight (h) , key (k) , obj (o) , tail(t)
{
fwdNodes = new Iterator<Key,Obj>* [h+1];
for ( int x = 1; x <= nodeHeight; x++ )
fwdNodes[x] = (Iterator<Key,Obj>*) NULL;
}
template <typename Key, typename Obj>
Iterator<Key,Obj>::Iterator(int h,bool t = false) : nodeHeight (h) , key ((Key) NULL) , obj ((Obj) NULL) , tail(t)
{
fwdNodes = new Iterator<Key,Obj>* [h+1];
for ( int x = 1; x <= nodeHeight; x++ )
fwdNodes[x] = (Iterator<Key,Obj>*) NULL;
}
template <typename Key_T, typename Mapped_T, size_t MaxLevel = 5>
class SkipList
{
typedef std::pair<Key_T, Mapped_T> ValueType;
public:
SkipList();
~SkipList();
SkipList(const SkipList &);
SkipList &operator=(const SkipList &);
size_t size() const;
Iterator<Key_T,Mapped_T> begin();
Iterator<Key_T,Mapped_T> end();
//ConstIterator begin() const;
//ConstIterator end() const;
//virtual void clear();
std::pair<Iterator<Key_T,Mapped_T>, bool> insert(const ValueType &);
template <typename IT_T>
void insert(IT_T range_beg, IT_T range_end);
void erase(Iterator<Key_T,Mapped_T> pos);
//virtual void erase(Iterator<Key_T,Mapped_T> range_beg, Iterator<Key_T,Mapped_T> range_end);
private:
Iterator<Key_T,Mapped_T>* head;
Iterator<Key_T,Mapped_T>* tail;
float probability;
size_t maxHeight;
size_t curHeight;
RandomHeight* randGen;
};
template <typename Key_T, typename Mapped_T, size_t MaxLevel>
SkipList<Key_T,Mapped_T,MaxLevel>::SkipList() : curHeight (1), maxHeight(MaxLevel) , probability (1.0/MaxLevel)
{
randGen = new RandomHeight(MaxLevel,probability);
// Create head and tail and attach them
head = new Iterator<Key_T,Mapped_T> (maxHeight);
tail = new Iterator<Key_T,Mapped_T> (maxHeight,true);
for ( int x = 1; x <= maxHeight; x++ )
head->fwdNodes[x] = tail;
}
template <typename Key_T, typename Mapped_T, size_t MaxLevel>
SkipList<Key_T,Mapped_T,MaxLevel>::~SkipList()
{
// Walk 0 level nodes and delete all
Iterator<Key_T,Mapped_T>* tmp;
Iterator<Key_T,Mapped_T>* nxt;
tmp = head;
while ( tmp )
{
nxt = tmp->fwdNodes[1];
delete tmp;
tmp = nxt;
}
delete randGen;
}
我的问题是在下面的插入函数:
template <typename Key_T, typename Mapped_T, size_t MaxLevel>
std::pair<Iterator<Key_T,Mapped_T>, bool> SkipList<Key_T,Mapped_T,MaxLevel>::insert(const ValueType &input)
{
Key_T k = input.first;
Mapped_T o = input.second;
int lvl = 0, h = 0;
Iterator<Key_T,Mapped_T>** updateVec = new Iterator<Key_T,Mapped_T>* [maxHeight+1];
Iterator<Key_T,Mapped_T>* tmp = head;
Key_T cmpKey;
// Figure out where new node goes
for ( h = curHeight; h >= 1; h-- )
{
cmpKey = tmp->fwdNodes[h]->getKey();
while ( !tmp->fwdNodes[h]->isTail() && cmpKey < k )
{
tmp = tmp->fwdNodes[h];
cmpKey = tmp->fwdNodes[h]->getKey();
}
updateVec[h] = tmp;
}
tmp = tmp->fwdNodes[1];
cmpKey = tmp->getKey();
// If dup, return false
if ( !tmp->isTail() && cmpKey == k )
{
delete updateVec;
return std::pair<Iterator<Key_T,Mapped_T>, bool> ( NULL,false);
}
else
{
// Perform an insert
lvl = randGen->newLevel();
if ( lvl > curHeight )
{
for ( int i = curHeight + 1; i <= lvl; i++ )
updateVec[i] = head;
curHeight = lvl;
}
// Insert new element
tmp = new Iterator<Key_T,Mapped_T>(k, o, lvl);
for ( int i = 1; i <= lvl; i++ )
{
tmp->fwdNodes[i] = updateVec[i]->fwdNodes[i];
updateVec[i]->fwdNodes[i] = tmp;
}
delete updateVec;
return std::pair<Iterator<Key_T,Mapped_T>, bool> (*tmp , true);
}
delete updateVec;
return std::pair<Iterator<Key_T,Mapped_T>, bool> ( NULL,false);
}
有什么问题吗?调试了很长时间,我还是弄不清楚。下面的代码给出一个内存转储错误!
std::pair < Iterator<int,float>,bool> a = s.insert(std::pair<int,int>(1,1));
s.insert(std::pair<int,int>(2,1));
s.insert(std::pair<int,int>(3,2));
你的迭代器实现违反了规则三。如果你创建或分配迭代器的副本,你会得到两个迭代器与fwdNodes
指向相同的内存位置。一旦其中一个被删除,另一个将以fwdNodes
指向已经释放的内存结束。
相关文章:
- 使用列表 STL 递归进行插入排序
- 列表 iter 不取消引用 使用列表进行插入排序
- 列表的有效性在插入后开始迭代器
- 如何通过保持第一个插入的位置来对列表中插入的其余元素进行排序?
- 如何从队列插入到 2D 列表
- 将元素插入链接列表
- 无法在我的链接列表中插入项目,head始终为NULL
- 通过动态分配插入列表元素
- 列表插入"Cannot convert argument from Class<T>* to Class<T> &&"
- 双链接列表插入功能C
- 链接列表插入,指针混乱
- 这个无锁数据列表插入是安全的吗
- STL 列表插入要求 3 个参数
- 将字符串列表插入 2D 矢量
- C++列表::插入编译错误
- 为什么我的列表插入函数不生成新节点
- 基于数组的列表-插入函数
- 使用链接列表插入弹出功能
- c++向量和列表插入
- c++列表插入的奇怪行为