1. 程式人生 > >[演算法天天見](五)跳躍連結串列

[演算法天天見](五)跳躍連結串列

跳躍連結串列

一、概述

跳錶實際上是連結串列的一種擴充套件,它解決的是連結串列的查詢速度問題。由於它是連結串列的擴充套件,所以他底層維護的本質還是一個有序連結串列。他的複雜度取決於什麼樣的node插入到最高哪層中。在插入的時候下從最高層開始找起,一直找到最底層,然後用一個函式算出這個節點要插入到幾層,最後再每一層執行插入操作。查詢和插入前半部分是同一個操作。刪除節點也很簡單,因為你找到的節點總是最上層節點,只要迴圈刪除下層本節點就可以了。

二、演算法

public class SkipListTest extends
Sprite { private var mMaxLayer:uint = 4; private var mSkipRoot:Vector.<SkipNode> = new Vector.<SkipNode>(4); private var nodeHead:Node = new Node(); public function SkipListTest() { super(); init(); var a:Array = [10,30,20,50,40]; for(var i:int = 0; i < a.length; i++) {
this.insert(a[i]); } print(); } private function init():void { //初始化頭結點 for(var i:int = 0; i < mMaxLayer; i++) { mSkipRoot[i] = new SkipNode(); mSkipRoot[i].data = nodeHead; if(i > 0) { mSkipRoot[i].down = mSkipRoot[i - 1]; } } } public function search
(value:int):SkipNode { var prev:Vector.<SkipNode> = new Vector.<SkipNode>(4);//上一個節點 var cur:Vector.<SkipNode> = new Vector.<SkipNode>(4);//當前查詢的節點 var i:int; for(i = 0; i < mMaxLayer; i++) { prev[i] = mSkipRoot[i]; cur[i] = prev[i].next; } i = mMaxLayer - 1; do { if(cur[i] == null) { i--; }else { if(cur[i].data.data > value)//在下層查詢 { i--; if(i >=0 ) { prev[i] =prev[i + 1].down; cur[i] = prev[i].next; } }else if(cur[i].data.data < value)//繼續在本層查詢 { prev[i] = cur[i]; cur[i] = prev[i].next; }else { return cur[i]; } } }while( i >= 0); return null; } public function insert(value:int):void { var prev:Vector.<SkipNode> = new Vector.<SkipNode>(4);//上一個節點 var cur:Vector.<SkipNode> = new Vector.<SkipNode>(4);//當前查詢的節點 var newNode:Node; var newSkipNode:SkipNode; var i:int; for(i = 0; i < mMaxLayer; i++) { prev[i] = mSkipRoot[i]; cur[i] = prev[i].next; } i = mMaxLayer - 1; do { if(cur[i] == null) { i--; }else { if(cur[i].data.data > value)//在下層查詢 { i--; if(i >=0 ) { prev[i] =prev[i + 1].down; cur[i] = prev[i].next; } }else if(cur[i].data.data < value)//繼續在本層查詢 { prev[i] = cur[i]; cur[i] = prev[i].next; }else//不儲存相同值 { return; } } }while( i >= 0) newNode = new Node(); newNode.data = value; //看要插入幾層 var layer:uint = randomLayer(); //對每一層進行插入 for(var j:int = 0; j <= layer; j++) { newSkipNode = new SkipNode(); newSkipNode.data = newNode; newSkipNode.next = prev[j].next; prev[j].next = newSkipNode; if(j > 0) { newSkipNode.down = prev[j - 1].next; } } } public function remove(value:int):void { //remove 其實很簡單了 因為 search 可以做到同時返回node與node的前驅 //偷下懶應該沒人發現吧.... } private function randomLayer():uint { return Math.floor(Math.random() * 4); } public function print():void { for(var i:int = mSkipRoot.length - 1; i >= 0 ; --i) { var s:String = ""; s += "第" + i + "行: "; var cur:SkipNode = mSkipRoot[i]; while(cur != null) { s += cur.toString() + ", "; cur = cur.next; } trace(s); } } } class SkipNode { public var data:Node;//引用的那個Node public var next:SkipNode;//下一個Node public var down:SkipNode;//下一級指向的Node public function toString():String { return data.toString(); } } class Node { public var data:int; public var next:Node; public function Node() { } public function toString():String { return data.toString(); } }