數據結構---跳表

目錄

一、跳表的概念

為什么要使用隨機值來確定層高

二、跳表的分析

(1)查找過程

(2)性能分析

三、跳表的實現

四、與紅黑樹哈希表的對比


skiplist本質上也是一種查找結構,用于解決算法中的查找問題,跟平衡搜索樹和哈希表的價值是
一樣的,可以作為key或者key/value的查找模型。

一、跳表的概念

跳表是受到有序鏈表的啟發上發展而來的。

但是可以看到鏈表查找的效率是O(N)。那么有人就在想了,能不能讓他每間隔幾個節點就升高一層,這樣可以更快的跳到后面,從而提高查找效率。

????????假如每相鄰兩個節點升高一層,增加一個指針,讓指針指向下下個節點,如圖b。這樣所有新增加的指針連成了一個新的鏈表,但它包含的節點個數只有原來的一半。由于新增加的指針,我們不再需要與鏈表中每個節點逐個進行比較了,需要比較的節點數大概只有原來的一半。

此時的效率就變成了O(logN)

那是不是意味著層數越高,查找的效率也就越高。我們可以在第二層新產生的鏈表上,繼續為每相鄰的兩個節點升高一層,增加一個指針,從而產生第三層鏈表。如下圖c,這樣搜索效率就進一步提高了。

????????但是人們發現,這樣效率雖然極高。但是一旦涉及到插入和刪除操作,就會改變該節點后面的所有節點的層高,因為我們規定了必須每隔幾個就提高一層。這樣即使在查找的時候效率很高,但是會由于插入操作,重新遍歷后面的節點進行層高重構,導致效率又回歸了O(N)。? ? ? ??

為什么要使用隨機值來確定層高

? ? ? ? 如果我們插入和刪除不會改變后面的層高呢?舉個例子,本來每次間隔1個要提高一層,但是現在我不再改變后面節點的層高了,我插入的新節點是多高就把他直接鏈接到鏈表中,是不是就規避了重構結構的損耗。

? ? ? ? 但是如果插入的高度是固定的,這就相當于沒有利用到跳表的優化。最開始我想能不能給一個數組來決定該節點有多少層呢?答案發現是不行的。

所以這里我們采取的是隨機值的辦法來決定新節點到底有多高。

二、跳表的分析

(1)查找過程

查找19分析:

從頭節點的最上面的節點開始, next=6,19大于6.直接向右跳到6. next=空,向下走,next=25.25大于19.再向下走. next=9.19大于9,向右走到9. next=17. 19大于17, 向右跳到17. next=25. 25大于19.向下走. next=19.找到19. 總結: 比它大, 向右走. 比它小, 向下走

插入/刪除分析:

插入和刪除操作的關鍵都是, 找到此位置的每一層節點的前一個和后一個節點. 插入和刪除和其他節點無關, 只需要修改每一層的next指針指向即可. 比如現在要在節點7和9之間插入節點8. 節點8假設是三層. 那么插入只需要考慮節點8的第一層和第二層的前一個節點是6,而第三層的前一個節點是7. 第一層的后一個節點是25.第二層的后一個節點是9.第三次的后一個節點也是9. 依次改變指針知曉即可.

(2)性能分析

????????skiplist插入一個節點時隨機出一個層數,聽起來怎么這么隨意,如何保證搜索時的效率呢?這里首先要細節分析的是這個隨機層數是怎么來的。一般跳表會設計一個最大層數maxLevel的限制,其次會設置一個多增加一層的概率p。那么計算這個隨機層數的偽代碼如下圖:

當數據量足夠大的時候,他的時間復雜度就是O(logN),這個效率是和紅黑樹等搜索樹相當的,非常可觀。

三、跳表的實現

