確定性跳躍表 |
---|
?鏈表的定義
??關于表的定義,這里只簡單的闡述一下:表同圖、集合一樣是一種抽象數據類型。值得指出的是,每一種數據類型都有與自己相關的操作,比如數字類型的 取余等。
/*結構體指針 *PtrToNode ,然后可以用 PtrToNode xxx來定義一個結構體,相當于 struct Node *xxx; 這里指出一點:
點操作符左邊的操作數是一個“結果為結構”的表達式;
箭頭操作符左邊的操作數是一個指向結構的指針。
PtrToNode保存的是一個首地址,(*Position).Element ,和Position->Element 結果是一樣的;這里寫成struct Node * 類型,個人理解應該是想用 ->操作符讀寫結構體成員,這樣比點操作符;
*/
typedef struct Node *PtrToNode; //創建節點數據類型,方便后續代碼使用
typedef PtrToNode List; //創建鏈表結構,包含 [值]和[下一個節點的地址]
typedef PtrToNode Position; //
struct Node
{
int Element;
Position Next;
};
Ⅰ 1-2-3確定性跳躍表
- 性質: 每一個間隙(除在頭和尾之間可能的零間隙外)的容量為1,2或3;
??簡析:上圖中有兩個容量為3的間隙:第一個是 25 和 45 之間高度為 1 的的三個元素,第二個是頭尾節點之間高度為2的三個元素。
Ⅱ 代碼實現
-
實現效果
??簡析:結構體設計為初始點為 Top&Right ;每個節點有一個Right指針,一個Down指針;具體細節下面將上代碼分析。
-
結構體類型
#include <stdio.h>
#include <stdlib.h>
#define Error(str) printf("%s \n",str),exit(1) // 定義一個遇見錯誤終止操作函數;
#define Infinity (10000) // 代表圖的無窮大:∞
typedef int ElementType; // 定義int別名為ElementType,方便識記
typedef struct SkipNode *SkipList; //定義struct SkipNode *類型,代碼里是用來創建表頭而已;
typedef struct SkipNode *Position; // 插入操作生成新的結點,主要由Position創建;
struct SkipNode
{
ElementType Element;
SkipList Right;
SkipList Down;
};
static Position Bottom = NULL; /*需要初始化為空*/
static Position Tail = NULL; /* 需要初始化為空*/
??簡析:很顯然,實現如圖的鏈表,一個結構體需要3個變量,分別為保存值的數據變量,一個指向Next結點的指針變量,一個指向Down的指針變量。其中定義的 Tail 用來方便判斷是否當前結點的位置,以方便編程;Bottom 是一個臨時存放數值的結構體,每次插入操作,每次操作會先存放到Bottom里,然后新建結點再轉移數值;
-
初始化
SkipList Initialize()
{
SkipList L;
if(Bottom == NULL )
{
// 這里有一個知識點 sizeof(Bottom)=4; sizeof(struct SkipNode)=12;
Bottom = malloc( sizeof(struct SkipNode));
if(Bottom == NULL )
Error("out of space");
Bottom->Right = Bottom->Down = Bottom;
Tail = malloc( sizeof(struct SkipNode));
if(Tail == NULL )
Error("out of space");
Tail->Element = Infinity ;
Tail->Right = Tail;
}
/* 創建Header節點 */
L = malloc( sizeof( struct SkipNode ) );
if( L == NULL )
Error( "Out of space!!!" );
L->Element = Infinity;
L->Right = Tail;
L->Down = Bottom;
return L;
}
??簡析:Bottom->Right ,Bottom->Down ,Tail->Right指向它們自己本身;Tail->Down = NULL; L在程序里始終為Header節點;
-
插入操作
重點:
while(Item > Current->Element)
if( Current->Element > Current->Down->Right->Right->Element )
?????
SkipList Insert(ElementType Item, SkipList L)
{
Position Current = L;
Position NewNode;
Bottom->Element = Item;
while( Current != Bottom )
{
while(Item > Current->Element )
Current = Current->Right;
//下面這句代碼是重點
if( Current->Element > Current->Down->Right->Right->Element )
{
NewNode = malloc( sizeof( struct SkipNode ));
if(NewNode == NULL )
Error("out of space ");
NewNode->Right = Current->Right;
NewNode->Down = Current->Down->Right->Right;
Current->Right = NewNode;
NewNode->Element = Current->Element;
Current->Element = Current->Down->Right->Element;
}
else
Current = Current->Down;
}
//必要時提高節點的高度(這里必要是保證header始終在最高層)
if(L->Right != Tail )
{
NewNode = malloc( sizeof(struct SkipNode ));
if(NewNode == NULL )
Error("out of space");
NewNode->Right = Tail;
NewNode->Down = L;
NewNode->Element = Infinity;
L= NewNode;
}
return L;
}
??簡析:上圖解釋:
?????變量解析:
變量 | L | C | B | D | R | N |
---|---|---|---|---|---|---|
含義 | 根(頂)節點 | 當前節點 | 底(臨時)節點 | Down指針 | Right指針 | 新建節點 |
首先把 5 放到臨時結構體 Bottom 中,
條件while(Item > Current->Element ) 判斷不成立 ; ?
條件 if( Current->Element > Current->Down->Right->Right->Element ) 成立;
然后新建節點N,交換指針,賦值;
條件if(L->Right != Tail ) 成立 ,新建節點交換指針并賦值;
-
查找操作
重點:
while(item != current->Element)
???????
Position Find(ElementType item , SkipList L )
{
Position current = L;
Bottom->Element = item;
while(item != current->Element)
{
if( item < current->Element )
{
current = current->Down;
}
else
current = current->Right;
}
return current;
}
??簡析:理解了插入,對于查找來說,不成問題,放寬心看幾分鐘基本就明白了。我一開始看插入,費了好幾張A4紙來比劃,也是智商捉急了···· *?*
-
學習ING
????? 暫時寫到這里,《數據結構與算法分析 C語言描述》連敲帶看半個月,到了11 、12章看得很是迷糊····
作為一名標準的機械男,居然不好好學切割焊銑,而從大一開始把三年的大部分美好時光傾情奉獻給了編程···,看電子和軟件方面的專業書比在修專業的還多····也不知是福是禍···。其實我想問這么一個問題:興趣廣泛,無一專精,于目前社會情況,是福是禍?