数据结构与算法-跳表skiplist C++ DEMO

先贴上一个跳表的实现

包括:初始化、插入、删除、搜索、整理

这是头文件

#pragma once

#include
#include
#include 
#include//使用vector作为动态数组,便于节点的调节
using namespace std;
#define MAX_LEVEL 10 //最大层数

template
class skiplist {
private:
	typedef struct node {
		int key;
		T data;
		vector nexts;
	}node;

	int level;//层数,0是最下面,level-1是最上面
	double num;//数据节点的数量
	node *head;

	node* createNode(int level, int key, T data) {
		node *ns = new node;
		ns->key = key;
		ns->data = data;
		for (int i = 0; i <= level; i++) {
			ns->nexts.push_back(NULL);
		}
		return ns;
	}
	node* createHead(int level, int key) {
		node *ns = new node;
		ns->key = key;
		for (int i = 0; i <= level; i++) {
			ns->nexts.push_back(NULL);
		}
		return ns;
	}
public:
	skiplist() {
		num = 0;
		level = 0;
		head = createHead(MAX_LEVEL - 1, 0);
		for (int i = 0; i < MAX_LEVEL; i++) {
			head->nexts[i] = NULL;
		}
	}
	//随机产生层数
	int randomLevel() {
		int rand_level = 1;
		while (rand() % 2) {
			rand_level++;
		}
		return (rand_level < MAX_LEVEL) ? rand_level : MAX_LEVEL;
	}

	//插入节点
	bool insert(int key, T data) {
		num++;
		node *previous[MAX_LEVEL];
		node *p, *wait_insert = NULL;
		p = head;
		int k = level;
		//从最高层往下查找需要插入的位置
		//填充previous
		for (int i = k - 1; i >= 0; i--) {
			while ((wait_insert = p->nexts[i]) && (wait_insert->key < key)) {
				p = wait_insert;
			}
			previous[i] = p;
		}
		//不能插入相同的key
		if (wait_insert&&wait_insert->key == key) {
			return false;
		}

		//产生一个随机层数K
		//新建一个待插入节点wait_insert
		//一层一层插入
		k = randomLevel();
		//更新跳表的level
		if (k > level) {
			for (int i = level; i < k; i++) {
				previous[i] = head;
			}
			level = k;
		}
		wait_insert = createNode(k, key, data);
		//逐层更新节点的指针,和普通列表插入一样
		for (int i = 0; i < k; i++) {
			wait_insert->nexts[i] = previous[i]->nexts[i];
			previous[i]->nexts[i] = wait_insert;
		}
		return true;
	}

	//搜索指定key的data
	T search(int key)const {
		node *intermediary, *target = NULL;
		intermediary = head;
		//从最高层开始搜
		int k = level;
		for (int i = k - 1; i >= 0; i--) {
			while ((target = intermediary->nexts[i]) && (target->key <= key)) {
				if (target->key == key) {
					return target->data;
				}
				intermediary = target;
			}
		}
		return NULL;
	}
	//删除指定key的节点
	bool deleteSL(int key) {
		num--;
		node *previous[MAX_LEVEL];
		node *p, *wait_del = NULL;
		p = head;
		//从最高层开始搜
		int k = level;
		for (int i = k - 1; i >= 0; i--) {
			//将p调节到需要删除的节点的前一个
			//直到wait节点的key大于等于key,之后判断若等于key则删除,大于key返回删除失败
			while ((wait_del = p->nexts[i]) && (wait_del->key < key)) {
				p = wait_del;
			}
			previous[i] = p;
		}

		//如果q是要删除的节点
		if (wait_del&&wait_del->key == key) {
			//就将q下一个节点的指针剪开,与previous里q之前的节点连接起来
			for (int i = 0; i < level; i++) {
				if (previous[i]->nexts[i] == wait_del) {
					previous[i]->nexts[i] = wait_del->nexts[i];
				}
			}
			//q没用了,删除
			free(wait_del);

			//如果删除的是最大层的节点,那么需要重新维护跳表
			for (int i = level - 1; i >= 0; i--) {
				if (head->nexts[i] == NULL) {
					level--;
				}
			}
			return true;
		}//如果不等于,则返回false
		else
			return false;
	}

	/*重载输出运算符*/
	friend ostream& operator<<(ostream& output, const skiplist& sl) {
		node *temp;
		//i代表层数,该循环为层外循环
		for (int i = sl.level - 1; i >= 0; i--) {
			output << i << "层:" << endl;
			//要从头开始打印
			temp = sl.head;
			//将每一层内的元素打印出来
			while (temp) {
				output << " -> " << temp->key;
				temp = temp->nexts[i];
			}
			//一层打印结束,换行
			output << "\n";
		}
		//打印结束,换行
		output << "\n";
		return output;
	}

	/*当链表过大,种种删除插入操作可能使得跳表索引结构不合理,此时需要重新整理结构
	传入的两个指针应该是该区域两头的最高层节点*/
	bool formate() {
		node * temp = head;
		node * next;
		node * pre = head;
		while (temp) {
			node * next = temp->nexts[0];
			temp->nexts.clear();
			temp->nexts.push_back(next);
			pre = temp;
			temp = next;
		}
		for (int i = 0; i < level - 1; i++) {
			pre->nexts.push_back(NULL);
		}

		int i = 0;
		while (head->nexts[i]->nexts[i] != NULL) {

			temp = head;

			while (1) {
				if (temp == NULL) {
					break;
				}
				if (temp->nexts[i] == NULL) {
					break;
				}

				if (temp->nexts[i]->nexts[i] == NULL) {
					temp->nexts.push_back(temp->nexts[i]);
					break;
				}

				temp->nexts.push_back(temp->nexts[i]->nexts[i]);//temp拔高一层
				temp = temp->nexts[i]->nexts[i];
			}
			i++;
		}
		level = head->nexts.size();
		return true;
	}
};

这是test文件:

#include
#include 
#include "skiplist.h"
using namespace std;

int main() {
	
	cout << " 测试初始化:\n";
	skiplist sl;

	cout << " 测试插入:\n";
	for (int i = 1; i <= 100; i++) {
		cout <

你可能感兴趣的:(数据结构与算法-跳表skiplist C++ DEMO)