struct SkipListNode {int _val;vector<SkipListNode*> _nextv;SkipListNode(int val, int height) :_val(val), _nextv(height, nullptr){}
};
class Skiplist {typedef SkipListNode node;
public:Skiplist() {//頭節點層數先給1層_head = new node(-1, 1);srand(time(0));}bool search(int target) {node* cur = _head;int level = _head->_nextv.size() - 1;while (level >= 0){//和cur->next[level]比較,比它小就向下走,比它大向右走if (cur->_nextv[level] && cur->_nextv[level]->_val < target)cur = cur->_nextv[level];//下一個節點是空,即是尾,也要向下走else if (!cur->_nextv[level] || cur->_nextv[level]->_val > target)level--;else return true;}return false;}vector<node*> FindPrevNode(int num){node* cur = _head;int level = _head->_nextv.size() - 1;vector<node*> prev(level + 1, _head);//用于保存每一層的前一個while (level >= 0){//一旦要向下走了,就可以更新了,向右走不需要動if (cur->_nextv[level] && cur->_nextv[level]->_val < num)cur = cur->_nextv[level];else if (cur->_nextv[level] == nullptr || cur->_nextv[level]->_val >= num){prev[level] = cur;--level;}}return prev;}void add(int num) {vector<node*> prev = FindPrevNode(num);int n = RandomLevel();node* newnode = new node(num, n);if (_head->_nextv.size() < n){_head->_nextv.resize(n, nullptr);prev.resize(n, _head);}//鏈接前后節點即可for (int i = 0; i < n; i++){//新節點的下一個是prev的下一個newnode->_nextv[i] = prev[i]->_nextv[i];prev[i]->_nextv[i] = newnode;}}bool erase(int num) {//要刪除你,先找到此節點的每層的前一個,和插入時相似vector<node*> prev = FindPrevNode(num);//代表這個值不存在, 最下層找不到它,它就一定不存在if (prev[0]->_nextv[0] == nullptr || prev[0]->_nextv[0]->_val != num)return false;node* del = prev[0]->_nextv[0];for (int i = 0; i < del->_nextv.size(); i++)prev[i]->_nextv[i] = del->_nextv[i];delete del;return true;}int RandomLevel(){int level = 1;while (rand() < RAND_MAX * _p && level < _max)level++;return level;}void Print(){int level = _head->_nextv.size();for (int i = level - 1; i >= 0; --i){node* cur = _head;while (cur){printf("%d->", cur->_val);cur = cur->_nextv[i];}printf("\n");}}
private:node* _head;size_t _max = 32;double _p = 0.5;
};

四、與紅黑樹哈希表的對比

總結:

