我所理解的核心鍊錶

2021-10-06 12:59:14 字數 4680 閱讀 9922

核心鍊錶

核心鍊錶與傳統鍊錶不一樣,傳統鍊錶資料域與指標域都是使用者自定義的,而是核心鍊錶資料域是使用者定義,但是指標域是核心煉表頭檔案中已經定義好的了。

核心鍊錶 :頭節點無效,雙向迴圈鍊錶

指標域結構體的結構

核心煉表頭檔案:kernel_list.h

struct list_head 

;

設計節點模型
struct list_node

;

學習核心鍊錶的增刪改查

初始化空鍊錶?

1)為頭節點申請堆空間

head = (struct list_node *)malloc(sizeof(struct list_node));

2)為頭節點指標域賦值

init_list_head(&(head->list));

解析:kernel_list.h ->49行:

#define init_list_head(ptr) 

dowhile(0

)

插入資料到鍊錶中

1)為新的節點申請空間

struct list_node *node =

null

; node =

(struct list_node *

)malloc

(sizeof

(struct list_node)

);

2)為資料域賦值

node->a = num

3)呼叫尾插/頭插的函式

尾插:list_add_tail(&(node->list),&(head->list));

頭插:list_add(&(node->list),&(head->list));

分析插入資料函式介面:

函式一: 將乙個節點new插入兩個節點next與prev之間。

static

inline

void

__list_add

(struct list_head *new,

-> 新節點的指標域結構體的位址

struct list_head *prev,

-> 新節點前乙個節點的指標域結構體的位址

struct list_head *next)

-> 新節點後乙個節點的指標域結構體的位址

函式二: 尾插

list_add_tail – add a new entry   -> 在鍊錶尾部新增乙個節點

insert a new entry before the specified head -> 尾插其實相當於在頭節點的前面插入乙個新的節點。

static

inline

void

list_add_tail

(struct list_head *new,

-> 新節點的指標域結構體的位址

struct list_head *head)

-> 頭節點的指標域結構體的位址

函式三: 頭插

list_add – add a new entry

insert a new entry after the specified head.

-> 在頭節點之後插入乙個資料

static

inline

void

list_add

(struct list_head *new,

-> 新節點的指標域結構體的位址

struct list_head *head)

-> 頭節點的指標域結構體的位址

往後遍歷鍊錶

20%

int

show_list_node

(struct list_node *head)

return0;

}或者80%

intshow_list

(struct list_node *head)

return0;

}

往前遍歷鍊錶

int

backward_show_list_node

(struct list_node *head)

return0;

}

分析:

list_entry – get the struct for this entry -> 列出某個節點內容

#define list_entry(ptr, type, member)

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

ptr: the &struct list_head pointer. -> 指向節點中指標域的結構體的位址 p

type: the type of the struct this is embedded in -> 大的結構體的型別 struct list_node

member: the name of the list_struct within the struct -> 小的結構體在大的結構體中變數叫什麼 list

返回值:指向大的結構體的指標。

list_for_each - iterate over a list -> 將整條鍊錶從頭開始往後遍歷一遍

#define list_for_each(pos, head)

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

list_for_each_prev - iterate over a list backwards -> 將整條鍊錶從頭開始往前遍歷一遍

#define list_for_each_prev(pos, head)

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

list_for_each_entry ->往後遍歷,其實就是list_for_each與list_entry結合。

#define list_for_each_entry(pos, head, member)

for (pos = list_entry((head)->next, typeof(*pos), member);

&pos->member != (head);

pos = list_entry(pos->member.next, typeof(*pos), member))

struct list_node

;struct list_node a;

fgets

(a.name,10,

stdin);

add_list_tail

(head,

"ggy"

,"12345678901"

,"gzdx",10

,"classmate");

使用者 -> buf:num if

(strncmp

(buf,

"num")==

0)if(

strncmp

(buf,

"relationship")==

0)使用者 ->

10-> 遍歷鍊錶

list_for_each_entry

(p,&

(head->list)

,list)

根據特徵值刪除節點

int

delete_list_node

(struct list_node *head,

int num)

}return0;

}或者intdelete_list_node

(struct list_node *head,

int num)

}return0;

}list_for_each_entry_safe -> 其實是list_for_each_safe與list_entry結合。

list_for_each_entry -> 其實是list_for_each與list_entry結合。

#define list_for_each_entry_safe(pos, n, head, member) \

for (pos = list_entry((head)->next, typeof(*pos), member), \

n = list_entry(pos->member.next, typeof(*pos), member); \

&pos->member != (head); \

pos = n, n = list_entry(n->member.next, typeof(*n), member))

釋放整條鍊錶的空間

int

delete_list

(struct list_node *head)

list_del(&

(head->list));

free

(head)

;return0;

}

我所理解的前端

轉眼間,在鵝廠的實習已經過去三個多月,涉及到實習生轉正留用的考核流程也逐步開始了。帶著一堆疑問,以及自己實習期間的心得體會,與導師暢談了一番。他作為資深前端工程師,就前端領域及我個人未來的職業規劃等方面分享了他自己的經驗。這次與導師的溝通讓我受益匪淺,現簡單總結如下。前端知識學習路線 首先,當然是就...

我所理解的陣列

陣列 一 一維陣列 1 陣列的建立 陣列顧名思義是含有相同元素的集合,類似我們高中數學所學習的集合 例如int arr 10 char arr1 2 float arr2 3 double arr3 5 注意 切記 這個中要給常量,不能使用變數。2 陣列的初始化 初始化是指 在陣列的建立同時並賦予合...

我所理解的OpenSocial

昨天在google參加了opensocial的講座,通過三位opensocial工程師的精彩演講,我對這個東西有了一些簡單的理解。下面就把我所理解的opensocial,也算是筆記整理在這裡。1 為什麼會有opensocial?當前社會是乙個網路的社會,當前的網路是乙個社會性的網路,sns遍地開花到...