redis 系列4 數據結構之鏈表

来源:https://www.cnblogs.com/MrHSR/archive/2018/11/01/9887373.html
-Advertisement-
Play Games

一. 概述 鏈表提供了高效的節點重排能力,以及順序性的節點訪問方式,並且可能通過增刪節點來靈活地調整鏈表的長度。作為一種數據結構,在C語言中並沒有內置的這種數據結構。所以Redis構建了自己的鏈表實現。鏈表在Redis中應用非常多,比如列表鍵的底層實現之一就是鏈表,當一個列表鍵包含了數量比較多的元素 ...


一. 概述

  鏈表提供了高效的節點重排能力,以及順序性的節點訪問方式,並且可能通過增刪節點來靈活地調整鏈表的長度。作為一種數據結構,在C語言中並沒有內置的這種數據結構。所以Redis構建了自己的鏈表實現。鏈表在Redis中應用非常多,比如列表鍵的底層實現之一就是鏈表,當一個列表鍵包含了數量比較多的元素,又或者列表中包含的元素都是比較長的字元串時,Redis就會使用鏈表作為列表鍵的底層實現。

-- 例1:使用integers 列表鍵包含了從1到10,共有10個整數
127.0.0.1:6379> rpush integers "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
(integer) 10
127.0.0.1:6379> llen integers
(integer) 10
127.0.0.1:6379> lrange integers 0 5
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"

  integers列表鍵的底層實現就是一個鏈表。鏈表中的每個節點都保存了一個整數值,除了鏈表鍵之外,發佈與訂閱,慢查詢,監視器等功能也用到了鏈表。Redis伺服器本身還使用鏈表來保存多個客戶端的狀態信息,以及使用鏈表來構建客戶端輸出緩衝區(output buffer)。

 

二 鏈表和鏈表節點定義

// 每個鏈表節點使用一個adlist.h/listNode結構來表示:
      typedef struct listNode
        {
            //前置節點
            struct listNode *prev;
            //後置節點
            struct listNode *next;
            //節點的值
            void *value;
        }listNode; //別名

  多個listNode可能通過prev和next指針組成雙端鏈表。雖然使用多個listNode結構就可以組成鏈表,但使用adlist.h/list 來持有鏈表的話,操作起來會更方便。

 typedef struct list
        {
            //表頭節點
            listNode    *head;
            //表尾節點
             listNode *tail;
            //鏈表所包含的節點數量 
            unsigned long len;
            //節點值複製函數
            void *(*dup) (void *ptr);
            //節點值釋放函數
            void (*free)(void *ptr)
            //節點值對比函數
            int (*match) (void *ptr,void *key)
        }list; //別名

  在list結構中鏈表提供了表頭指針head, 表尾指針tail,以及鏈表長度計數器len, 而dup, free和match成員則是用於實現多態鏈表所需的類型特定函數:dup 函數用於複製鏈表節點所保存的值; free 函數用於釋放鏈表節點所保存的值; match 函數則用於對比鏈表節點所保存的值和另一個輸入值是否相等。

 

三.Redis的鏈表實現的特性總結

  (1)雙端: 鏈表節點帶有prev 和next 指針,獲取某個節點的前置節點和後置節點的複雜度都是0(1) 。

  (2)無環: 表頭節點的prev指針和表尾節點的next 指針都指向null ,對鏈表的訪問以null 為終點 。

  (3)帶表頭指針和表尾指針:通過list結構的head指針和tail 指針,程式獲取鏈接的表頭節點和表尾節點的複雜度為0(1)

  (4)帶鏈表長度計數器:程式使用list結構的len屬性來對list持有的鏈表節點進行計數,程式獲取鏈表中節點數量的複雜度為0(1)

  (5)多態:鏈表節點使用void* 指針來保存節點值,並且可能通過list結構的dup,free,match 三個屬性為節點值設置類型特定函數,所以鏈表可以用於保存各種不同類型的值。

 

四. 鏈表和鏈表節點的API

函數

作用

listSetDupMethod

將給定的函數設置為鏈表的節點值複製函數

listGetDupMethod

返回鏈表當前正在使用的節點值複製函數

listSetFreeMethod

將給定的函數設置為鏈表的節點值釋放函數

listGetFree

返回鏈表當前正在使用的節點值釋放函數

listSetMatchMethod

將給定的函數設置為鏈表的節點值對比函數

