数据结构与算法--跳表
先贴上一个跳表的实现
包括:初始化、插入、删除、搜索、整理
这是头文件
#pragma once
#include<stdlib.h>
#include<iostream>
#include <math.h>
#include<vector>//使用vector作为动态数组,便于节点的调节
using namespace std;
#define MAX_LEVEL 10 //最大层数
template<typename T>
class skiplist {
private:
typedef struct node {
int key;
T data;
vector<node*> 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<T>& 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<iostream>
#include <string>
#include "skiplist.h"
using namespace std;
int main() {
cout << " 测试初始化:\n";
skiplist<string> sl;
cout << " 测试插入:\n";
for (int i = 1; i <= 100; i++) {
cout <<sl.insert(i, "hhh");
}
cout << " \n测试输出运算符重载:\n";
cout << endl<<sl;
cout << " \n测试搜索功能:\n";
cout << "键100的数据:" << sl.search(100) << endl;
cout << " \n测试删除功能:\n";
cout <<" 删除4号键值对:" <<sl.deleteSL(4) << endl;
cout << sl;
cout << " \n测试整理功能:\n";
cout<<sl.formate();
cout <<"\nformated:\n" <<sl;
system("pause");
return 0;
}