日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

java 跳跃表_c++实现跳跃表(Skip List)的方法示例

發(fā)布時間:2023/12/18 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 跳跃表_c++实现跳跃表(Skip List)的方法示例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

Skip List是一種隨機化的數據結構,基于并聯(lián)的鏈表,其效率可比擬于二叉查找樹(對于大多數操作需要O(log n)平均時間)。基本上,跳躍列表是對有序的鏈表增加上附加的前進鏈接,增加是以隨機化的方式進行的,所以在列表中的查找可以快速的跳過部分列表(因此得名)。所有操作都以對數隨機化的時間進行。Skip List可以很好解決有序鏈表查找特定值的困難。

跳表是平衡樹的一種替代的數據結構,但是和紅黑樹不相同的是,跳表對于樹的平衡的實現(xiàn)是基于一種隨機化的算法的,跳躍表使用概率均衡技術而不是使用強制性均衡,因此,對于插入和刪除結點比傳統(tǒng)上的平衡樹算法更為簡潔高效。

一個跳表具有以下特征:

1.一個跳表應該有幾個層(level)組成;

2.跳表的第一層包含所有的元素;

3.每一層都是一個有序的鏈表;

4.如果元素x出現(xiàn)在第i層,則所有比i小的層都包含x;

5.第i層的元素通過一個down指針指向下一層擁有相同值的元素;

6.Top指針指向最高層的第一個元素。

下面來研究一下跳表的核心思想: 先從鏈表開始,如果是一個簡單的鏈表,那么我們知道在鏈表中查找一個元素I的話,需要將整個鏈表遍歷一次。

如果是說鏈表是排序的,并且節(jié)點中還存儲了指向前面第二個節(jié)點的指針的話,那么在查找一個節(jié)點時,僅僅需要遍歷N/2個節(jié)點即可。

如上圖所示,是一個即為簡單的跳躍表。傳統(tǒng)意義的單鏈表是一個線性結構,向有序的鏈表中插入一個節(jié)點需要O(n)的時間,查找操作需要O(n)的時間。如果我們使用上圖的跳躍表,就可以減少查找所需時間為O(n/2),因為我們可以先通過每個節(jié)點的最上面的指針先進行查找,這樣子就能跳過一半的節(jié)點。比如我們想查找19,首先和6比較,大于6之后,在和9進行比較,然后在和12進行比較......最后比較到21的時候,發(fā)現(xiàn)21大于19,說明查找的點在17和21之間,從這個過程中,我們可以看出,查找的時候跳過了3、7、12等點,因此查找的復雜度為O(n/2)。

當然上面只是最簡單的就是跳躍表,真正的跳表每一個結點不單單只包含指向下一個結點的指針,可能包含很多個指向后續(xù)結點的指針,這樣就可以跳過一些不必要的結點,從而加快查找、刪除等操作。對于一個鏈表內每一個結點包含多少個指向后續(xù)元素的指針,這個過程是通過一個隨機函數生成器得到,就是通過隨機生成一個結點中指向后續(xù)結點的指針數目。

通過上面的跳表的很容易設計這樣的數據結構:

定義每個節(jié)點類型:

typedef struct nodeStructure *node;

typedef struct nodeStructure

{

keyType key; // key值

valueType value; // value值

// 向前指針數組,根據該節(jié)點層數的

// 不同指向不同大小的數組

node forward[1];

};

上面的每個結構體對應著圖中的每個節(jié)點,如果一個節(jié)點是一層的節(jié)點的話(如7,12等節(jié)點),那么對應的forward將指向一個只含一個元素的數組,以此類推。

定義跳表數據類型:

// 定義跳表數據類型

typedef struct listStructure{

int level;

struct nodeStructure * header;

} * list;

先不看代碼先用圖來描述一下Skip List構造,插入和刪除的過程:

構造Skip List

1、給定一個有序的鏈表。

2、選擇連表中最大和最小的元素,然后從其他元素中按照一定算法(隨機)隨即選出一些元素,將這些元素組成有序鏈表。這個新的鏈表稱為一層,原鏈表稱為其下一層。

3、為剛選出的每個元素添加一個指針域,這個指針指向下一層中值同自己相等的元素。Top指針指向該層首元素

4、重復2、3步,直到不再能選擇出除最大最小元素以外的元素。

插入過程

例子:插入 119, level = 2

如果 K 大于鏈表的層數,則要添加新的層。

例子:插入 119, K = 4

刪除 21

看到這就很清楚了,上面已經提到所謂的Skip List是每層從它的下一層按照某種規(guī)律抽出一些元素,它的操作也很簡單,它的操作其實按層來操作鏈表,基本上是從上往下來操作。

具體的實現(xiàn)如下:

定義數據結構

//

// skiplist_def.h

// test

//

// Created by 杜國超 on 17/9/24.

// Copyright ? 2017年 杜國超. All rights reserved.

//

