linux 雙向迴圈連結串列(下)
1 雙向連結串列在Linux核心中的實現過程
Linux核心對雙向迴圈連結串列的設計非常巧妙,連結串列的所有運算都基於只有兩個指標域的list_head結構體來進行。
- /* linux-2.6.38.8/include/linux/types.h */
- struct list_head {
- struct list_head *next, *prev;
- };
連結串列的運算(原始碼都在linux-2.6.38.8/include/linux/list.h檔案中定義,並且假定CONFIG_DEBUG_LIST未定義):
(1)、連結串列頭結點的建立
1.1 靜態建立
- #define LIST_HEAD_INIT(name) { &(name), &(name) }
- #define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
通過LIST_HEAD巨集建立一個list_head結構體變數name,並把name的所有成員(next和prev)都初始化為name的首地址。
1.2 動態建立
-
staticinlinevoid INIT_LIST_HEAD(
- {
- list->next = list;
- list->prev = list;
- }
把list_head結構體變數的首地址傳遞給INIT_LIST_HEAD函式來對其成員進行初始化。
(2)、結點的新增
list_add函式是把新結點new新增到head結點的後面,而list_add_tail函式是把新結點new插入到結點head的前面。
函式原始碼如下:
-
staticinlinevoid __list_add(
- struct list_head *prev,
- struct list_head *next)
- {
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
- }
- staticinlinevoid list_add(struct list_head *new, struct list_head *head) //
- {
- __list_add(new, head, head->next);
- }
- staticinlinevoid list_add_tail(struct list_head *new, struct list_head *head)
- {
- __list_add(new, head->prev, head);
- }
- (3)、結點的刪除
list_del函式的作用是將結點*entry從連結串列中移走,並把此結點的兩個成員分別初始化為LIST_POISON1和LIST_POISON2。注意,這裡的*entry結點所佔用的記憶體並沒有被釋放。
list_del_init函式的作用也是將結點*entry從連結串列中移走,但它把此結點的兩個成員初始化為entry。
- staticinlinevoid __list_del(struct list_head * prev, struct list_head * next)
- {
- next->prev = prev;
- prev->next = next;
- }
- staticinlinevoid __list_del_entry(struct list_head *entry)
- {
- __list_del(entry->prev, entry->next);
- }
- staticinlinevoid list_del(struct list_head *entry)
- {
- __list_del(entry->prev, entry->next);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
- }
- staticinlinevoid list_del_init(struct list_head *entry)
- {
- __list_del_entry(entry);
- INIT_LIST_HEAD(entry);
- }
LIST_POISON1和LIST_POISON2的值定義在linux-2.6.38.8/include/linux/poison.h檔案中:
- #define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
- #define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
其中POISON_POINTER_DELTA的值在CONFIG_ILLEGAL_POINTER_VALUE未配置時為0。
(4)、結點的替換
list_replace函式的作用是用結點*new替換掉結點*old,list_replace_init函式的作用與list_replace相同,除了它還會把*old結點的兩個成員初始化為old外。
- staticinlinevoid list_replace(struct list_head *old,
- struct list_head *new)
- {
- new->next = old->next;
- new->next->prev = new;
- new->prev = old->prev;
- new->prev->next = new;
- }
- staticinlinevoid list_replace_init(struct list_head *old,
- struct list_head *new)
- {
- list_replace(old, new);
- INIT_LIST_HEAD(old);
- }
(5)、結點的移動
list_move函式的作用是把*list結點從它所在的連結串列中移除,然後把它新增到*head結點的後面。list_move_tail函式的作用與list_move相同,但它把*list插入到*head結點的前面。
- staticinlinevoid list_move(struct list_head *list, struct list_head *head)
- {
- __list_del_entry(list);
- list_add(list, head);
- }
- staticinlinevoid list_move_tail(struct list_head *list,
- struct list_head *head)
- {
- __list_del_entry(list);
- list_add_tail(list, head);
- }
(6)、判斷*list是否是連結串列head的最後一個結點,是則返回1,否則返回0
- staticinlineint list_is_last(conststruct list_head *list,
- conststruct list_head *head)
- {
- return list->next == head;
- }
(7)、判斷head是否為空表,是則返回1,否則返回0
- staticinlineint list_empty(conststruct list_head *head)
- {
- return head->next == head;
- }
- staticinlineint list_empty_careful(conststruct list_head *head)
- {
- struct list_head *next = head->next;
- return (next == head) && (next == head->prev);
- }
(8)、翻轉連結串列
-
相關推薦
linux 雙向迴圈連結串列(下)
1 雙向連結串列在Linux核心中的實現過程 Linux核心對雙向迴圈連結串列的設計非常巧妙,連結串列的所有運算都基於只有兩個指標域的list_head結構體來進行。 /* linux-2.6.38.8/include/linux/t
雙向迴圈連結串列(帶頭結點)
//定義結構體 typedef struct data { int data; struct data *pro; //前驅 struct data *next; //後繼 }DATA; //建立雙向迴圈連結串列 DATA *cr
C++ 雙向迴圈連結串列(簡稱:雙鏈表)
一、概念 1.在雙鏈表中的每個結點應有兩個連結指標: lLink -> 指向前驅結點&nb
C++——實現雙向迴圈連結串列(帶頭結點)
雙向連結串列也叫雙鏈表,是連結串列的一種,它的每個資料結點中都有兩個指標,分別指向直接後繼和直接前驅。所以,從雙向連結串列中的任意一個結點開始,都可以很方便地訪問它的前驅結點和後繼結點。一般我們都構造雙向迴圈連結串列。 簡單的畫一個雙向迴圈簡易圖: 下面就用C++實現一下基本操
C++資料結構與STL--雙向迴圈連結串列(實現自定義iterator類)
class dLinkList {private:node<T> *head; //頭節點size_t length; //連結串列長度void dInsert(node<T> *curr,T val) //插入的輔助函式,把新節點插入curr前 {node<T>* t
雙向迴圈連結串列(建立·插入·刪除·遍歷)
author:chen ming dong #include<stdio.h> #include<stdlib.h> typedef struct list { int a; struct list *next;
連結串列(下):如何輕鬆寫出正確的連結串列程式碼?
本文是學習演算法的筆記,《資料結構與演算法之美》,極客時間的課程 寫好連結串列程式碼 技巧一、理解指標或引用的含義 不管是C語言中指標的含義,還是JAVA語言中引用的概念,它們的意思是一樣的,都是儲存所指物件的記憶體地址。 編寫連結串列程式碼的時候,這樣的程式碼: p -&g
07-連結串列(下):如何輕鬆寫出正確的連結串列程式碼
上一節我講了連結串列相關的基礎知識。學完之後,我看到有人留言說,基礎知識我都掌握了,但是寫連結串列程式碼還是很費勁。哈哈,的確是這樣的! 想要寫好連結串列程式碼並不是容易的事兒,尤其是那些複雜的連結串列操作,比如連結串列反轉、有序連結串列合併等,寫的時候非常容易
雙向迴圈連結串列(c++)
#include<iostream> using namespace std; struct ListNode { ListNode() :_data(0) ,_prev(0) , _next(0) {} ListNode( c
(Linux 核心)建立雙向迴圈連結串列
#define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_h
(Linux 核心)雙向迴圈連結串列list_head
什麼是雙向迴圈連結串列就不說了,學習linux的應該都有C家族的基礎。 struct list_head { struct list_head *next, *prev; }; list_head
資料結構與演算法(五)-線性表之雙向連結串列與雙向迴圈連結串列
前言:前面介紹了迴圈連結串列,雖然迴圈連結串列可以解決單鏈表每次遍歷只能從頭結點開始,但是對於查詢某一節點的上一節點,還是頗為複雜繁瑣,所以可以在結點中加入前一個節點的引用,即雙向連結串列 一、簡介 雙向連結串列:在連結串列中,每一個節點都有對上一個節點和下一個節點的引用或指標,即從一個節點出發可以有
UVa11925 生成排列(Generating Permutations)---雙向迴圈連結串列
題目描述:給你一個特定序列,要求你經過一定的變換規則將升序列變為給的特定序列。 https://vjudge.net/problem/UVA-11925 變換規則為:1.第一個元素和第二個元素交換. 2、首元素到尾部。 題目分析:逆著處理,最後輸出的時候倒著輸出就行了。若第一個元素大於第
資料結構學習筆記——C++實現雙向迴圈連結串列模板類(超詳解)
定義了兩個標頭檔案分別放置結點類模板(Node.h)和雙鏈表模板(DoubleLinkList.h), 然後在原始檔的main函式中測試。 Node.h #pragma once # include <iostream> template <class
C語言實現雙向非迴圈連結串列(帶頭結點尾結點)的基本操作
我在之前一篇部落格中《C語言實現雙向非迴圈連結串列(不帶頭結點)的基本操作》中詳細實現了不帶頭尾節點的雙向非迴圈連結串列的很多操作。其實同單鏈表一樣,不帶頭結點的連結串列很多操作都是比較麻
C語言學習歷程(四)雙向迴圈連結串列
首先通過定義結構體。 接著是完整的函式: #include <stdio.h> #include <stdlib.h> #define T 1 #define F 0 typedef int Elementype; typedef int
(C語言版)連結串列(四)——實現雙向迴圈連結串列建立、插入、刪除、釋放記憶體等簡單操作
雙向迴圈連結串列是基於雙向連結串列的基礎上實現的,和雙向連結串列的操作差不多,唯一的區別就是它是個迴圈的連結串列,通過每個節點的兩個指標把它們扣在一起組成一個環狀。所以呢,每個節點都有前驅節點和後繼節點(包括頭節點和尾節點)這是和雙向連結串列不同的地方。我們看下雙向迴圈連結
雙向迴圈連結串列C++實現(完整版)
#include<iostream> using namespace std; /* *節點類 */ struct DCNode { int data; DCNode * prior; DCNode * next; }; /* *連結串列類 */
資料結構(雙向迴圈連結串列)(C語言)
C語言實現雙向迴圈連結串列的基本功能與除錯: //DoubleCircleLinkLst.h #ifndef _LINKLIST_H #define _LINKLIST_H #include <stdio.h> #include <stdlib.h&g
《劍指offer》系列 二叉搜尋樹與雙向連結串列(Java)
連結 牛客: 二叉搜尋樹與雙向連結串列 題目描述 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。 思路 這個程式碼是借鑑網上的,整體結構和中序遍歷非常類似,只不過將原本輸出那部分的操作換成了改變結