  • 平均空間開銷
    • 跳表的額外空間主要用于存儲多層指針,平均每個節點增加的指針數為?O(log n)
    • 相比平衡樹(如紅黑樹),跳表的空間開銷更可控。(因為紅黑樹是一個三叉鏈,每一個節點都要要存儲3個節點)
  • 對比哈希表
    • 哈希表需要額外的空間存儲哈希桶和處理沖突,空間開銷可能更高。
    • 極端情況下哈希表會退化成鏈表,從而要使用紅黑樹。
    • 哈希表一旦擴容,則需要對原來的每一個元素重新映射,并且還要拷貝到新表中。如果擴容策略較為激進,則會導致空間開銷較大。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76933.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76933.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76933.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PCDN通過個人路由器,用更靠近用戶的節點來分發內容,從而達到更快地網絡反應速度

PCDN&#xff08;P2P CDN&#xff09;的核心思想正是利用個人路由器、家庭寬帶設備等分布式邊緣節點&#xff0c;通過就近分發內容來降低延遲、提升網絡響應速度&#xff0c;同時降低傳統CDN的帶寬成本。以下是其技術原理和優勢的詳細分析&#xff1a; 1. 為什么PCDN能更快&…

用excel做九乘九乘法表

公式&#xff1a; IF($A2>B 1 , 1, 1,A2 & “" & B$1 & “” & $A2B$1,”")

凡泰極客亮相QCon2025鴻蒙專場,解析FinClip“技術+生態”雙引擎

2025年4月10日&#xff0c;備受矚目的QCon開發者技術峰會盛大舉行&#xff0c;本次活動開設鴻蒙專場以“HarmonyOS NEXT 創新特性與行業實踐”為主題&#xff0c;匯聚了眾多鴻蒙生態的領軍人物與技術專家&#xff0c;共同探討鴻蒙操作系統的技術創新與行業應用。 凡泰極客CTO徐…

java HttpServletRequest 和 HttpServletResponse

HttpServletRequest 和 HttpServletResponse 詳解 1. HttpServletRequest&#xff08;HTTP 請求對象&#xff09; HttpServletRequest 是 Java Servlet API 提供的接口&#xff0c;用于封裝客戶端的 HTTP 請求信息。它繼承自 ServletRequest&#xff0c;并增加了 HTTP 協議相…

HAL TIM PWM產生 藍橋杯

目錄 0.原理 0.1 CNT和CCR關系 0.2 PWM模式1模式2 1. cubemx配置 需求(將PA1輸出1Khz的 50&#xff05;占空比的方波) 1.0 PWM的頻率計算: 2.代碼 0.原理 0.1 CNT和CCR關系 CNT計數器和CCR比較器進行比較,如果是向上計數,CNT逐漸增加,CCR是虛線位置,也是用戶自定義的…

python入門:簡單介紹和python和pycharm軟件安裝/學習網址/pycharm設置(改成中文界面,主題,新建文件)

Python 目前是 AI 開發的首選語言 軟件安裝 python解釋器 官網下載 Python |Python.org 勾選 Add python.exe to PATH 將python.exe添加到PATH 勾選這個選項會將Python的可執行文件路徑添加到系統的環境變量PATH中。這樣做的好處是&#xff0c;你可以在命令行中從任何位置直…

CMD命令行筆記

CMD命令行筆記&#xff0c;涵蓋常用命令及實用技巧&#xff0c;適合快速查閱&#xff1a; 一、基礎操作 打開CMD Win R → 輸入 cmd → 回車管理員模式&#xff1a;右鍵開始菜單 → 選擇“命令提示符&#xff08;管理員&#xff09;” 常用命令 help&#xff1a;查看所有命令…

android中dp和px的關系

關于android的dp和px的關系是我剛開始學習android的第一個知識點&#xff0c;不知不覺學安卓也有一年了&#xff0c;但是偶然間我發現我理解的dp和px的關系一直是錯的&#xff0c;真的是有一點搞笑&#xff0c;今天特意寫一篇博客紀念一下這個我理解錯一年的知識點。 dp和px之間…

(四)機器學習---邏輯回歸及其Python實現

之前我們提到了常見的任務和算法&#xff0c;本篇我們使用邏輯回歸來進行分類 分類問題回歸問題聚類問題各種復雜問題決策樹√線性回歸√K-means√神經網絡√邏輯回歸√嶺回歸密度聚類深度學習√集成學習√Lasso回歸譜聚類條件隨機場貝葉斯層次聚類隱馬爾可夫模型支持向量機高…

【汽車產品開發項目管理——端到端的汽車產品誕生流程】

MPU&#xff1a;集成運算器、寄存器和控制器的中央處理器芯片 MCU&#xff1a;微控制單元&#xff0c;將中央處理器CPU、存儲器ROM/RAM、計數器、IO接口及多種外設模塊集成在單一芯片上的微型計算機系統。 汽車產品開發項目屬性&#xff1a;臨時性、獨特性、漸進明細性、以目標…

Python將不能修改的值稱為不可變的 ,而不可變的列表被稱為元組------元組

列表非常適合用于存儲在程序運行期間可能變化的數據集。列表是可以修改的&#xff0c;這對處理網站的用戶列表或游戲中的角色列表至關重要。然而&#xff0c;有時候你需要創建一系列不可修改的元素&#xff0c;元組可以滿足這種需求。Python將不能修改的值稱為不可變的&#xf…

智慧醫院室內導航系統架構拆解:技術選型與性能攻堅指南

本文面向醫院信息化團隊技術負責人及醫療IoT解決方案開發者&#xff0c;聚焦解決大規模院區導航系統的擴展性、多源數據融合及實時路徑規劃等技術難點&#xff0c;提供從架構到落地的完整技術路線圖。 如需獲取智慧醫院導航導診系統解決方案請前往文章最下方獲取&#xff0c;如…

醫藥采購系統平臺第4天03:實現根據用戶的角色顯示不同用戶的權限菜單編寫攔截器實現權限攔截模塊的開發流程和測試流程小節

如果想要獲取相關的源碼,筆記,和相關工具,對項目需求的二次開發,可以關注我并私信!!! 四 權限管理(用戶授權)的應用:根據用戶的角色顯示不同用戶的權限菜單 經過上面的與第三方系統的成功的接入,而且在“角色管理”菜單中也對需要授權的角色進行了授權--->給一級…

#2 物聯網組成要素

從下至上&#xff0c;則包括了5個要素&#xff0c;包括 設備 / 傳感器 / 網絡 / 物聯網服務 / 數據分析 這五個要素。為了便于理解&#xff0c;我們用思維導圖展示 物聯網構成架構 設備 能夠感測和反饋并連到網絡進行物聯網服務的裝置 傳感器 傳感器和網關的融合實現了物…

< 自用文 Project-30.6 Crawl4AI > 為AI模型優化的網絡爬蟲工具 幫助收集和處理網絡數據的工具

官方鏈接&#xff1a; Github &#xff1a;https://github.com/unclecode/crawl4ai 文檔主頁&#xff1a;https://docs.crawl4ai.com/ 當前版本&#xff1a;Crawl4AI v0.5.0 主要新功能&#xff1a; 可配置策略&#xff08;廣度優先、深度優先、最佳優先&#xff09;探索整…

【Kafka基礎】監控與維護:動態配置管理,靈活調整集群行為

1 基礎配置操作 1.1 修改主題保留時間 /export/home/kafka_zk/kafka_2.13-2.7.1/bin/kafka-configs.sh --alter \--bootstrap-server 192.168.10.33:9092 \--entity-type topics \--entity-name yourtopic \--add-config retention.ms86400000 參數說明&#xff1a; retention…

04-微服務 面試題-mk

文章目錄 1.Spring Cloud 常見的組件有哪些?2.服務注冊和發現是什么意思?(Spring Cloud 如何實現服務注冊發現)3.Nacos配置中心熱加載實現原理及關鍵技術4.OpenFeign在微服務中的遠程服務調用工作流程5.你們項目負載均衡如何實現的 ?6.什么是服務雪崩,怎么解決這個問題?…

Redis最佳實踐——秒殺系統設計詳解

基于Redis的高并發秒殺系統設計&#xff08;十萬級QPS&#xff09; 一、秒殺系統核心挑戰 瞬時流量洪峰&#xff1a;100萬 QPS請求沖擊庫存超賣風險&#xff1a;精準扣減防止超賣系統高可用性&#xff1a;99.99%服務可用性要求數據強一致性&#xff1a;庫存/訂單/支付狀態同步…

AI大模型從0到1記錄學習 數據結構和算法 day18

3.3.1 棧的概述 棧&#xff08;Stack&#xff09;是一個線性結構&#xff0c;其維護了一個有序的數據列表&#xff0c;列表的一端稱為棧頂&#xff08;top&#xff09;&#xff0c;另一端稱為棧底&#xff08;bottom&#xff09;。棧對數據的操作有明確限定&#xff0c;插入元素…

粘性定位(position:sticky)——微信小程序學習筆記

1. 簡介 CSS 中的粘性定位&#xff08;Sticky positioning&#xff09;是一種特殊的定位方式&#xff0c;它可以使元素在滾動時保持在視窗的特定位置&#xff0c;類似于相對定位&#xff08;relative&#xff09;&#xff0c;但當頁面滾動到元素的位置時&#xff0c;它會表現得…