数据结构笔记之跳表(SkipList)

 

一、跳表简述

跳表可以看做是一个带有索引的链表,在介绍跳表之前先看一下一个普通的链表,假如当前维护了一个有序的链表:

image

现在要在这个链表中查找128,因为事先不知道链表中数值的分布情况,我们只能从前到后依次遍历,那么有没有什么取巧的方法呢?

如果我们能够存储下最中间节点的引用,比如存储节点29的引用,然后每次要查找节点的时候就先跟29比较一下,如果比29小就还是从前往后找(因为不会超过中间节点,从前往后和从中间往前区别不大),如果比29大就直接跳到29开始往后找,这种思想就是为链表添加了一个简单的索引,一下可以节省掉一半的查找时间。跳表的设计思想类似,通过为链表的每个节点设置高度来添加索引,不同的高度称为不同的层,每一层的next只能指向当前层的下一个节点,下面是一个跳表的示例:

image

最左面一列null为head节点,用于保存每一层的第一个节点,在查找的时候先从最高层开始查找,比如要在上面的跳表中查找128:

image

首先取最高层第六层的next,是47,比128小,直接跳到47,然后47的第六层的next是null,说明到了最后一个了,层数减少,47的第五层的next是255,比128大,也不行,继续减少层数,47的第四层的next是255,依然比128大,继续减少层数,47的第三层的next是128,get it!

看上面的过程有没有意识到一个问题,就是如果跳表的层数过多的话”比较-降层“这个过程就会有不少的浪费,比如上面的在47这个节点进行了4次比较才找到了有效的next节点,如果这个值再大一点的话就会退化得很严重。那么这个层是如何来的呢,跳表的高度是通过一个随机数决定的,初始时默认为一层,然后一直产生随机数只要小于0.5就将层数加一层继续随机,但是随机这种东西毕竟是不可控的,为了避免出现过高的层数最好还是设置一个最大层数以免某些节点的层数过大。

 

二、跳表的实现

跳表的简单Java实现:

SkipList.java:

package alg.link;

import org.apache.commons.lang3.StringUtils;

/**
 * 跳表结构的简单Java实现
 *
 * @author CC11001100
 */
public class SkipList<T extends Comparable<T>> {

	private static final double DEFAULT_CONTINUE_INCREMENT_LEVEL_THRESHOLD = 0.75;
	private static final int DEFAULT_MAX_LEVEL = 10;

	// 用于控制层数,决定层数时当随机数小于此值时会一直升层直到最大,取值范围[0, 1],值越大越可能得到高层数,此值设置不当很有可能退化成链表
	private double continueIncrementLevelThreshold;
	// 为了防止随机数出现异常情况过高,对最大层数做一个限制
	private int maxLevel;
	// 链表的头结点,每一层的头都保存在这里
	private Node<T> head;

	public SkipList() {
		this(DEFAULT_CONTINUE_INCREMENT_LEVEL_THRESHOLD, DEFAULT_MAX_LEVEL);
	}

	public SkipList(double threshold) {
		this(threshold, DEFAULT_MAX_LEVEL);
	}

	public SkipList(double threshold, int maxLevel) {
		this.continueIncrementLevelThreshold = threshold;
		this.maxLevel = maxLevel;
		this.head = new Node<>(null, 0);
		// 初始化时就将其扩充到最大避免后面扩容增加复杂性,只有head会浪费一些空间其它节点都是有几层申请多长的数组
		this.head.next = new Node[maxLevel];
	}

	public void add(T value) {
		Node[] previous = findPrevious(value);
		Node<T> node = new Node<>(value, randomLevel());
		for (int i = 0; i < previous.length && i < node.level; i++) {
			node.next[i] = previous[i].next[i];
			previous[i].next[i] = node;
		}
		if (node.level > head.level) {
			for (int i = node.level - 1; i >= 0 && head.next[i] == null; i--) {
				head.next[i] = node;
			}
			head.level = node.level;
		}
	}

	public void remove(T value) {
		Node[] previous = findPrevious(value);
		Node node = previous[0].next[0];
		if (node.value.compareTo(value) != 0) {
			return;
		}
		for (int i = 0; i < previous.length && i < node.level; i++) {
			previous[i].next[i] = node.next[i];
		}
	}

