跳表(Java 实现)

public abstract class SkipListUtil {

    /**
     * 按照规则生成随机层数,层数越大,概率越低
     *
     * @return
     */
    public static int generateRandomLevel() {
        int result = SkipListConfig.MIN_LEVEL;
        Random random = new Random();
        while (random.nextInt(SkipListConfig.MAX_LEVEL) < SkipListConfig.MAX_LEVEL * SkipListConfig.P && result < SkipListConfig.MAX_LEVEL) {
            result++;
        }
        return result;
    }

    /**
     * 计算跳跃表的平均高度
     *
     * @param skipList
     * @param <T>
     * @return
     */
    public static <T> double computeAvgLevel(SkipList<T> skipList) {
        double result = 0;
        for (SkipListNode<T> skipListNode : skipList) {
            result += skipListNode.getLevels().length;
        }
        return result / skipList.length;
    }
}

public abstract class SkipListConfig {
    /**
     * 每一层节点提升为上层节点的概率,概率越大,层数越高
     */
    public static final double P = 0.5;
    public static final int MAX_LEVEL = 64;
    public static final int MIN_LEVEL = 1;
}
/**
 * 跳表节点
 */
@Data
@Accessors(chain = true)
@EqualsAndHashCode
public class SkipListNode<T> implements Comparable<SkipListNode<T>> {
    /**
     * 存储数据
     */
    private T element;

    /**
     * 排序的分值,约定0为最小分数
     */
    private double score;

    /**
     * 后退指针(指向前一个节点)
     * <p>
     * 头结点指向null
     */
    private SkipListNode<T> prev;

    /**
     * 每个节点的数组长度不一样,随机生成一个层级
     * <p>
     * 例如,层级为8,代表该节点出现在8个层级上
     * <p>
     * 值越大,出现概率越低
     */
    private SkipListLevel<T>[] levels;

    @Override
    public int compareTo(SkipListNode<T> other) {
        return Double.compare(this.score, other.score);
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class SkipListLevel<T> {
        /**
         * 同一层的下一个结点
         */
        private SkipListNode<T> next;

        /**
         * 当前结点与同层的next节点之间的距离
         */
        private int span;
    }


    public SkipListNode(int levelNum) {
        this.element = null;
        this.score = 0;
        prev = null;
        levels = new SkipListLevel[levelNum];
        for (int i = 0; i < levels.length; i++) {
            levels[i] = new SkipListLevel<>(null, 0);
        }
    }

    public SkipListNode() {
        this.element = null;
        score = 0;
        prev = null;
        levels = new SkipListLevel[SkipListUtil.generateRandomLevel()];
        for (int i = 0; i < levels.length; i++) {
            levels[i] = new SkipListLevel<>(null, 0);
        }
    }

    @Override
    public String toString() {
        return "SkipListNode{" +
                "element=" + element +
                ", score=" + score +
                ", prev=" + prev +
                ", levels=" + levels.length +
                '}';
    }
}
public class SkipList<T> implements Iterable<SkipListNode<T>> {
    /**
     * 头结点
     */
    SkipListNode<T> head;

    /**
     * 尾结点
     */
    SkipListNode<T> tail;

    /**
     * 除头结点之外的节点个数
     */
    int length;

    /**
     * 跳跃表的高度
     */
    int level;


    public SkipList() {
        // 初始化头结点
        head = new SkipListNode<T>(SkipListConfig.MAX_LEVEL);
        tail = null;
        this.length = 0;
        this.level = 1;
    }

    /**
     * 查询节点所在的位置(有序链表)
     * <p>
     * 1. 查询上层节点(每一层都是有序链表)
     * <p>
     * 2. 上层发现大于或为null,查找下一层
     *
     * @param node
     * @return
     */
    public SkipListNode<T>[] find(SkipListNode<T> node) {
        SkipListNode<T>[] update = new SkipListNode[node.getLevels().length];

        SkipListNode<T> pNode = this.head;
        SkipListNode<T> nextNode;

        // 当插入节点层数为1时,会退化,因此需要进行优化
        for (int i = node.getLevels().length - 1; i >= 0; i--) {
            while ((nextNode = pNode.getLevels()[i].getNext()) != null && nextNode.compareTo(node) < 0) {
                pNode = nextNode;
            }
            update[i] = pNode;
        }
        // 返回每一个层级插入位置的前一个节点
        return update;
    }


    /**
     * 插入节点
     * <p>
     * 1. 查询插入位置
     * <p>
     * 2. 调整跳跃表高度
     * <p>
     * 3. 插入节点
     * <p>
     * 4. 调整prev指针
     *
     * @param node 待插入节点
     */
    public void add(SkipListNode<T> node) {
        if (this.length++ == 0) {
            this.tail = node;
            SkipListNode.SkipListLevel<T>[] headLevels = this.head.getLevels();
            for (int i = 0; i < node.getLevels().length; i++) {
                headLevels[i].setNext(node);
            }
            return;
        }

        SkipListNode.SkipListLevel<T>[] levels = node.getLevels();
        // 更新跳表的最大层数
        this.level = Math.max(this.level, levels.length);
        // 查询前置节点
        SkipListNode<T>[] preNodes = find(node);

        for (int i = 0; i < levels.length; i++) {
            SkipListNode.SkipListLevel<T> preNodeLevel = preNodes[i].getLevels()[i];
            SkipListNode<T> nextNode = preNodeLevel.getNext();

            // 当前插入节点连接下一个结点
            levels[i].setNext(nextNode);
            // nextNode连接当前结点
            nextNode.setPrev(node);
            // 前置节点连接当前插入节点
            preNodeLevel.setNext(node);
        }

        // 如果当前结点插入在尾结点之后,那么当前插入的节点就是新的尾结点
        SkipListNode<T> preNode = preNodes[0];
        if (preNode == tail) {
            tail = node;
        }
        node.setPrev(preNode);


    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        for (SkipListNode<T> skipListNode : this) {
            builder.append(skipListNode.toString()).append("->");
        }

        return builder.toString();
    }

    /**
     * 自定义迭代器
     */
    private class SkipListIterator implements Iterator<SkipListNode<T>> {
        SkipListNode<T> prevNode;
        int cursor;

        public SkipListIterator() {
            this.prevNode = tail;
            this.cursor = length - 1;
        }

        @Override
        public boolean hasNext() {
            return cursor >= 0;
        }

        @Override
        public SkipListNode<T> next() {
            SkipListNode<T> result = prevNode;
            prevNode = prevNode.getPrev();
            cursor--;
            return result;
        }
    }

    @Override
    public Iterator<SkipListNode<T>> iterator() {
        return new SkipListIterator();
    }
}

测试代码

public class MainDemo {
    public static void main(String[] args) {
        SkipList<String> skipList = new SkipList<>();

        SkipListNode<String> skipListNodeD = new SkipListNode<>(4);
        skipListNodeD.setElement("4");
        skipListNodeD.setScore(4);
        skipList.add(skipListNodeD);

        SkipListNode<String> skipListNodeA = new SkipListNode<>(1);
        skipListNodeA.setElement("2");
        skipListNodeA.setScore(2);
        skipList.add(skipListNodeA);


        SkipListNode<String> skipListNodeB = new SkipListNode<>(1);
        skipListNodeB.setElement("1");
        skipListNodeB.setScore(1);
        skipList.add(skipListNodeB);

        SkipListNode<String> skipListNodeC = new SkipListNode<>(1);
        skipListNodeC.setElement("3");
        skipListNodeC.setScore(3);
        skipList.add(skipListNodeC);



        System.out.println(skipList);
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值