listGetMatchMethod

返回鏈表當前正在使用的節點值對比函數

listLenth

返回鏈表的長度(包含多少節點)

listFirst

返回鏈表的表頭節點

listLast

返回鏈表的表尾節點

listPrevNode

返回給定節點的前置節點

listNextNode

返回給定節點的後置節點

listNodeValue

返回給定節點目前正在保存的值

listCreate

創建一個不包含任何節點的新鏈表

listAddNodeHead

將一個包含給定值的新節點添加到給定鏈表的表頭

listAddNodeTail

將一個包含給定值的新節點添加到給定鏈表的表尾

listInsertNode

將一個包含給定值的新節點添加到給定節點的之前或者之後

listSearchKey

查找並返回鏈表中包含給定值的節點

listIndex

返回鏈表在給定索引上的節點

listDelNode

從鏈表中刪除給定節點

listRotate

將鏈表的表尾節點彈出,然後將被彈出的節點插入到鏈表的表頭,成為新的表頭節點

listDup

複製一個給定鏈表的副本

listRelease

釋放給定鏈表,以及鏈表中的所有節點

  總結:

    (1) 鏈表被廣泛用於實現Redis的各種功能,比如列表鍵,發佈與訂閱,慢查詢,監視器等。

    (2) 每個鏈表節點由一個listNode結構來表示,每個節點都有一個指定前置節點和後置節點的指針,所以Redis的鏈表實現是雙端鏈表。

    (3) 每個鏈表使用一個list結構來表示,這個結構帶有表頭節點指針 ,表尾節點指針,以及鏈表長度等信息。

    (4) 因為鏈表表頭節點的前置節點和表尾節點的後置節點都指向null, 所以Redis的鏈表實現是無環鏈表。

    (5) 通過為鏈表設置不同的類型特定函數,Redis的鏈表可以用於保存各種不同類型的值。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 伺服器 swap 交換分區製作 作用:‘提升‘ 記憶體的容量,防止OOM(Out Of Memory) 查看當前的交換分區 增加交換分區 可是是分區,LVM,File file創建: 1、新建一個專門的文件用於swap分區 註:此文件的大小是count的大小乘以bs大小,上面命令的大小是4GB 2、通 ...
  • linux的touch命令一般用來修改文件時間戳,或者新建一個不存在的文件。 一.命令格式: touch [參數]... 文件... 二.命令參數: |參數|描述| | | | | a | 或 time=atime或 time=access或 time=use 只更改存取時間。| | c | 或 n ...
  • 設計目的: 減少各種狀態值欄位; 減少資料庫冗餘和存儲空間; 增加狀態值時可靈活調整,無需增加額外欄位 ...
  • 前言 前面介紹了redis持久化和容災備份,這篇會介紹redis主從複製和redis持久化在主從複製中的一些應用。因為本人沒有那麼多伺服器或機器,所以這裡主要介紹下如何在docker容器中搭建主從複製以及搭建過程中遇到的一些問題。關於redis的深入講解,這邊博客《深入學習Redis(3):主從複製 ...
  • 似乎只要coding,這些代碼就要跟我過不去似的 今天在linux上安裝了mysql-server,想不到竟然被一個及其簡單的問題給難住了。 是的,我竟然無法登陸!!! 在論壇,百度,google上苦苦搜尋了半天,終於找到了問題所在。本質上還是自己資料庫學習的不夠扎實導致的問題。 廢話不多說,直接上 ...
  • mysql的出錯代碼表,根據mysql的頭文件mysql/include/mysqld_error.h整理而成 1005:創建表失敗 1006:創建資料庫失敗 1007:資料庫已存在,創建資料庫失敗 1008:資料庫不存在,刪除資料庫失敗 1009:不能刪除資料庫文件導致刪除資料庫失敗 1010:不 ...
  • 1、下載 https://dev.mysql.com/downloads/mysql/ 2、解壓到固定位置,如D:\MySQL\mysql 5.7.24 3、添加my.ini文件 跟bin同級 ··· [mysql] 設置mysql客戶端預設字元集 default character set=utf ...
  • map 結構 1. 語法:map(k1,v1,k2,v2,…) 1. 語法:map(k1,v1,k2,v2,…) 操作類型:map ,map類型的數據可以通過'列名['key']的方式訪問 案例: select deductions['Federal Taxes'],deductions['Stat ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...