	public boolean contains(T value) {
		Node[] previous = findPrevious(value);
		Node node = previous[0].next[0];
		return node.value.compareTo(value) == 0;
	}

	private int randomLevel() {
		int level = 1;
		while (level < maxLevel && Math.random() < continueIncrementLevelThreshold) {
			level++;
		}
		return level;
	}

	private Node[] findPrevious(T value) {
		Node[] previous = new Node[head.level];
		Node<T> node = head;
		for (int i = head.level - 1; i >= 0; i--) {
			while (node.next[i] != null && node.next[i].value.compareTo(value) < 0) {
				node = node.next[i];
			}
			previous[i] = node;
		}
		return previous;
	}

	/**
	 * head_next   level_next                         # 注释,实际不会打印标题
	 * 67        	 	  	  	67
	 * 67        	 	  	  	67
	 * 67        	 	  	  	67
	 * 67        	 	  	  	67
	 * 19        	 	19	  	67
	 * 19        	 	19	  	67
	 * 6         	6	19	  	67
	 * 6         	6	19	  	67	82
	 * 6         	6	19	46	67	82
	 */
	public void show() {
		StringBuilder sb = new StringBuilder();
		for (int i = maxLevel; i > 0; i--) {
			// 这一层级的头指针指向谁
			Node levelHead = head.next[i - 1];
			if (levelHead != null) {
				sb.append(String.format("%-10s", levelHead.value.toString())).append("\t");
			} else {
				sb.append(StringUtils.repeat(" ", 10)).append("\t");
			}
			// 然后是每一层按层数是否出现打印value或空白填充
			Node node = head.next[0];
			while (node != null) {
				String s = node.value.toString();
				if (node.level >= i) {
					sb.append(s).append("\t");
				} else {
					sb.append(StringUtils.repeat(" ", s.length())).append("\t");
				}
				node = node.next[0];
			}
			if (i != 1) {
				sb.append("\n");
			}
		}
		System.out.println(sb.toString());
	}

	private static class Node<T extends Comparable<T>> {
		// 当前节点的值
		T value;
		// 当前节点的层数
		int level;
		// 记录当前节点在每一层的next节点
		Node<T>[] next;

		private Node(T value, int level) {
			this.value = value;
			this.level = level;
			this.next = new Node[level];
		}
	}

}

SkipListTest.java:

package alg.link;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author CC11001100
 */
public class SkipListTest {

	public static void main(String[] args) {

		SkipList<Integer> skipList = new SkipList<>();
		Random random = new Random();
		List<Integer> numList = new ArrayList<>();
		for (int i = 0; i < 30; i++) {
			int n = random.nextInt(100);
			System.out.println("now insert " + n);
			skipList.add(n);
			skipList.show();
			numList.add(n);
			System.out.println("---------------------------------------------------------------------------");

			if (Math.random() < 0.5 && !numList.isEmpty()) {
				int removeNum = numList.remove(random.nextInt(numList.size()));
				System.out.println("now remove " + removeNum);
				skipList.remove(removeNum);
				skipList.show();
				System.out.println("---------------------------------------------------------------------------");
			}
		}

	}

}

测试效果:

now insert 35
          	  	
          	  	
          	  	
          	  	
          	  	
          	  	
          	  	
35        	35	
35        	35	
35        	35	
---------------------------------------------------------------------------
now insert 56
56        	  	56	
56        	  	56	
56        	  	56	
56        	  	56	
56        	  	56	
56        	  	56	
56        	  	56	
35        	35	56	
35        	35	56	
35        	35	56	
---------------------------------------------------------------------------
now remove 35
56        	56	
56        	56	
56        	56	
56        	56	
56        	56	
56        	56	
56        	56	
56        	56	
56        	56	
56        	56	
---------------------------------------------------------------------------
now insert 45
56        	  	56	
56        	  	56	
56        	  	56	
56        	  	56	
56        	  	56	
45        	45	56	
45        	45	56	
45        	45	56	
45        	45	56	
45        	45	56	
---------------------------------------------------------------------------
now remove 56
          	  	
          	  	
          	  	
          	  	
          	  	
45        	45	
45        	45	
45        	45	
45        	45	
45        	45	
---------------------------------------------------------------------------
now insert 7
          	 	  	
          	 	  	
          	 	  	
          	 	  	
          	 	  	
