Skip List(跳跃表)与ConcurrentSkipListMap

来源:互联网 发布:淘宝品质退款包括哪些 编辑:程序博客网 时间:2024/06/05 06:07


学习来源:skip list
【算法导论33】跳跃表(Skip list)原理与java实现

Skip List(跳跃表)原理详解与实现


Skip List是一种随机化的数据结构,基于并联的链表,有多级的索引可以跳过大段的区间,其效率可比拟于二叉查找树(log n)。基本上,跳跃列表是对有序的链表增加上附加的前进链接,增加是以随机化的方式进行的,所以在列表中的查找可以快速的跳过部分列表(因此得名)。Skip List可以很好解决有序链表查找特定值的困难。使用skip list统计比指定的数值小的项的个数的时间复杂度是log(n)级的,节点中的数值发生变化时,更新的代价也是log(n)级。

Skip list的性质
(1) 由很多层结构组成,level是通过一定的概率随机产生的。
(2) 每一层都是一个有序的链表,默认是升序,也可以根据创建映射时所提供的Comparator进行排序,具体取决于使用的构造方法。
(3) 最底层(Level 1)的链表包含所有元素。
(4) 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现。
(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

以下的图片是从上面学习的三个连接中获取过来:




ConcurrentSkipListMap提供了一种线程安全的并发访问的排序映射表。内部是SkipList(跳表)结构实现,在理论上能够在O(log(n))时间内完成查找、插入、删除操作。

查找和插入的jdk源码:

private V doPut(K key, V value, boolean onlyIfAbsent) {        Node<K,V> z;             // added node        if (key == null)            throw new NullPointerException();        Comparator<? super K> cmp = comparator;        outer: for (;;) {            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {                if (n != null) {                    Object v; int c;                    Node<K,V> f = n.next;                    if (n != b.next)               // inconsistent read                        break;                    if ((v = n.value) == null) {   // n is deleted                        n.helpDelete(b, f);                        break;                    }                    if (b.value == null || v == n) // b is deleted                        break;                    if ((c = cpr(cmp, key, n.key)) > 0) {                        b = n;                        n = f;                        continue;                    }                    if (c == 0) {                        if (onlyIfAbsent || n.casValue(v, value)) {                            @SuppressWarnings("unchecked") V vv = (V)v;                            return vv;                        }                        break; // restart if lost race to replace value                    }                    // else c < 0; fall through                }                z = new Node<K,V>(key, value, n);                if (!b.casNext(n, z))                    break;         // restart if lost race to append to b                break outer;            }        }        int rnd = ThreadLocalRandom.nextSecondarySeed();        if ((rnd & 0x80000001) == 0) { // test highest and lowest bits            int level = 1, max;            while (((rnd >>>= 1) & 1) != 0)                ++level;            Index<K,V> idx = null;            HeadIndex<K,V> h = head;            if (level <= (max = h.level)) {                for (int i = 1; i <= level; ++i)                    idx = new Index<K,V>(z, idx, null);            }            else { // try to grow by one level                level = max + 1; // hold in array and later pick the one to use                @SuppressWarnings("unchecked")Index<K,V>[] idxs =                    (Index<K,V>[])new Index<?,?>[level+1];                for (int i = 1; i <= level; ++i)                    idxs[i] = idx = new Index<K,V>(z, idx, null);                for (;;) {                    h = head;                    int oldLevel = h.level;                    if (level <= oldLevel) // lost race to add level                        break;                    HeadIndex<K,V> newh = h;                    Node<K,V> oldbase = h.node;                    for (int j = oldLevel+1; j <= level; ++j)                        newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);                    if (casHead(h, newh)) {                        h = newh;                        idx = idxs[level = oldLevel];                        break;                    }                }            }            // find insertion points and splice in            splice: for (int insertionLevel = level;;) {                int j = h.level;                for (Index<K,V> q = h, r = q.right, t = idx;;) {                    if (q == null || t == null)                        break splice;                    if (r != null) {                        Node<K,V> n = r.node;                        // compare before deletion check avoids needing recheck                        int c = cpr(cmp, key, n.key);                        if (n.value == null) {                            if (!q.unlink(r))                                break;                            r = q.right;                            continue;                        }                        if (c > 0) {                            q = r;                            r = r.right;                            continue;                        }                    }                    if (j == insertionLevel) {                        if (!q.link(r, t))                            break; // restart                        if (t.node.value == null) {                            findNode(key);                            break splice;                        }                        if (--insertionLevel == 0)                            break splice;                    }                    if (--j >= insertionLevel && j < level)                        t = t.down;                    q = q.down;                    r = q.right;                }            }        }        return null;    }
private V doGet(Object key) {        if (key == null)            throw new NullPointerException();        Comparator<? super K> cmp = comparator;        outer: for (;;) {            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {                Object v; int c;                if (n == null)                    break outer;                Node<K,V> f = n.next;                if (n != b.next)                // inconsistent read                    break;                if ((v = n.value) == null) {    // n is deleted                    n.helpDelete(b, f);                    break;                }                if (b.value == null || v == n)  // b is deleted                    break;                if ((c = cpr(cmp, key, n.key)) == 0) {                    @SuppressWarnings("unchecked") V vv = (V)v;                    return vv;                }                if (c < 0)                    break outer;                b = n;                n = f;            }        }        return null;    }
删除的源码:

final V doRemove(Object key, Object value) {        if (key == null)            throw new NullPointerException();        Comparator<? super K> cmp = comparator;        outer: for (;;) {            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {                Object v; int c;                if (n == null)                    break outer;                Node<K,V> f = n.next;                if (n != b.next)                    // inconsistent read                    break;                if ((v = n.value) == null) {        // n is deleted                    n.helpDelete(b, f);                    break;                }                if (b.value == null || v == n)      // b is deleted                    break;                if ((c = cpr(cmp, key, n.key)) < 0)                    break outer;                if (c > 0) {                    b = n;                    n = f;                    continue;                }                if (value != null && !value.equals(v))                    break outer;                if (!n.casValue(v, null))                    break;                if (!n.appendMarker(f) || !b.casNext(n, f))                    findNode(key);                  // retry via findNode                else {                    findPredecessor(key, cmp);      // clean index                    if (head.right == null)                        tryReduceLevel();                }                @SuppressWarnings("unchecked") V vv = (V)v;                return vv;            }        }        return null;    }




原创粉丝点击