跳表(skipList)的原理和java實現


寫這個博客的原因是因為看其他人寫的java實現的跳表代碼總是有點看不懂,原理倒是比較清楚,所以自己動手寫了一個簡單的跳表,希望能給看這塊兒數據結構的同學一個啟發,原理我覺得這篇文章寫的不錯,推薦給大家:https://blog.csdn.net/pcwl1206/article/details/83512600?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

不多說,直接貼代碼:

package com.example.demo;

import java.util.Random;

/**
 * 跳表的實現
 */
public class SkipList {
    public static final int MAX_LEVEL = 16; //跳表所允許的最大層級
    private SkipListNode head = new SkipListNode(null, MAX_LEVEL);
    private Random random = new Random();
    private int usedLevel = 1; //當前跳表使用中的最大層級

    public void insert(int value) {
        int level = randomLevel(); //找出當前插入值隨機最大層數
        //遍歷節點並插入
        insert(value, level);

    }

    public void delete(int value) {
        //從最高層開始,尋找節點
        int level = usedLevel;
        while(level >= 1) {
            level--;
            SkipListNode searchResult = search(value, level);
            if(searchResult != null) {
                deleteNode(searchResult);
                break;
            }
        }

    }

    //逐層打印
    public void print() {
       int level = usedLevel;
       while(level >= 1) {
           level--;
           printLevel(level);
       }
    }

    private void printLevel(int level) {
        SkipListNode current = head;
        String result = new String();
        while (current.next[level] != null) {
            result = result + current.next[level].data + " -> ";
            current = current.next[level];
        }
        System.out.println("第 " + level + " 層的數據為 : " + result);
    }

    private void deleteNode(SkipListNode searchResult) {
        //將當前節點的前置節點和后置節點關聯起來即可
        int currentLevel = searchResult.getMaxlevel();
        while(currentLevel >= 1) {
            currentLevel--;
            //當前節點的前置節點的后置節點 = 當前節點的后置節點
            searchResult.pre[currentLevel].next[currentLevel] = searchResult.next[currentLevel];
            if(searchResult.next[currentLevel] != null) {
                //如果當前節點的后置節點不為null
                //當前節點的額后置節點的前置節點 = 當前節點的前置節點
                searchResult.next[currentLevel].pre[currentLevel] = searchResult.pre[currentLevel];
            }
        }
    }

    private SkipListNode search(int value, int level) {
        //從頭開始遍歷
        SkipListNode current = head;
        while(current.next[level] != null && current.next[level].data < value) {
            current = current.next[level];
        }
        if(current.next[level] == null || current.next[level].data != value) {
            //如果搜索到最后,或者已經搜索到比尋找值大的節點了
            return null;
        }
        return current.next[level];

    }

    private void insert(int value, int level) {
        SkipListNode node = new SkipListNode(value, level); //構造當前節點
        int currentLevel = level;
        while(currentLevel-- > 0) {
            //從最高層開始,遍歷每一層
            if(head.next[currentLevel] == null) {
                //如果當前沒有插入任何元素,直接插入即可
                head.next[currentLevel] = node;
                node.pre[currentLevel] = head;
            } else {
                SkipListNode current = head.next[currentLevel], pre = head;
                //從第一個元素開始遍歷
                while(current != null && current.data < value) {
                    pre = current;
                    current = current.next[currentLevel];
                }
                //設置前置節點的后置節點為當前節點
                pre.next[currentLevel] = node;
                node.pre[currentLevel] = pre;
                if(current != null) {
                    //如果沒有遍歷到結尾,則需要設置當前節點的前置節點
                    current.pre[currentLevel] = node;
                    node.next[currentLevel] = current;
                }
            }

        }
        usedLevel = usedLevel > level ? usedLevel : level;
    }

    //隨機生成函數,即對於任意一個要插入跳表的節點,它的層級為多少
    private int randomLevel() {
        int level = 1;
        for(int i = 1; i < MAX_LEVEL; i++) {
            if(random.nextInt() % 2 == 1) {
                level++;
            }
        }
        return level;
    }


    private class SkipListNode{
        private Integer data;
        private SkipListNode[] next; //后置節點
        private SkipListNode[] pre; //前置節點,方便刪除使用

        public SkipListNode(Integer data, int maxLevel) {
            this.data = data;
            next = new SkipListNode[maxLevel];
            pre = new SkipListNode[maxLevel];
        }

        int getMaxlevel() {
            return next.length;
        }

    }

    public static void main(String[] args) {
        SkipList skipList = new SkipList();
        skipList.insert(10);
        skipList.insert(25);
        skipList.insert(83);
        skipList.insert(20);
        skipList.print();
        System.out.println("------------------");
        skipList.delete(83);
        skipList.delete(20);
        skipList.print();

    }
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM