跳表中的每个节点都有多层跳表指针,最高层数取决于链表长度n,层数每增加1,一次移动的距离就乘2,因此假设最高层数为h,到达目标节点可能的最远移动距离就是1+21+22+…+2h令它等于i,此时h也是最多的移动次数,可以解出h=log2(i+1)-1,移动次数最多不会超过这个值,所以显然时间代价是O(log n)级别的。
具体的实现思路基本上注释都写到了,如果想进一步完善的话可以把跳表指针数量初始化为log n个。
#include<iostream>
using namespace std;
typedef struct Node {
int data;
Node** skip;
Node() {
data = 0;
skip = (Node**)malloc(sizeof(Node*) * 4);//先假设跳表数组存放了4个跳表指针
}
~Node() {
free(skip);
}
}Node;
void Insert(Node** phead,int x) {//在尾部后面插入
Node* newNode = new Node();
newNode->skip[0] = NULL;
newNode->data = x;
if (*phead == NULL)
*phead = newNode;
else {
Node* temp = *phead;
while (temp->skip[0]) {
temp->skip[0] = temp->skip[0];
temp = temp->skip[0];
}
temp->skip[0] = newNode;
}
}
void Print(Node* head) {
Node* temp = head;
while (temp) {
cout << temp->data << " ";
temp = temp->skip[0];
}
cout << endl;
}
int search(Node* head,int i) {
Node* temp = head;
for (int j = 0; j < i-1; j++) {
if (!temp) return -1;//没找到就返回-1
temp = temp->skip[0];
}
return temp->data;
}
bool searchSkip(Node* head, int i) {
Node* temp = head;
int level = 0;
int len = 0;//求链表长度
while (temp) {
len++;
temp = temp->skip[0];
}
if (i <= 0 || i > len) return false;//查找失败返回-1
temp = head;
//设置每一层的skip指针
while (1 + pow(2, level + 1) < len) {
while (temp && temp->skip[level]) {
temp->skip[level + 1] = temp->skip[level]->skip[level];
temp = temp->skip[level + 1];//出循环后每一层上的最后一个节点skip指针都指向NULL
}
temp = head;
level++;
}
int sum = 1;
int times = 0;//记录指针移动总次数
int j = level;//试探每一层移动后的位置,只有预期位置在查找位置之前才能移过去
while (j >= 0) {//若当前层的下一位置已超过查找位置,层数减一,依次向低层试探
if (sum + pow(2, j) < i) {
sum += pow(2, j);
temp = temp->skip[j];
times++;
}
else if (sum + pow(2, j) == i) {
temp = temp->skip[j];
times++;
cout << temp->data << endl;
cout << "层数为:" << level << endl;
cout << "移动总次数为:" << times << endl;
return true;
}
j--;
}
if (j < 0) {
cout << temp->data << endl;
cout << "层数为:" << level << endl;
cout << "移动总次数为:" << times << endl;
return true;
}
}
int main() {
Node* head = NULL;
Insert(&head, 2);
Insert(&head, 5);
Insert(&head, 8);
Insert(&head, 7);
Insert(&head, 9);
Insert(&head, 6);
Insert(&head, 11);
Insert(&head, 3);
Insert(&head, 24);
Insert(&head, 13);
Insert(&head, 17);
Insert(&head, 20);
Print(head);
int i = 0;
cout << "输入查找位置:" << endl;
cin >> i;
cout << "顺序搜索结果:" << endl;
cout << search(head, i) << endl;//顺序搜索结果
cout << "移动总次数为:" << i - 1 << endl;
cout << "跳表搜索结果:" << endl;
searchSkip(head, i);//跳表搜索结果
}