#ifndef skiplist_def_h

#define skiplist_def_h

#define MAX_LEVEL 8

typedef int KeyType;

typedef int ValueType;

//定義節(jié)點信息數據結構

template

struct NodeStructure {

K key;

V value;

NodeStructure* forward[1];

};

//定義跳躍表數據結構

template

struct SkipLisStructure{

int level;

NodeStructure* header;

};

typedef struct NodeStructure NodeType;

typedef struct SkipLisStructure ListType;

typedef NodeType* Node;

typedef ListType* List;

#define NEW_LEVEL_NODE(level) (Node)malloc(sizeof(NodeType) + (level) * sizeof(Node))

#endif /* skiplist_def_h */

增刪查操作實現(xiàn)

//

// skiplist.h

// test

//

// Created by 杜國超 on 17/9/24.

// Copyright ? 2017年 杜國超. All rights reserved.

//

#ifndef skiplist_h

#define skiplist_h

#include "skiplist_def.h"

class CSkipList{

public:

CSkipList();

~CSkipList();

public:

ValueType* Search(const KeyType& key);

bool Insert(KeyType& key,ValueType& value);

bool Delete(const KeyType& key,ValueType& value);

void FreeList();

private:

int RandomLevel();

private:

List _skipList;

int _size;

};

#endif /* skiplist_h */

//

// skiplist.cpp

// test

//

// Created by 杜國超 on 17/9/24.

// Copyright ? 2017年 杜國超. All rights reserved.

//

#include "skiplist_def.h"

#include "skiplist.h"

#include

CSkipList::CSkipList(){

_skipList = (List)malloc(sizeof(ListType));

// 設置跳表的層level,初始的層為0層(數組從0開始)

_skipList->level = 0;

_skipList->header = NEW_LEVEL_NODE(MAX_LEVEL);

// 將header的forward數組清空

for(int i = 0; i < MAX_LEVEL; ++i)

_skipList->header->forward[i] = NULL;

_size = 0;

}

CSkipList::~CSkipList()

{

FreeList();

}

ValueType* CSkipList::Search(const KeyType& key){

Node node = _skipList->header;

Node indexNode = NULL;

for(int i = _skipList->level - 1; i >= 0; --i){

while((indexNode = node->forward[i]) && (indexNode->forward[i]->key <= key))

{

if (indexNode->key == key)

{

return &(indexNode->value);

}

node = indexNode;

}

}

return NULL;

}

bool CSkipList::Insert(KeyType& key, ValueType& value)

{

Node update[MAX_LEVEL];

int i;

Node node = _skipList->header;

Node indexNode = NULL;

//尋找key所要插入的位置

for(i = _skipList->level - 1; i >= 0; --i){

while((indexNode = node->forward[i]) && (indexNode->forward[i]->key < key))

{

node = indexNode;

}

update[i] = node;

}

node = node->forward[0];

//如果key已經存在

if(node->key == key){

node->value = value;

return false;

}else{

//隨機生成新結點的層數

int level = RandomLevel();

if(level > _skipList->level){

for (int i = _skipList->level;i < level;++i)

{

update[i] = _skipList->header;

}

_skipList->level = level;

}

//申請新的結點

Node newNode = NEW_LEVEL_NODE(level);

newNode->key = key;

newNode->value = value;

//調整forward指針

for(int i = level - 1; i >= 0; --i){

node = update[i];

newNode->forward[i] = node->forward[i];

node->forward[i] = newNode;

}

//更新元素數目

++_size;

return true;

}

}

bool CSkipList::Delete(const KeyType& key,ValueType& value){

Node update[MAX_LEVEL];

int i;

Node node = _skipList->header;

Node indexNode = NULL;

//尋找key所要插入的位置

for(i = _skipList->level - 1; i >= 0; --i){

while((indexNode = node->forward[i]) && (indexNode->forward[i]->key < key))

{

node = indexNode;

}

update[i] = node;

}

node = node->forward[0];

//結點不存在

if(node->key != key){

return false;

}else{

value = node->value;

//調整指針

for(i = 0; i < _skipList->level; ++i){

if(update[i]->forward[i] != node)

break;

update[i]->forward[i] = node->forward[i];

}

//刪除結點

free(node);

for(int i = _skipList->level - 1; i >= 0; i--){

if(_skipList->header->forward[i]==NULL){

_skipList->level--;

}

}

//更新鏈表元素數目

--_size;

return true;

}

}

int CSkipList::RandomLevel()

{

int k = 1;

while (rand()%2)

{

k++;

}

k=(k

return k;

}

void CSkipList::FreeList(){

Node p = _skipList->header;

Node q;

while(p != NULL){

q = p->forward[0];

free(p);

p = q;

}

free(p);

free(_skipList);

_size = 0;

}

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

總結

以上是生活随笔為你收集整理的java 跳跃表_c++实现跳跃表(Skip List)的方法示例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。