|NO.Z.00044|——————————|BigDataEnd|——|Hadoop&ElasticSearch.V44|——|ELK.v44|原理剖析|数据结构.V2|

一、调表实现:编程实现
### --- 调表实现:编程实现

package com.yanqi.es;

import java.util.Comparator;
//存储kv类型数据

public class SkipList<K, V> {
    //头节点
    private Node<K, V> first;
    //最高层数
    private static final int MAX_LEVEL = 10;
    //当前跳表有效层数
    private int realLeve;
    //新节点随机的层数的概率
    private static final double f = 0.25;
    //容量
    int size;
    //skiplist中key必须具有可比较性
    private Comparator<K> comparator;
    //构造器
    public SkipList(Comparator<K> comparator) {
        this.first = new Node(null, null, MAX_LEVEL);
        this.comparator = comparator;
    }
    public SkipList() { 
        this(null);//不传比较器,就是默认你的key一定实现了java的compareble接口
    }
    //比较方法
    int compare(K k1, K k2) { 
        int cmp = comparator == null ? ((Comparable) k1).compareTo(k2) : 
                comparator.compare(k1, k2);
        return cmp;
    }
    int getSize() {
        return 0;
    }
    //是否为空
    boolean isEmpty() {
        return size == 0;
    }
    //校验key
    public void checkKeyIsNull(K key) { 
        if (key == null) { 
            throw new IllegalArgumentException("key should not be null...");
        }
    }
    //增删查
    V get(K key) {
        /**
         * - 从顶层链表的首元素开始,从左往右搜索,直至找到一个大于或等于目标的元素,或者到达当前层链表的尾部
         * - 如果该元素等于目标元素,则表明该元素已被找到
         * - 如果该元素大于目标元素或已到达链表的尾部,则退回到当前层的前一个元素,然后转入下一层进行搜索
         */
        
        checkKeyIsNull(key);
        //获取头节点
        Node<K, V> node = first;
        for (int i = realLeve - 1; i >= 0; i--) {
            //查找的key大于遇到的节点的key一直向右
            int cmp = -1;
            while (node.nexts[i] != null && (cmp = compare(key, node.nexts[i].key)) > 0) {
                //一直向右
                node = node.nexts[i]; 
            }
            //说明查找的key小于等于node.nexts[i].key
            if (cmp == 0) {
                //找到了节点
                return node.nexts[i].value; 
            } 
        }
        //跳表中不存在这个key
        return null; 
    }
    //根据key查找value
    V put(K key, V value) { checkKeyIsNull(key);
    //确定新节点的位置与get过程类似
        Node<K, V> node = first;
        //初始化一个装新节点前面节点的数组,数组长度:有效层数
        final Node<K, V>[] prevNodes = new Node[realLeve];
        for (int i = realLeve - 1; i >= 0; i--) {
            //查找的key大于遇到的节点的key一直向右
            int cmp = -1;
            while (node.nexts[i] != null && (cmp = compare(key, node.nexts[i].key)) > 0) {
                //一直向右
                node = node.nexts[i];
            }
            //说明查找的key小于等于node.nexts[i].key
            if (cmp == 0) {//更新
                // 找到了节点
                // 要覆盖的节点是node.nexts[i]
                final V oldValue = node.nexts[i].value;
                node.nexts[i].value = value;
                return oldValue; 
            }
            //这里就是向下一层的动作
            prevNodes[i] = node; 
        }
        //确定插入的位置,就是上述循环之后的node节点,就是在node节点之后插入新节点;
        // 获取到新节点的层数
        int newLeve = getNewNodeLeve();
        Node<K, V> newNode = new Node<>(key, value, newLeve);//新节点的层数如何确定呢?随机
        // 新节点前面的节点的特征:都有向下一层的动作
        for (int i = 0; i < newLeve; i++) {
            //如果新节点层数大于realLevel
            if (i >= realLeve) { 
                first.nexts[i] = newNode; 
            } else { 
                newNode.nexts[i] = prevNodes[i].nexts[i];
                prevNodes[i].nexts[i] = newNode; 
            } 
        }
        //容量增加
        size++;
        //跳表有效层数更新
        realLeve = Math.max(realLeve, newLeve);
        return null; 
    }
    private int getNewNodeLeve() {
        int level = 1;
        if (Math.random() < f && level < MAX_LEVEL) {
            level++;
        }
        return level;
    }
    V remove(K key) { checkKeyIsNull(key);
    //确定删除节点的位置
        Node<K, V> node = first;
        //初始化一个装目标节点前面节点的数组,数组长度:有效层数
        final Node<K, V>[] prevNodes = new Node[realLeve];
        boolean flag = false;
        for (int i = realLeve - 1; i >= 0; i--) {
            //查找的key大于遇到的节点的key一直向右
            int cmp = -1;
            while (node.nexts[i] != null && (cmp = compare(key, node.nexts[i].key)) > 0) {
                //一直向右
                node = node.nexts[i];
            }
            if (cmp == 0) {
                //找到了删除的key
                flag = true;
            }
            //这里就是向下一层的动作
            prevNodes[i] = node;
        }
        //判断flag标识
        if (!flag) {
            //没有找到目标元素
            return null;
        }
        //找到了删除的元素,执行删除动作
        // 确定要删除的节点
        Node<K, V> deleteNode = node.nexts[0];
        //与添加类似
        for (int i = 0; i < deleteNode.nexts.length; i++) {
            prevNodes[i].nexts[i] = deleteNode.nexts[i];
        }
        //关于跳表的有效层数进行更新,删除的目标节点有可能是跳表中最高层,需要修改跳表的有效层数
        int finalLeve = realLeve;
        while (--finalLeve >= 0 && first.nexts[finalLeve] == null) {
            //有效层数要减1
            realLeve = finalLeve;
        }
        return deleteNode.value;
    }
    private static class Node<K, V> {
        K key;
        V value;
        Node<K, V>[] nexts; //向后多个节点的引用
        //构造器
        public Node(K key, V value, int level) {
            this.key = key;
            this.value = value;
            this.nexts = new Node[level];
        }
        @Override
        public String toString() {
            return key + ":" + value + "_" + nexts.length;
        }
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("一共" + realLeve + "层").append("\n");
        for (int i = realLeve - 1; i >= 0; i--) {
            Node<K, V> node = first;
            while (node.nexts[i] != null) {
                sb.append(node.nexts[i]);
                sb.append(" ");
                node = node.nexts[i];
            }
            sb.append("\n");
        }
        return sb.toString();
    }
} 
### --- 编程实现测试类