45        	 	45	
45        	 	45	
45        	 	45	
45        	 	45	
7         	7	45	
---------------------------------------------------------------------------
now insert 57
          	 	  	  	
          	 	  	  	
          	 	  	  	
          	 	  	  	
          	 	  	  	
45        	 	45	  	
45        	 	45	  	
45        	 	45	  	
45        	 	45	57	
7         	7	45	57	
---------------------------------------------------------------------------
now remove 7
          	  	  	
          	  	  	
          	  	  	
          	  	  	
          	  	  	
45        	45	  	
45        	45	  	
45        	45	  	
45        	45	57	
45        	45	57	
---------------------------------------------------------------------------
now insert 75
          	  	  	  	
          	  	  	  	
          	  	  	  	
          	  	  	  	
          	  	  	  	
45        	45	  	  	
45        	45	  	  	
45        	45	  	  	
45        	45	57	  	
45        	45	57	75	
---------------------------------------------------------------------------
now remove 75
          	  	  	
          	  	  	
          	  	  	
          	  	  	
          	  	  	
45        	45	  	
45        	45	  	
45        	45	  	
45        	45	57	
45        	45	57	
---------------------------------------------------------------------------
now insert 96
          	  	  	  	
          	  	  	  	
          	  	  	  	
          	  	  	  	
          	  	  	  	
45        	45	  	  	
45        	45	  	96	
45        	45	  	96	
45        	45	57	96	
45        	45	57	96	
---------------------------------------------------------------------------
now remove 96
          	  	  	
          	  	  	
          	  	  	
          	  	  	
          	  	  	
45        	45	  	
45        	45	  	
45        	45	  	
45        	45	57	
45        	45	57	
---------------------------------------------------------------------------
now insert 40
40        	40	  	  	
40        	40	  	  	
40        	40	  	  	
40        	40	  	  	
40        	40	  	  	
40        	40	45	  	
40        	40	45	  	
40        	40	45	  	
40        	40	45	57	
40        	40	45	57	
---------------------------------------------------------------------------
now remove 40
          	  	  	
          	  	  	
          	  	  	
          	  	  	
          	  	  	
45        	45	  	
45        	45	  	
45        	45	  	
45        	45	57	
45        	45	57	
---------------------------------------------------------------------------
now insert 69
          	  	  	  	
          	  	  	  	
          	  	  	  	
          	  	  	  	
          	  	  	  	
45        	45	  	  	
45        	45	  	  	
45        	45	  	69	
45        	45	57	69	
45        	45	57	69	
---------------------------------------------------------------------------
now insert 11
          	  	  	  	  	
          	  	  	  	  	
          	  	  	  	  	
          	  	  	  	  	
          	  	  	  	  	
45        	  	45	  	  	
11        	11	45	  	  	
11        	11	45	  	69	
11        	11	45	57	69	
11        	11	45	57	69	
---------------------------------------------------------------------------
now insert 19
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
45        	  	  	45	  	  	
11        	11	  	45	  	  	
11        	11	  	45	  	69	
11        	11	19	45	57	69	
11        	11	19	45	57	69	
---------------------------------------------------------------------------
now insert 55
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
45        	  	  	45	  	  	  	
11        	11	  	45	  	  	  	
11        	11	  	45	55	  	69	
11        	11	19	45	55	57	69	
11        	11	19	45	55	57	69	
---------------------------------------------------------------------------
now remove 55
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
45        	  	  	45	  	  	
11        	11	  	45	  	  	
11        	11	  	45	  	69	
11        	11	19	45	57	69	
11        	11	19	45	57	69	
---------------------------------------------------------------------------
now insert 43
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
45        	  	  	  	45	  	  	
11        	11	  	  	45	  	  	
11        	11	  	  	45	  	69	
11        	11	19	  	45	57	69	
11        	11	19	43	45	57	69	
---------------------------------------------------------------------------
now remove 43
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
45        	  	  	45	  	  	
11        	11	  	45	  	  	
11        	11	  	45	  	69	
11        	11	19	45	57	69	
11        	11	19	45	57	69	
---------------------------------------------------------------------------
now insert 5
          	 	  	  	  	  	  	
          	 	  	  	  	  	  	
          	 	  	  	  	  	  	
          	 	  	  	  	  	  	
          	 	  	  	  	  	  	
