RT Thread 雙向鍊錶分析

2021-10-05 17:11:49 字數 4260 閱讀 2444

從鍊錶刪除節點函式 rt_list_remove()

鍊錶節點元素訪問

雙向鍊錶也叫雙鏈表,是鍊錶的一種,是在作業系統中常用的資料結構,它的每個資料結點中都有兩個指標,分別指向直接後繼和直接前驅,其頭指標 head 是唯一確定的。所以,從雙向鍊錶中的任意乙個結點開始,都可以很方便地訪問它的前驅結點和後繼結點,這種資料結構形式使得雙向鍊錶在查詢時更加方便,特別是大量資料的遍歷。由於雙向鍊錶具有對稱性,能方便地完成各種插入、刪除等操作,但需要注意前後方向的操作。

/**

* double list structure

*/struct rt_list_node

;typedef

struct rt_list_node rt_list_t;

/**< type for lists. */

/* 獲取type結構體中member成員在這個結構體中的偏移  */

#define rt_container_of(ptr, type, member) ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

/* 初始化鍊錶物件 */

#define rt_list_object_init(object)

/* 獲取結構體變數的位址 */

#define rt_list_entry(node, type, member) rt_container_of(node, type, member)

/* 遍歷鍊錶 */

#define rt_list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next)

/* 安全地遍歷鍊錶 */

#define rt_list_for_each_safe(pos, n, head)

/* 迴圈遍歷head鍊錶中每乙個pos中的member成員 */

#define rt_list_for_each_entry(pos, head, member)

#define rt_list_for_each_entry_safe(pos, n, head, member)

/* 獲取鍊錶中的第乙個元素 */

#define rt_list_first_entry(ptr, type, member) rt_list_entry((ptr)->next, type, member)

/**

* @brief 初始化鍊錶

* * @param l 將被初始化的鍊錶

*/rt_inline void

rt_list_init

(rt_list_t *l)

在使用鍊錶的時候必須要進行初始化,將鍊錶的指標指向自己,為以後新增節點做準備 ,鍊錶的資料結構也是需要記憶體空間的,所以也需要進行記憶體的申請.

描述:其初始化完成後可以檢查一下鍊錶初始化是否成功,判斷鍊錶是不是空的就行了,因為初始化完成的時候,鍊錶肯定是空的,注意,在初始化鍊錶的時候其實鍊錶就是煉表頭,需要申請記憶體

rt_inline void 	rt_list_insert_after (rt_list_t *l, rt_list_t *n)

/** * @brief insert a node after a list

* * @param l 操作的鍊錶

* @param n 將要被插入的新節點

* * @param n 將要被插入的新節點

* @param l 操作鍊錶

刪除節點與新增節點一樣,其實刪除節點更簡單,只需要知道刪除哪個節點即可,把該節點前後的節點鏈結起來,那它就刪除了,然後該節點的指標指向節點本身即可,不過要注意的是也要講該節點的記憶體釋放掉,因為該節點是動態分配記憶體的,否則會導致記憶體洩漏,

/** * @brief 獲取鍊錶長度

* @param l the list to get.

*/rt_inline unsigned

intrt_list_len

(const rt_list_t *l)

return len;

}

rt_list_t成員是存放在節點中部或是尾部,不同型別的節點rt_list_t成員位置還不一樣,在遍歷整個鍊錶時,獲得的是後繼節點(前驅節點)的rt_list_t成員的位址,那如何根據rt_list_t成員的位址訪問節點中其他元素?儘管不同型別節點中rt_list_t成員位置不定,但是在確定型別節點中,rt_list_t成員的偏移是固定的,在獲取rt_list_t成員位址的情況下,計算出rt_list_t成員在該節點中的偏移,即(rt_list_t成員位址)-(rt_list_t成員偏移)=節點起始位址。關鍵在於如何計算不同型別節點中rt_list_t成員偏移。rt-thread中給出的相應演算法如下:

/**

* rt_list_for_each - iterate over a list

* @pos: 指向宿主結構的指標,在for迴圈中是乙個迭代變數

* @head: 煉表頭

*/#define rt_list_for_each(pos, head) \

for (pos = (head)->next; pos != (head); pos = pos->next)

/**

* rt_container_of - 就是通過結構體變數中某個成員的首位址進而獲得整個結構體變數的首位址

* */

#define rt_container_of(ptr, type, member) \

((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

(1)作用:知道乙個結構體中某個元素的指標,反推這個結構體變數的指標。有了rt_container_of巨集,我們可以從乙個元素的指標得到整個結構體變數的指標,繼而得到結構體中其它元素的指標。

(2)type 關鍵字的作用是:type (a)時由變數a得到a的型別,所以type 的作用就是由變數名得到變數的資料型別。

(3)這個巨集的工作原理:先用type 得到member元素的型別,將member成員的指標轉成自己型別的指標,然後用這個指標減去該元素相對於整個結構體變數的偏移量之後得到的就是整個結構體變數的首位址了,再把這個位址強制型別轉換為type *即可。

Rt Thread之雙向鍊錶學習

struct rt list node typedef struct rt list node rt list t 第一步 看的時候主要是看原來的圖 l next 就是node2,因為要新插入乙個,node2往後退 所以l next prev 就指向新插入的節點。node2的前乙個是n 第二步 原來...

rt thread隨筆4補充 雙向鍊錶

typedef struct dnode dnode,doublelist 1 struct rt list node 2 6typedef struct rt list node rt list t rt list t 型別的節點裡面有兩個 rt list t 型別的節點指標 next 和 pre...

mysql 雙向鍊錶 雙向鍊錶

雙向鍊錶是鍊錶變型,相比於單鏈表導航或者是向前和向後的兩種方式。以下是重要的術語來理解雙向鍊錶的概念 link 鍊錶的每個鏈路儲存資料稱為乙個元素。linkedlist linkedlist包含連線鏈結到名為首先第乙個鏈結,並稱為最後的最後乙個鏈結 last 雙向鍊錶表示 按照如上圖中所示,以下是要...