package com.yanqi.es;

public class SkipListTest {
    public static void main(String[] args) {
        final SkipList<Integer, String> list = new SkipList<>();
        list.put(1,"aaa" );
        list.put(2,"bbb" );
        // System.out.println(list);
        //
        System.out.println(list.get(1));
        list.remove(1);
        System.out.println(list);
    }
}
### --- 编译打印

D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=58581:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.80000.Hadoop.project\elasticsearch\target\classes;C:\Users\Administrator\.m2\repository\org\elasticsearch\client\elasticsearch-rest-high-level-client\7.9.0\elasticsearch-rest-high-level-client-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\client\elasticsearch-rest-client\7.9.0\elasticsearch-rest-client-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpclient\4.5.10\httpclient-4.5.10.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpcore\4.4.12\httpcore-4.4.12.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpasyncclient\4.1.4\httpasyncclient-4.1.4.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpcore-nio\4.4.12\httpcore-nio-4.4.12.jar;C:\Users\Administrator\.m2\repository\commons-codec\commons-codec\1.11\commons-codec-1.11.jar;C:\Users\Administrator\.m2\repository\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\plugin\mapper-extras-client\7.9.0\mapper-extras-client-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\plugin\parent-join-client\7.9.0\parent-join-client-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\plugin\aggs-matrix-stats-client\7.9.0\aggs-matrix-stats-client-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\plugin\rank-eval-client\7.9.0\rank-eval-client-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\plugin\lang-mustache-client\7.9.0\lang-mustache-client-7.9.0.jar;C:\Users\Administrator\.m2\repository\com\github\spullara\mustache\java\compiler\0.9.6\compiler-0.9.6.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\elasticsearch\7.9.0\elasticsearch-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\elasticsearch-core\7.9.0\elasticsearch-core-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\elasticsearch-secure-sm\7.9.0\elasticsearch-secure-sm-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\elasticsearch-x-content\7.9.0\elasticsearch-x-content-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;C:\Users\Administrator\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.10.4\jackson-core-2.10.4.jar;C:\Users\Administrator\.m2\repository\com\fasterxml\jackson\dataformat\jackson-dataformat-smile\2.10.4\jackson-dataformat-smile-2.10.4.jar;C:\Users\Administrator\.m2\repository\com\fasterxml\jackson\dataformat\jackson-dataformat-yaml\2.10.4\jackson-dataformat-yaml-2.10.4.jar;C:\Users\Administrator\.m2\repository\com\fasterxml\jackson\dataformat\jackson-dataformat-cbor\2.10.4\jackson-dataformat-cbor-2.10.4.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\elasticsearch-geo\7.9.0\elasticsearch-geo-7.9.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-core\8.6.0\lucene-core-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-analyzers-common\8.6.0\lucene-analyzers-common-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-backward-codecs\8.6.0\lucene-backward-codecs-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-grouping\8.6.0\lucene-grouping-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-highlighter\8.6.0\lucene-highlighter-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-join\8.6.0\lucene-join-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-memory\8.6.0\lucene-memory-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-misc\8.6.0\lucene-misc-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-queries\8.6.0\lucene-queries-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-queryparser\8.6.0\lucene-queryparser-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-sandbox\8.6.0\lucene-sandbox-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-spatial-extras\8.6.0\lucene-spatial-extras-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-spatial3d\8.6.0\lucene-spatial3d-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\apache\lucene\lucene-suggest\8.6.0\lucene-suggest-8.6.0.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\elasticsearch-cli\7.9.0\elasticsearch-cli-7.9.0.jar;C:\Users\Administrator\.m2\repository\net\sf\jopt-simple\jopt-simple\5.0.2\jopt-simple-5.0.2.jar;C:\Users\Administrator\.m2\repository\com\carrotsearch\hppc\0.8.1\hppc-0.8.1.jar;C:\Users\Administrator\.m2\repository\joda-time\joda-time\2.10.4\joda-time-2.10.4.jar;C:\Users\Administrator\.m2\repository\com\tdunning\t-digest\3.2\t-digest-3.2.jar;C:\Users\Administrator\.m2\repository\org\hdrhistogram\HdrHistogram\2.1.9\HdrHistogram-2.1.9.jar;C:\Users\Administrator\.m2\repository\org\elasticsearch\jna\5.5.0\jna-5.5.0.jar;C:\Users\Administrator\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-core\2.5\log4j-core-2.5.jar;C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-api\2.5\log4j-api-2.5.jar com.yanqi.es.SkipListTest
aaa
一共12:bbb_1 


Process finished with exit code 0

 
 
 
 
 
 
 
 
 

Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
                                                                                                                                                   ——W.S.Landor

 

 

posted on   yanqi_vip  阅读(18)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示