跳表
跳表是为了降低链表的复杂度,在链表中间的节点中加入一个指针
-首先其数据成员:
1、用于往链表中插入数据确定其级数
2、当前最大的级数
3、允许的最大级数
4、链表当前大小
5、首节点
6、尾节点
7、用于查找数据时确定所有层数的最后一个节点(不是某一层真的最后一个节点,只是要插入位置的前面节点的最后一个)
8、最大关键字
float cutOff;//用来确定层数
int levels; //当前最大的非空链表
int dSize; //字典的数对个数
int maxLevel;//允许的最大链表层数
K tailKey; //最大关键字
skipNode<K, E>* headerNode; //头节点指针
skipNode<K, E>* tailNode; //尾节点指针
skipNode<K, E>** last; //last[i]表示i层的最后节点
成员函数
- 构造函数
template<class K,class E>
skipList<K, E>::skipList(K largeKey, int maxPairs, float prob)
{//构建函数,关键字小于largeKey且size最多为maxPairs. 0<prob<1;
cutOff = prob * RAND_MAX;
tailKey = largeKey;
dSize = 0;
levels = 0;
maxLevel = maxPairs;
//生成头节点、尾节点和数组last
pair<K, E> tailPair;
tailPair.first = tailKey;
headerNode = new skipNode<K, E>(tailPair, maxLevel + 1);
tailNode = new skipNode<K, E>(tailPair, 0);
//当链表为空,头节点有maxLevel+1个指向尾节点的指针
for (int i = 0; i <= maxLevel; i++)
{
headerNode->next[i] = tailNode;
}
}
- 查找函数
template<class K,class E>
skipNode<K, E>* skipList<K, E>::search(const K& k)const
{
skipNode<K, E>* temp = headerNode;
//从上层链表到下层遍历
for (int i = levels; i >=0; i--)
{
while (temp->next[i]->element.first<k)
{
temp = temp->next[i];
}
last[i] = temp;
}
return temp->next[0];
}
查找函数将小于要查找数每一层的最后一个节点放入last----last[i] = temp;返回的是第一个不小于查找数的节点,但并不一定是要找的
- 分配级数函数
template<class K,class E>
int skipList<K, E>::level()const
{
int lev = 0;
while (rand()<=cutOff)
{
lev++;
}
return (level <= maxLevel) ? lev : maxLevel;
}
分配级数也可以将随机数生成器产生的数分几段:第一段(1~1/p)…
- 插入函数
template<class K,class E>
void skipList<K, E>::insert(const pair<const K, E>& thePair)
{//把数对thePair插入字典,覆盖其关键字相同的已存在的数对
if (thePair.first>=tailKey)
{//关键字太大
ostringstream s;
s << "Key = " << thePair.first << " nust be < " << tailKey;
throw illegalParameterValue(s.str());
}
//查看关键字为theKey的数对是否存在
skipNode<K, E>* temp = search(thePair.first);
if (temp->element.first==thePair.first)
{//存在
temp->element.second = thePair.second;
return;
}
//不存在
int theLevel = level();
if (theLevel>levels)
{
theLevel = ++levels;
last[theLevel] = headerNode;
}
//插入新节点
skipNode<K, E>* newNode = new skipNode<K, E>(thePair, theLevel + 1);
for (int i = 0; i <= theLevel; i++)
{
newNode->next[i] = last[i]->next[i];
last[i]->next[i] = newNode;
}
dSize++;
return;
}
插入函数中:
if (theLevel>levels)
{
theLevel = ++levels;
last[theLevel] = headerNode;
}
使插入函数级数最大为当前级数+1;并将其作为当前级数
//插入新节点
skipNode<K, E>* newNode = new skipNode<K, E>(thePair, theLevel + 1);
for (int i = 0; i <= theLevel; i++)
{
newNode->next[i] = last[i]->next[i];
last[i]->next[i] = newNode;
}
将要插入的节点插入不大于theLevel所有层最后一个节点的后面
- 删除节点函数
template<class K,class E>
void skipList<K, E>::erase(const K& k)
{
//链表中没有
if (k>=tailKey)
{
return;
}
//判断是否有匹配的
skipNode<K, E>* temp = search(k);
if (temp->element.first!=k)
{//不存在
return;
}
//从链表中删除节点
for (int i = 0; i <= levels&&last[i]->next[i]==temp; i--)
{
last[i]->next[i] = temp->next[i];
}
//更新链表级
while (levels>0&&headerNode->next[levels]==tailNode)
{
levels--;
}
delete temp;
dSize--;
}
删除函数中while (levels>0&&headerNode->next[levels]==tailNode),表示删除的节点为当前级数节点