45        	 	  	  	45	  	  	
11        	 	11	  	45	  	  	
11        	 	11	  	45	  	69	
11        	 	11	19	45	57	69	
5         	5	11	19	45	57	69	
---------------------------------------------------------------------------
now remove 5
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
45        	  	  	45	  	  	
11        	11	  	45	  	  	
11        	11	  	45	  	69	
11        	11	19	45	57	69	
11        	11	19	45	57	69	
---------------------------------------------------------------------------
now insert 92
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
45        	  	  	45	  	  	  	
11        	11	  	45	  	  	  	
11        	11	  	45	  	69	  	
11        	11	19	45	57	69	92	
11        	11	19	45	57	69	92	
---------------------------------------------------------------------------
now remove 45
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
          	  	  	  	  	  	
11        	11	  	  	  	  	
11        	11	  	  	69	  	
11        	11	19	57	69	92	
11        	11	19	57	69	92	
---------------------------------------------------------------------------
now insert 56
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
          	  	  	  	  	  	  	
11        	11	  	  	  	  	  	
11        	11	  	  	  	69	  	
11        	11	19	  	57	69	92	
11        	11	19	56	57	69	92	
---------------------------------------------------------------------------
now insert 31
          	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	
11        	11	  	  	  	  	  	  	
11        	11	  	  	  	  	69	  	
11        	11	19	31	  	57	69	92	
11        	11	19	31	56	57	69	92	
---------------------------------------------------------------------------
now insert 29
          	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	
11        	11	  	  	  	  	  	  	  	
11        	11	  	29	  	  	  	69	  	
11        	11	19	29	31	  	57	69	92	
11        	11	19	29	31	56	57	69	92	
---------------------------------------------------------------------------
now insert 96
          	  	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	  	
          	  	  	  	  	  	  	  	  	  	
11        	11	  	  	  	  	  	  	  	96	
11        	11	  	29	  	  	  	69	  	96	
11        	11	19	29	31	  	57	69	92	96	
11        	11	19	29	31	56	57	69	92	96	
---------------------------------------------------------------------------
now insert 0
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
11        	 	11	  	  	  	  	  	  	  	96	
0         	0	11	  	29	  	  	  	69	  	96	
0         	0	11	19	29	31	  	57	69	92	96	
0         	0	11	19	29	31	56	57	69	92	96	
---------------------------------------------------------------------------
now remove 19
          	 	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	
11        	 	11	  	  	  	  	  	  	96	
0         	0	11	29	  	  	  	69	  	96	
0         	0	11	29	31	  	57	69	92	96	
0         	0	11	29	31	56	57	69	92	96	
---------------------------------------------------------------------------
now insert 54
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	
11        	 	11	  	  	54	  	  	  	  	96	
0         	0	11	29	  	54	  	  	69	  	96	
0         	0	11	29	31	54	  	57	69	92	96	
0         	0	11	29	31	54	56	57	69	92	96	
---------------------------------------------------------------------------
now insert 8
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
11        	 	 	11	  	  	54	  	  	  	  	96	
0         	0	 	11	29	  	54	  	  	69	  	96	
0         	0	 	11	29	31	54	  	57	69	92	96	
0         	0	8	11	29	31	54	56	57	69	92	96	
---------------------------------------------------------------------------
now remove 56
          	 	 	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	
