寫這個博客的原因是因為看其他人寫的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(); } }