直接上代码,拷贝过去就能运行
注释写在对应的代码里、
节点的定义
#ifndef _SKIP_NODE_H
#define _SKIP_NODE_H
#include <iostream>
struct skipNode
{
int key;
int value;
int level; //size表示该节点存在的最高层数
skipNode* *next; //skipNode* 的数组
skipNode(int k, int v, int size) : key(k), value(v), level(size) {
next = new skipNode*[size];
}
void print() {
std::cout << "--------------" << std::endl;
std::cout << "key = " << key << ", value = " << value << std::endl;
std::cout << "--------------" << std::endl;
}
};
#endif
跳表类的实现
// MySkipList.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include "SkipNode.h"
#include <iostream>
using namespace std;
class skipList {
public:
skipList(int, int, float prob = 0.5, int maxNum = 10000);
~skipList();
skipNode* find(const int) const;
void erase(const int);
void insert(const int k, const int v);
void print();
protected:
//获得新的level
int getNewLevel()const;
//搜索指定key的附近节点
skipNode* search(const int) const;
private:
float cutOff; //用于生成新的层级
int levels; //当前已经分到了多少层
int maxLevel; //层数上限
int maxKey; //key值上限
int dataSize; //节点个数
skipNode* headerNode;
skipNode* tailNode;
skipNode** last; //因为是单链结构,所以保存查找的节点的前一个节点
};
//prob = 每隔 1/prob 个节点分一层
//headKey = 头节点的key值,所有节点key值均不大于此key值
//tailKey = 为节点的key值,所有节点key值均不大于此key值
//maxNum = 跳表最大接受的节点个数
skipList::skipList(int headKey, int tailKey, float prob, int maxNum)
{
cutOff = prob * RAND_MAX;
maxLevel = (int)ceil(logf((float)maxNum) / logf(1 / prob));
levels = 0;
maxKey = headKey;
dataSize = 0;
//初始化头尾节点
headerNode = new skipNode(headKey, 0, maxLevel + 1);
tailNode = new skipNode(tailKey, 0, 0);
//上次对比的节点
last = new skipNode*[maxLevel + 1];
//初始化头尾节点指向
for (int i = 0; i <= maxLevel; i++)
headerNode->next[i] = tailNode;
}
skipList::~skipList()
{
skipNode* node;
//第0层包含了所有的节点
while (headerNode != tailNode) {
node = headerNode->next[0];
delete headerNode;
headerNode = node;
}
delete tailNode;
delete[] last;
}
//利用随机数是否大于cutoff值获得新的level值
//但新的level值不超过maxLevel,防止浪费
int skipList::getNewLevel() const
{
int lev = 0;
while (rand() <= cutOff)
lev++;
return lev <= maxLevel? lev: maxLevel;
}
skipNode * skipList::search(const int theKey) const
{
if (theKey > maxKey)
return NULL;
skipNode* node = headerNode;
for (int i = levels; i >= 0; i--)
{
while (node->next[i]->key < theKey)
node = node->next[i];
//因为节点处在单链上
//所以,这里保存该节点的前一个节点,方便插入
last[i] = node;
}
return node->next[0];
}
skipNode * skipList::find(const int theKey) const
{
if (theKey >= maxKey)
return NULL;
skipNode* node = headerNode;
for (int i = levels; i >= 0; i--)
while (node->next[i]->key < theKey)
node = node->next[i];
if (node->next[0]->key == theKey)
return node->next[0];
return NULL;
}
void skipList::erase(const int theKey)
{
if (theKey > maxKey)
return;
skipNode* node = search(theKey);
if (node->key != theKey)
return;
for (int i = 0; i <= levels && last[i]->next[i] == node; i++)
last[i]->next[i] = node->next[i];
//删除没有数据的层
while (levels > 0 && headerNode->next[levels] == tailNode)
levels--;
delete node;
dataSize--;
}
void skipList::insert(const int k, const int v)
{
if (k > maxKey) {
cout << "key = " << k << "不能比maxKey = " << maxKey << "大" << endl;
return;
}
skipNode* node = search(k);
//节点已存在
if (node->key == k)
{
node->value = v;
return;
}
//节点不存在, 此时node在新加的节点右侧
//生成新的层次
int newLevel = getNewLevel();
if (newLevel > levels)
{
newLevel = ++levels;
last[newLevel] = headerNode;
}
skipNode* newNode = new skipNode(k, v, newLevel);
//last节点数组保存了该节点的前一个节点
//每一层都插入
for (int i = 0; i <= newLevel; i++)
{
newNode->next[i] = last[i]->next[i];
last[i]->next[i] = newNode;
}
dataSize++;
return;
}
void skipList::print()
{
cout << "output all node->" << endl;
skipNode* node, *nextNode;
for (int i = levels; i >= 0; i--)
{
node = headerNode;
cout << "第" << i << "层" << "->";
while (node != tailNode) {
cout << "(k=" << node->key << " , v=" << node->value << ")";
cout << " -> ";
node = node->next[i];
}
cout << endl;
}
cout << "--------------" << endl;
}
int main()
{
skipList list(999, 1000);
list.insert(1, 100);
list.insert(3, 300);
list.insert(2, 200);
list.insert(7, 700);
list.insert(6, 600);
list.insert(4, 400);
list.insert(5, 500);
list.print();
skipNode* node = list.find(3);
if (node)
node->print();
else
cout << "find node not exist" << endl;
list.erase(3);
list.print();
node = list.find(3);
if (node)
node->print();
else
cout << "find node not exist" << endl;
}
运行的结果

本文详细介绍了跳表数据结构的实现过程,包括节点定义、跳表类的构造和析构、搜索、插入、删除等核心操作。通过具体的代码示例,展示了如何在C++中实现跳表,并提供了完整的运行示例。

228

被折叠的 条评论
为什么被折叠?