11        	 	 	11	  	  	54	  	  	  	96	
0         	0	 	11	29	  	54	  	69	  	96	
0         	0	 	11	29	31	54	57	69	92	96	
0         	0	8	11	29	31	54	57	69	92	96	
---------------------------------------------------------------------------
now insert 60
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
11        	 	 	11	  	  	54	  	  	  	  	96	
0         	0	 	11	29	  	54	  	  	69	  	96	
0         	0	 	11	29	31	54	57	  	69	92	96	
0         	0	8	11	29	31	54	57	60	69	92	96	
---------------------------------------------------------------------------
now insert 41
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
41        	 	 	  	  	  	41	  	  	  	  	  	  	
11        	 	 	11	  	  	41	54	  	  	  	  	96	
0         	0	 	11	29	  	41	54	  	  	69	  	96	
0         	0	 	11	29	31	41	54	57	  	69	92	96	
0         	0	8	11	29	31	41	54	57	60	69	92	96	
---------------------------------------------------------------------------
now remove 92
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
41        	 	 	  	  	  	41	  	  	  	  	  	
11        	 	 	11	  	  	41	54	  	  	  	96	
0         	0	 	11	29	  	41	54	  	  	69	96	
0         	0	 	11	29	31	41	54	57	  	69	96	
0         	0	8	11	29	31	41	54	57	60	69	96	
---------------------------------------------------------------------------
now insert 20
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
41        	 	 	  	  	  	  	41	  	  	  	  	  	
11        	 	 	11	20	  	  	41	54	  	  	  	96	
0         	0	 	11	20	29	  	41	54	  	  	69	96	
0         	0	 	11	20	29	31	41	54	57	  	69	96	
0         	0	8	11	20	29	31	41	54	57	60	69	96	
---------------------------------------------------------------------------
now remove 41
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
11        	 	 	11	20	  	  	54	  	  	  	96	
0         	0	 	11	20	29	  	54	  	  	69	96	
0         	0	 	11	20	29	31	54	57	  	69	96	
0         	0	8	11	20	29	31	54	57	60	69	96	
---------------------------------------------------------------------------
now insert 58
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
11        	 	 	11	20	  	  	54	  	  	  	  	96	
0         	0	 	11	20	29	  	54	  	58	  	69	96	
0         	0	 	11	20	29	31	54	57	58	  	69	96	
0         	0	8	11	20	29	31	54	57	58	60	69	96	
---------------------------------------------------------------------------
now remove 31
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	
11        	 	 	11	20	  	54	  	  	  	  	96	
0         	0	 	11	20	29	54	  	58	  	69	96	
0         	0	 	11	20	29	54	57	58	  	69	96	
0         	0	8	11	20	29	54	57	58	60	69	96	
---------------------------------------------------------------------------
now insert 79
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	
11        	 	 	11	20	  	54	  	  	  	  	  	96	
0         	0	 	11	20	29	54	  	58	  	69	  	96	
0         	0	 	11	20	29	54	57	58	  	69	79	96	
0         	0	8	11	20	29	54	57	58	60	69	79	96	
---------------------------------------------------------------------------
now insert 38
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
11        	 	 	11	20	  	  	54	  	  	  	  	  	96	
0         	0	 	11	20	29	  	54	  	58	  	69	  	96	
0         	0	 	11	20	29	38	54	57	58	  	69	79	96	
0         	0	8	11	20	29	38	54	57	58	60	69	79	96	
---------------------------------------------------------------------------
now insert 31
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
11        	 	 	11	20	  	  	  	54	  	  	  	  	  	96	
0         	0	 	11	20	29	  	  	54	  	58	  	69	  	96	
0         	0	 	11	20	29	31	38	54	57	58	  	69	79	96	
0         	0	8	11	20	29	31	38	54	57	58	60	69	79	96	
---------------------------------------------------------------------------
now remove 79
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	
11        	 	 	11	20	  	  	  	54	  	  	  	  	96	
0         	0	 	11	20	29	  	  	54	  	58	  	69	96	
0         	0	 	11	20	29	31	38	54	57	58	  	69	96	
0         	0	8	11	20	29	31	38	54	57	58	60	69	96	
---------------------------------------------------------------------------
now insert 78
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	 	  	  	  	  	  	  	  	  	  	  	  	  	
11        	 	 	11	20	  	  	  	54	  	  	  	  	78	96	
0         	0	 	11	20	29	  	  	54	  	58	  	69	78	96	
0         	0	 	11	20	29	31	38	54	57	58	  	69	78	96	
0         	0	8	11	20	29	31	38	54	57	58	60	69	78	96	
---------------------------------------------------------------------------
now remove 0
          	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	  	  	  	
          	 	  	  	  	  	  	  	  	  	  	  	  	  	
11        	 	11	20	  	  	  	54	  	  	  	  	78	96	
11        	 	11	20	29	  	  	54	  	58	  	69	78	96	
11        	 	11	20	29	31	38	54	57	58	  	69	78	96	
8         	8	11	20	29	31	38	54	57	58	60	69	78	96	
---------------------------------------------------------------------------

 

