Hands on implementation of a jump table

Time:2021-12-29

preface

This paper mainly introduces the characteristics of jump table and how to implement a jump table by yourself.

Skip list

Jump table is a typical space for time model. The underlying data structure is an ordered single linked tableMultilayer index, the binary search method is implemented to query data. Multi tier index not only improves the query efficiency, but also makes the time complexity of insertion and deletion less thanO(logn)。 In addition, the spatial complexity of multi-layer index isO(n)

Jump table is a randomized dynamic data structure. It introduces multi-layer index, so it is necessary to maintain the balance between index and original data during operation. Unlike red and black treesAVLThe tree maintains the balance between the left and right subtrees by left and right rotation, and the jump table uses random functions to randomly the number of index layers to be constructed, so as to maintain the balance.

The performance of jump table is similar to that of red black treeAVLThe tree is similar, but the implementation of jump table is relatively simple. At present, it is inRedisLevelDBIt is used on both.

The above describes the characteristics of table hopping, and the specific code is pasted below:

package main.java.skiplist;

import java.util.Random;

/**
 *Traditional skip table
 * 1.  Element cannot be repeated
 * 2.  Random number of index layers
 */
public class SkipList {
    //Random tool for random index layers
    private final Random random;
    public final int MAX_LEVEL = 16;
    //Current layers
    public int level;
    public SkipNode head;

    public SkipList() {
        random = new Random();
        head = new SkipNode(Integer.MIN_VALUE, MAX_LEVEL);
        level = 1;
    }

    /**
     *Returns the number of randomly built index layers
     * @return [1, MAX_LEVEL]
     */
    private int randomLevel() {
        int n = 1;
        for (int i = 1; i < MAX_LEVEL; i++) {
            if (random.nextInt(2) == 1)
                n++;
        }
        return n;
    }

    /**
     *Query nodes according to val
     *@ param Val node value
     *@ return if the value does not exist, null is returned; Otherwise, the query node is returned
     */
    public SkipNode find(int val) {
        SkipNode p = head;
        for (int i=level-1; i>=0; i--) {
            while (p.next[i] != null && p.next[i].value < val) {
                p = p.next[i];
            }
        }
        return p.next[0] != null && p.next[0].value == val ? p.next[0] : null;
    }

    /**
     *Delete nodes according to val
     *@ param Val node value
     *@ return if the value does not exist, null is returned; Otherwise, the deleted node will be returned
     */
    public SkipNode delete(int val) {
        SkipNode[] prev = new SkipNode[MAX_LEVEL];

        SkipNode p = head;
        for (int i=level-1; i>=0; i--) {
            while (p.next[i] != null && p.next[i].value < val) {
                p = p.next[i];
            }
            prev[i] = p;
        }
        if (p.next[0] != null && p.next[0].value == val) {
            SkipNode res = p.next[0];
            for (int i = 0; i < res.level; i++) {
                prev[i].next[i] = prev[i].next[i].next[i];
            }
            return res;
        }
        return null;
    }

    /**
     *Insert node
     *@ param Val node value
     */
    public void insert(int val) {
        int newLevel = randomLevel();
        SkipNode newNode = new SkipNode(val, newLevel);
        SkipNode[] prev = new SkipNode[newLevel];

        SkipNode p = head;
        for (int i=newLevel-1; i>=0; i--) {
            while (p.next[i] != null && p.next[i].value < val) {
                p = p.next[i];
            }
            prev[i] = p;
        }
        for (int i=0; i level)
            level = newLevel;
    }

    public void show() {
        StringBuffer sb = new StringBuffer();
        int col = 0;
        SkipNode p = head.next[0];
        while (p != null) {
            p.setSpan(col);
            col++;
            p = p.next[0];
        }
        SkipNode[] arr = head.next;
        for (int i=level-1; i>=0; i--) {
            sb. Append (string. Format ("layer% 2D:", I));
            p = arr[i];
            for (int j = 0; j < col; j++) {
                if (p != null && p.span == j) {
                    sb.append(p.value);
                    p = p.next[i];
                }else {
                    sb.append(" ");
                }
                if (j != col-1)
                    sb.append(" -> ");
            }
            sb.append("\n");
        }
        System.out.println(sb.toString());
    }

    public static final class SkipNode {
        int level;
        int value;
        int span; //  Auxiliary printing
        SkipNode[] next;

        public SkipNode(int v, int level) {
            value = v;
            this.level = level;
            next = new SkipNode[level];
        }

        @Override
        public String toString() {
            return "SkipNode{" +
                    "level=" + level +
                    ", value=" + value +
                    ", span=" + span +
                    '}';
        }

        public void setSpan(int span) {
            this.span = span;
        }
    }
}

Effect screenshot

raw data:

image

Query and delete:

image

reference resources