c++实现跳跃表

直接上代码,拷贝过去就能运行
注释写在对应的代码里、

节点的定义

#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;
}


运行的结果

在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值