.

转载于:https://www.cnblogs.com/cc11001100/p/9801252.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您介绍一下使用C++设计skiplist数据结构的基本思路和实现方法。Skiplist是一种基于链表数据结构,支持高效的查找、插入和删除操作,其核心思想是通过在链表中添加多级索引(即跳表),以实现快速查找的目的。 以下是一个简单的skiplist的C++实现代码: ```c++ #include <iostream> #include <cstdlib> #include <ctime> using namespace std; const int MAX_LEVEL = 16; // 定义skiplist的最大层数 // 定义节点结构体 struct Node { int value; Node **forward; // 存储每层索引的指针 Node(int level, int value) { this->value = value; forward = new Node*[level+1]; memset(forward, 0, sizeof(Node*)*(level+1)); } ~Node() { delete[] forward; } }; // 定义skiplist类 class SkipList { public: SkipList(); ~SkipList(); void insert(int value); void remove(int value); bool contains(int value); void print(); private: int level; Node *header; double probability() { return (double) rand() / RAND_MAX; } int randomLevel() { int lvl = 0; while (probability() < 0.5 && lvl < MAX_LEVEL) { lvl++; } return lvl; } }; // 初始化skiplist SkipList::SkipList() { level = 0; header = new Node(MAX_LEVEL, 0); srand(time(NULL)); } // 销毁skiplist SkipList::~SkipList() { if (header != NULL) { delete header; } } // 插入节点 void SkipList::insert(int value) { Node *update[MAX_LEVEL+1]; memset(update, 0, sizeof(Node*)*(MAX_LEVEL+1)); Node *x = header; for (int i = level; i >= 0; i--) { while (x->forward[i] != NULL && x->forward[i]->value < value) { x = x->forward[i]; } update[i] = x; } x = x->forward[0]; if (x == NULL || x->value != value) { int lvl = randomLevel(); if (lvl > level) { for (int i = level+1; i <= lvl; i++) { update[i] = header; } level = lvl; } x = new Node(lvl, value); for (int i = 0; i <= lvl; i++) { x->forward[i] = update[i]->forward[i]; update[i]->forward[i] = x; } } } // 删除节点 void SkipList::remove(int value) { Node *update[MAX_LEVEL+1]; memset(update, 0, sizeof(Node*)*(MAX_LEVEL+1)); Node *x = header; for (int i = level; i >= 0; i--) { while (x->forward[i] != NULL && x->forward[i]->value < value) { x = x->forward[i]; } update[i] = x; } x = x->forward[0]; if (x->value == value) { for (int i = 0; i <= level; i++) { if (update[i]->forward[i] != x) { break; } update[i]->forward[i] = x->forward[i]; } delete x; while (level > 0 && header->forward[level] == NULL) { level--; } } } // 查找节点 bool SkipList::contains(int value) { Node *x = header; for (int i = level; i >= 0; i--) { while (x->forward[i] != NULL && x->forward[i]->value < value) { x = x->forward[i]; } } x = x->forward[0]; return x != NULL && x->value == value; } // 打印skiplist void SkipList::print() { for (int i = 0; i <= level; i++) { Node *x = header->forward[i]; cout << "Level " << i << ": "; while (x != NULL) { cout << x->value << " "; x = x->forward[i]; } cout << endl; } } int main() { SkipList sl; sl.insert(1); sl.insert(2); sl.insert(3); sl.insert(5); sl.insert(4); sl.print(); sl.remove(3); sl.print(); cout << sl.contains(3) << endl; cout << sl.contains(5) << endl; return 0; } ``` 这里我们定义了一个Node结构体,用于存储skiplist中的节点信息,其中包括节点的值和每层索引的指针。然后我们定义了一个SkipList类,实现了插入、删除、查找和打印等操作。在插入操作中,我们使用随机数生成每个节点的层数,以实现跳表的效果;在删除操作中,我们首先查找到要删除的节点,然后按照相应的层数更新每层索引的指针,最后删除该节点即可。在查找操作中,我们从最高层逐层向下查找,直到找到目标节点或者遍历完整个skiplist。 希望这个简单的skiplist C++实现代码可以帮助您更好地理解和使用该数据结构

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值