关于跳表的详细介绍请看数据结构与算法——跳表。
本文主要介绍跳表的一种实现方式。
头文件如下:
/*
* Copyright: (c) 2019
*
* 文件名称: SkipList.h
* 文件标识:
* 摘 要: 跳表的一种模板实现方法,跳表中存储的是模板类型,并且存储的是不重复的
*
* 版 本: 1.0
* 作 者: RF_LYF
* 创建日期: 2019/5/14 8:51
*/
#ifndef _SKIPLIST_H
#define _SKIPLIST_H
#include <iostream>
#define MAX_LEVEL 16
template<typename T>
class SNode
{
typedef SNode<T>* pSNode;
public:
SNode()
{
maxLevel = 0;
forward = new pSNode[MAX_LEVEL];
for(int i = 0; i < MAX_LEVEL; ++i)
{
forward[i] = NULL;
}
}
~SNode()
{
delete []forward;
forward = NULL;
}
T data;
int maxLevel;
pSNode *forward;
};
template<typename T>
class SkipList
{
typedef SNode<T>* pSNode;
public:
SkipList(void);
~SkipList(void);
void Insert(const T value);
void Delete(const T value);
pSNode Find(const T value);
void printAll();
private:
int randomLevel();
void InitArr(pSNode*, int);
void clear();
int getRandom();
private:
int levelCount;
pSNode head;
};
#endif //_SKIPLIST_H
源文件如下:
/*
* Copyright: (c) 2019
*
* 文件名称: SkipList.cpp
* 文件标识:
* 摘 要:
*
* 版 本: 1.0
* 作 者: RF_LYF
* 创建日期: 2019/5/14 8:50
*/
#include "SkipList.h"
#include <random>
#include <stdlib.h>
#include <time.h>
template<typename T>
SkipList<T>::SkipList(void)
{
levelCount = 1;
head = new SNode<T>();
}
template<typename T>
SkipList<T>::~SkipList(void)
{
clear();
}
/**
* @brief 在跳表中插入某一数据
*
* @method: Insert
* @access: public
* @param: const T value
* @Return: void
* @author: RF_LYF
* @since: 2019/5/15 22:52
*/
template<typename T>
void SkipList<T>::Insert(const T value)
{
int level = randomLevel();
pSNode newNode = new SNode<T>();
newNode->data = value;
newNode->maxLevel = level;
pSNode* update = new pSNode[level];
InitArr(update, level);
for(int i = 0; i < level; ++i)
{
update[i] = head;
}
pSNode p = head;
for(int i = level - 1; i >= 0; --i)
{
while(p->forward[i] != NULL && p->forward[i]->data < value)
p = p->forward[i];
update[i] = p;
}
for(int i = 0; i < level; ++i)
{
newNode->forward[i] = update[i]->forward[i];
update[i]->forward[i] = newNode;
}
if(levelCount < level)
levelCount = level;
delete []update;
}
/**
* @brief 在跳表中删除某一数据
*
* @method: Delete
* @access: public
* @param: const T value
* @Return: void
* @author: RF_LYF
* @since: 2019/5/15 22:52
*/
template<typename T>
void SkipList<T>::Delete(const T value)
{
pSNode *update = new pSNode[levelCount];
InitArr(update, levelCount);
pSNode p = head;
for(int i = levelCount - 1; i >= 0; --i)
{
while(p->forward[i] != NULL && p->forward[i]->data < value)
p = p->forward[i];
update[i] = p;
}
if(p->forward[0] != NULL && p->forward[0]->data == value)
{
pSNode delptr = p->forward[0];
for(int i = levelCount - 1; i >= 0; --i)
{
if(update[i]->forward[i] != NULL && update[i]->forward[i]->data == value)
{
update[i]->forward[i] = update[i]->forward[i]->forward[i];
}
}
delete delptr;
}
delete []update;
}
/**
* @brief 在跳表中查找某一数据
*
* @method: Find
* @access: public
* @param: const T value
* @Return: ::pSNode
* @author: RF_LYF
* @since: 2019/5/15 22:52
*/
template<typename T>
typename SkipList<T>::pSNode SkipList<T>::Find(const T value)
{
pSNode p = head;
for(int i = levelCount - 1; i >=0; --i)
{
while(p->forward[i] != NULL && p->forward[i]->data < value)
{
p = p->forward[i];
}
}
if(p->forward[0] != NULL && p->forward[0]->data == value)
return p->forward[0];
else
return NULL;
}
/**
* @brief 随机确定跳表更新的层数
*
* @method: randomLevel
* @access: private
* @Return: int
* @author: RF_LYF
* @since: 2019/5/15 22:52
*/
template<typename T>
int SkipList<T>::randomLevel()
{
int level = 1;
for(int i = 1; i < MAX_LEVEL; ++i)
{
if(1 == (getRandom() % 3))
{
level++;
}
}
return level;
}
/**
* @brief 初始化数组
*
* @method: InitArr
* @access: private
* @param: typename SkipList<T>::pSNode * Arr
* @param: int nLen
* @Return: void
* @author: RF_LYF
* @since: 2019/5/15 22:53
*/
template<typename T>
void SkipList<T>::InitArr(typename SkipList<T>::pSNode* Arr, int nLen)
{
for(int i = 0; i < nLen; ++i)
{
Arr[i] = NULL;
}
}
/**
* @brief 仅用来测试
*
* @method: printAll
* @access: public
* @Return: void
* @author: RF_LYF
* @since: 2019/5/15 22:54
*/
template<typename T>
void SkipList<T>::printAll()
{
for(int i = levelCount - 1; i >= 0; --i)
{
pSNode p = head;
std::cout << "The " << i + 1 << " layer" << std::endl;
while(p->forward[i] != NULL)
{
std::cout << p->forward[i]->data << " ";
p = p->forward[i];
}
std::cout << std::endl;
}
}
/**
* @brief 清空跳表
*
* @method: clear
* @access: private
* @Return: void
* @author: RF_LYF
* @since: 2019/5/15 22:53
*/
template<typename T>
void SkipList<T>::clear()
{
pSNode p = head;
while(p->forward[0] != NULL)
{
pSNode delptr = p->forward[0];
p->forward[0] = p->forward[0]->forward[0];
delete delptr;
}
delete head;
head = NULL;
}
/**
* @brief 获取一个随机数
*
* @method: getRandom
* @access: private
* @Return: int
* @author: RF_LYF
* @since: 2019/5/15 22:53
*/
template<typename T>
int SkipList<T>::getRandom()
{
static int count = 1;
std::default_random_engine generator(time(NULL) + count);
std::uniform_int_distribution<int> distribution(1,99999);
int dice_roll = distribution(generator);
count += 100;
return dice_roll;
}
以上实现,当插入新数据时,通过随机函数确定需要更新的索引层,会存在下边的几层索引的结点完全一样,进而导致查找效率降低,极端情况下时间复杂度会退化为O(n),因此还需要进一步改进。