[演算法天天見](五)跳躍連結串列
阿新 • • 發佈:2018-11-08
跳躍連結串列
一、概述
跳錶實際上是連結串列的一種擴充套件,它解決的是連結串列的查詢速度問題。由於它是連結串列的擴充套件,所以他底層維護的本質還是一個有序連結串列。他的複雜度取決於什麼樣的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();
}
}