跳跃表-随机化数据结构

Skip list(跳表)是一种可以代替平衡树的数据结构

参考
http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Map/skip-list-impl.html

http://www.acmerblog.com/skip-list-impl-java-5773.html

Skip list的性质

(1) 由很多层结构组成,level是通过一定的概率随机产生的。
(2) 每一层都是一个有序的链表,默认是升序
(3) 最底层(Level 1)的链表包含所有元素。
(4) 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现。
(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

这里写图片描述

Java代码实现:

  1. SkipListEntry.java , 这是跳跃表中存储的每个元素实体类,包含 上下左右 四个指针。
package skiplist;

public class SkipListEntry {
    public String key;
    public Integer value;

    public int pos;

    public SkipListEntry up, down, left, right;

    public static String negInf = new String("-oo");
    public static String posInf = new String("+oo");

    public SkipListEntry(String k, Integer v){
        key = k;
        value = v;

        up = down = left = right = null;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public Integer getValue() {
        return value;
    }

    public Integer setValue(Integer value) {
        Integer OldValue = value;
        this.value = value;

        return OldValue;
    }

    @Override
    public boolean equals(Object obj) {
        SkipListEntry ent;
        try{
            ent = (SkipListEntry) obj;
        } catch (ClassCastException ex){
            return false;
        }
        return (ent.getKey() == key) && (ent.getValue() == value);
    }

    @Override
    public String toString() {
        return "SkipListEntry [key=" + key + ", value=" + value + "]";
    }








}

2 SkipList.java, 跳跃表类,包含算法的实现。 head 和 tail 分别是 顶层的头和尾。

package skiplist;

import java.util.Random;

public class SkipList {
    public SkipListEntry head;
    public SkipListEntry tail;

    public int n; // 跳跃表中元素的个数
    public int h; // 跳跃表的高度

    public Random r;

    public SkipList()
    {
        SkipListEntry p1,p2;

        p1 = new SkipListEntry(SkipListEntry.negInf, null);
        p2 = new SkipListEntry(SkipListEntry.posInf, null);

        head = p1;
        tail = p2;

        p1.right = p2;
        p2.left = p1;

        n = 0;
        h = 0;
        r = new Random();



    }

    /** 返回包含元素的个数  */
    public int size()
    {
        return n;
    }

    /** 跳跃表是否为空 */
    public  boolean isEmpty()
    {
        return (n == 0);
    }

    /** 在最下面一层, 找到要插入的位置前面的哪个key*/
    public SkipListEntry findEntry(String k)
    {
        SkipListEntry p;
        p = head;

        while(true){
            while( p.right.key != SkipListEntry.posInf && 
                    p.right.key.compareTo(k) <= 0){
                p = p.right;

            }
            if(p.down != null){
                p = p.down;
            }else{
                break;
            }
        }

        return p;
    }

    /** 返回和key绑定的值 */
    public Integer get(String k)
    {
        SkipListEntry p;

        p = findEntry(k);
        if (k.equals(p.getKey())){
            return p.value;
        }else{
            return null;
        }

    }

    /** 放一个key-value到跳跃表中 ,替换原有的并返回*/
    public Integer put(String k , Integer v){
        SkipListEntry p, q;
        int i;
        /** 找到key 就返回原值, 将新值替换进链表 */
        p = findEntry(k);
        if(k.equals(p.getKey())){
            Integer old = p.value;
            p.value = v;
            return old;
        }

        /** 如果没有找到新值,就新建一个 */
        q = new SkipListEntry(k, v);

        q.left = p;
        q.right = p.right;
        p.right.left = q;
        p.right = q;

        i = 0;
        while(r.nextDouble() < 0.5){
            //如果超出了高度,需要重新建一个顶层
            if (i >= h) {
                SkipListEntry p1, p2;

                h = h + 1;
                p1 = new SkipListEntry(SkipListEntry.negInf, null);
                p2 = new SkipListEntry(SkipListEntry.posInf, null);

                p1.right = p2;
                p1.down = head;

                p2.left = p1;
                p2.down = tail;

                head.up = p1;
                tail.up = p2;

                head = p1;
                tail = p2;
            }

            // 将p移动到 最左边
            while(p.up == null){
                p = p.left;
            }

            p = p.up;

            SkipListEntry e;

            e = new SkipListEntry(k, null); 
            e.left = p;
            e.right = p.right;
            e.down = q;

            p.right.left = e;
            p.right = e;
            q.up = e;

            q = e; // q 进行下一层迭代
            i = i + 1; // 当前层 +1

        }

        n = n + 1;

        return (null);

    }


    public Integer remove(String key) {
        return (null);
    }

    public void printHorizontal() {
        String s = "";
        int i;
        SkipListEntry p;

        p = head;

        while (p.down != null) {
            p = p.down;
        }

        i = 0;
        while (p != null) {
            p.pos = i++;
            p = p.right;
        }

        p = head;
        while (p != null) {
            s = getOneRow(p);
            System.out.println(s);

            p = p.down;
        }
    }

    //用了打印测试
    public String getOneRow(SkipListEntry p) {
        String s;
        int a, b, i;

        a = 0;

        s = "" + p.key;
        p = p.right;

        while (p != null) {
            SkipListEntry q;

            q = p;
            while (q.down != null)
                q = q.down;
            b = q.pos;

            s = s + " <-";

            for (i = a + 1; i < b; i++)
                s = s + "--------";

            s = s + "> " + p.key;

            a = b;

            p = p.right;
        }

        return (s);
    }

    //用了打印测试
    public void printVertical() {
        String s = "";
        SkipListEntry p;
        p = head;
        while (p.down != null)
            p = p.down;

        while (p != null) {
            s = getOneColumn(p);
            System.out.println(s);

            p = p.right;
        }
    }
    //用了打印测试
    public String getOneColumn(SkipListEntry p) {
        String s = "";
        while (p != null) {
            s = s + " " + p.key;
            p = p.up;
        }
        return (s);
    }
}

3 测试类,Test.java

package skiplist;

public class Test {
    public static void main(String[] args) {
        SkipList S = new SkipList();

        S.printHorizontal();
        System.out.println("------");
        // S.printVertical();
        // System.out.println("======");

        S.put("ABC", 123);
        S.printHorizontal();
        System.out.println("------");
        // S.printVertical();
         //System.out.println("======");

        S.put("DEF", 123);
        S.printHorizontal();
        System.out.println("------");
        // S.printVertical();
        // System.out.println("======");

        S.put("KLM", 123);
        S.printHorizontal();
        System.out.println("------");
        // S.printVertical();
        // System.out.println("======");

        S.put("HIJ", 123);
        S.printHorizontal();
        System.out.println("------");
        // S.printVertical();
        // System.out.println("======");

        S.put("GHJ", 123);
        S.printHorizontal();
        System.out.println("------");
        // S.printVertical();
        // System.out.println("======");

        S.put("AAA", 123);
        S.printHorizontal();
        System.out.println("------");
        // S.printVertical();
        // System.out.println("======");

    }
}

输出结果

-oo <-> +oo
------
-oo <-> ABC <-> +oo
------
-oo <-> ABC <-> DEF <-> +oo
------
-oo <-----------------> KLM <-> +oo
-oo <-> ABC <-> DEF <-> KLM <-> +oo
------
-oo <-----------------> HIJ <---------> +oo
-oo <-----------------> HIJ <---------> +oo
-oo <-----------------> HIJ <---------> +oo
-oo <-----------------> HIJ <-> KLM <-> +oo
-oo <-> ABC <-> DEF <-> HIJ <-> KLM <-> +oo
------
-oo <-------------------------> HIJ <---------> +oo
-oo <-------------------------> HIJ <---------> +oo
-oo <-----------------> GHJ <-> HIJ <---------> +oo
-oo <-----------------> GHJ <-> HIJ <-> KLM <-> +oo
-oo <-> ABC <-> DEF <-> GHJ <-> HIJ <-> KLM <-> +oo
------
-oo <---------------------------------> HIJ <---------> +oo
-oo <---------------------------------> HIJ <---------> +oo
-oo <-------------------------> GHJ <-> HIJ <---------> +oo
-oo <-------------------------> GHJ <-> HIJ <-> KLM <-> +oo
-oo <-> AAA <-> ABC <-> DEF <-> GHJ <-> HIJ <-> KLM <-> +oo
------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值