跳表查找C++demo(时间复杂度O(log n))通俗易懂的版本

跳表中的每个节点都有多层跳表指针,最高层数取决于链表长度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);//跳表搜索结果
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值