核心連結串列
阿新 • • 發佈:2020-12-12
核心連結串列
核心連結串列是純粹的連結串列結構,只有向前向後的兩個指標。將核心連結串列巢狀到我們自己所寫的,有資料的結構體裡面,這樣便可以將我們所輸入的資料連線起來。
參考檔案:/usr/include/btrfs/list.h
下面先來分析list.h的一些基本功能。
插入資料
核心連結串列有很多巧妙之處,比如這裡無論是頭插還是尾插都是呼叫函式__list_add來實現。
staticinlinevoid__list_add(structlist_head*xnew, structlist_head*prev, structlist_head*next) { next->prev=xnew; xnew->next=next; xnew->prev=prev; prev->next=xnew; }
頭插資料
staticinlinevoidlist_add(structlist_head*xnew,structlist_head*head)
{
__list_add(xnew,head,head->next);
}
尾插資料
staticinlinevoidlist_add_tail(structlist_head*xnew,structlist_head*head)
{
__list_add(xnew,head->prev,head);
}
刪除節點
將連結串列中的某個節點刪除。
static inline void list_del_init(struct list_head *entry) { __list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); } static inline void __list_del(struct list_head * prev, struct list_head * next) { next->prev = prev; prev->next = next; }
查詢節點
list_for_each將每個節點從連結串列中取出,list_entry將取出的節點進行運算,運算結果為使用者定義的結構體地址(該節點)。通過遍歷加list_entry運算,便可以訪問連結串列中每一個數據的值,也可以將符合某個資料的值的節點地址返回。
#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); \ pos = pos->next) #define list_entry(ptr, type, member) \ ((type*)((char * )(ptr) - (unsigned long)(&((type*)0)->member)))
核心連結串列的使用
建立一個.c檔案,包含/usr/include/btrfs/list.h。通過以上功能的分析,已經可以實現連結串列的增,刪,改,查的功能。
#include "list.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct kernel_list{
int data;
struct list_head kernel_head;
}my_kernel_list, *p_kernel_list;
int input_msg(char * msg)
{
// 讓使用者輸入新的資料
int num ;
printf("%s:" , msg);
scanf("%d" , &num);
while(getchar() != '\n');
return num;
}
p_kernel_list new_node()
{
p_kernel_list new = calloc(1, sizeof(my_kernel_list));
if(NULL == new)
{
printf("節點建立失敗\n");
return NULL;
}
INIT_LIST_HEAD(&new->kernel_head);
return new;
}
void insert_node(p_kernel_list head)
{
p_kernel_list new = new_node();
new->data = input_msg("請輸入頭插節點的資料");
list_add(&new->kernel_head, &head->kernel_head);
}
bool display_list(p_kernel_list head)
{
if (list_empty(&head->kernel_head))
{
printf("連結串列為空,列印失敗\n");
return false;
}
struct list_head *pos;
p_kernel_list tmp;
list_for_each(pos, &head->kernel_head)
{
tmp = list_entry(pos, my_kernel_list, kernel_head);
printf("data:%d\n", tmp->data);
}
}
void add_tail_node(p_kernel_list head)
{
p_kernel_list new = new_node();
new->data = input_msg("請輸入尾插節點的資料");
list_add_tail(&new->kernel_head, &head->kernel_head);
}
p_kernel_list find_node(p_kernel_list head, int fdata)
{
struct list_head *pos;
p_kernel_list tmp;
list_for_each(pos, &head->kernel_head)
{
tmp = list_entry(pos, my_kernel_list, kernel_head);
if (tmp->data == fdata)
{
return tmp;
}
}
return NULL;
}
bool del_node(p_kernel_list head)
{
int del_data = input_msg("請輸入需要刪除的資料");
p_kernel_list del_pos;
del_pos = find_node(head, del_data);
if (NULL == del_pos)
{
printf("刪除失敗,查無此資料\n");
return false;
}
list_del_init(&del_pos->kernel_head);
}
bool replace_node(p_kernel_list head)
{
p_kernel_list new = new_node();
p_kernel_list old_node;
int del_data = input_msg("請輸入需要被替換的資料");
old_node = find_node(head, del_data);
if (NULL == old_node)
{
printf("替換失敗,查無次資料\n");
return false;
}
int new_data = input_msg("請輸入新資料");
new->data = new_data;
list_replace_init(&old_node->kernel_head, &new->kernel_head);
}
int main(int argc, char const *argv[])
{
p_kernel_list head = new_node();
insert_node(head);
insert_node(head);
add_tail_node(head);
add_tail_node(head);
display_list(head);
del_node(head);
display_list(head);
replace_node(head);
display_list(head);
return 0;
}