2020-11-12 跳表


前言

用c++实现一个简单跳表。


一、什么是跳表

跳表的介绍很多数据结构中都有,第一次了解的推荐看一下这片博客:https://blog.csdn.net/daniel_ustc/article/details/20218489 ,在这里就不介绍了

二、c++实现代码

代码如下(示例):

#include <limits.h>
#include <vector>
#include <iostream>
using namespace std;

struct SKNode
{
	int key;
	int value;
	int level;
	SKNode **next;
	SKNode(int iKey, int iValue, int iLevel) :key(iKey), value(iValue), level(iLevel)
	{
		next = new SKNode *[iLevel];
	}
	void print()
	{
		std::cout << "--------------" << std::endl;
		std::cout << "key = " << key << ", value = " << value << std::endl;
		std::cout << "--------------" << std::endl;
	}
};

class SkipList
{
public:
	SkipList(double iProb, int iMaxLevel);
	~SkipList();
	SKNode *find(int iKey);
	void insert(int iKey, int iValue);
	void erase(int iKey);
	void print();
private:
	int getLevel();
	SKNode *search(int iKey,vector<SKNode *>&ovNodes);
private:
	int m_curLevel;         //当前最大层数
	const int m_maxLevel;   //跳表最大层数
	double m_probability;   //生成下一层的概率
	SKNode *m_pHeadNode;    //跳表头结点,头结点的key最小
	SKNode *m_pTailNode;    //跳表尾部结点,尾结点的key最大
};

SkipList::SkipList(double iProb=0.5, int iMaxLevel=10)
	:m_probability(iProb), m_maxLevel(iMaxLevel), m_curLevel(0)
{
	m_pHeadNode = new SKNode(INT_MIN, 0, m_maxLevel);
	m_pTailNode = new SKNode(INT_MAX, 0, m_maxLevel);
	//将头尾结点连结起来
	for (int i = 0; i < m_maxLevel;++i)
	{
		m_pHeadNode->next[i] = m_pTailNode;
	}
}

SkipList::~SkipList()
{
	SKNode *pNext = nullptr;
	while (m_pHeadNode!=m_pTailNode)
	{
		pNext = m_pHeadNode->next[0];
		delete m_pHeadNode;
		m_pHeadNode = pNext;
	}
	delete m_pTailNode;
}

int SkipList::getLevel()
{
	int iCutNum = 1000 * m_probability;
	int iRandNum = rand() % 1001;
	int iLevel = 1;
	while (iRandNum<=iCutNum)
	{
		iLevel++;
		iRandNum = rand() % 1001;
	}
	return iLevel;
}

SKNode *SkipList::search(int iKey, vector<SKNode *>&ovNodes)
{
	//逐层从上向下查找,直到找到第一个不小于指定key的节点
	ovNodes.resize(m_curLevel);
	SKNode *node = m_pHeadNode;
	for (int i = m_curLevel-1; i >= 0; --i)
	{
		
		while (node->next[i]->key < iKey)
		{
			int temp = node->next[i]->key;
			node = node->next[i];
		}
		ovNodes[i]=node;
	}
	return node->next[0];
}

SKNode *SkipList::find(int iKey)
{
	//逐层从上向下查找,直到找到第一个不小于指定key的节点
	vector<SKNode *>vNodes;
	SKNode *node = search(iKey, vNodes);
	if (node->key == iKey)
	{
		return node;
	}
	return nullptr;
}

void SkipList::insert(int iKey, int iValue)
{
	vector<SKNode *>vNodes;
	SKNode *node = search(iKey, vNodes);
	if (node->key == iKey)
	{
		node->value=iValue;
		return;
	}
	int iLevel = getLevel();
	SKNode *pNewNode = new SKNode(iKey, iValue, iLevel);
	if (iLevel>m_maxLevel)
	{
		iLevel = m_maxLevel;
	}
	if (iLevel>m_curLevel)
	{
		for (int i = m_curLevel; i < iLevel;++i)
		{
			vNodes.push_back(m_pHeadNode);
		}
		m_curLevel = iLevel;
	}
	for (int i = 0; i < iLevel; ++i)
	{
		pNewNode->next[i] = vNodes[i]->next[i];
		vNodes[i]->next[i] = pNewNode;
	}
}

void SkipList::erase(int iKey)
{
	vector<SKNode *>vNodes;
	SKNode *node = search(iKey, vNodes);
	if (node->key != iKey)
	{
		return;
	}
	for (int i = 0; i < m_curLevel&&vNodes[i]->next[i]==node; ++i)
	{
		vNodes[i]->next[i] = node->next[i];
	}
	while (m_curLevel>=0&&m_pHeadNode->next[m_curLevel]==m_pTailNode)
	{
		--m_curLevel;
	}
	delete node;
}

void SkipList::print()
{
	cout << "output all node->" << endl;
	SKNode* node, *nextNode;
	for (int i = m_curLevel-1; i >= 0; i--)
	{
		node = m_pHeadNode->next[0];
		cout << "第" << i+1 << "层" << "->";
		while (node != m_pTailNode) {
			cout << "(k=" << node->key << " , v=" << node->value << ")";
			if (node->next[0]!=m_pTailNode)
			{
				cout << " -> ";
			}
			node = node->next[i];
		}
		cout << endl;
	}
	cout << "--------------" << endl;
}

int main()
{
	SkipList list;
	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();

	SKNode* 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;
	system("pause");
}

在 PostgreSQL 数据库中,并没有内置的跳表(Skip List)索引实现。PostgreSQL 提供了多种索引类型,如B树索引、哈希索引、GiST索引和GIN索引等,但没有直接支持跳表的索引类型。 B树索引是 PostgreSQL 中最常用的索引类型之一。它适用于范围查询和等值查询,并且可以保持数据有序性。B树索引在处理数据块的平衡性和查询效率方面具有很好的性能。 除了B树索引之外,PostgreSQL 还提供了其他类型的索引用于特定的场景。例如,哈希索引适用于等值查询,可以提供快速的哈希查找;GiST 索引(通用搜索树)和 GIN 索引(通用倒排索引)适用于全文搜索和复杂的匹配查询。 虽然 PostgreSQL 不提供内置的跳表索引实现,但是你可以使用扩展或自定义索引实现跳表的功能。通过编写自定义插件或使用第三方扩展,你可以在 PostgreSQL 中实现跳表索引。这需要一定的开发工作,并且需要充分测试和评估性能。 需要注意的是,自定义实现的跳表索引可能会受到 PostgreSQL 内核版本更新的影响,并且可能无法享受到 PostgreSQL 内置索引的一些优化和支持。 总之,PostgreSQL 并没有内置的跳表索引实现,但提供了其他类型的索引,如B树索引、哈希索引、GiST索引和GIN索引等,用于满足不同的查询需求。如果需要使用跳表索引,你可以考虑自定义实现或使用第三方扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值