国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【腳踢數(shù)據(jù)結構】內核鏈表

這篇具有很好參考價值的文章主要介紹了【腳踢數(shù)據(jù)結構】內核鏈表。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

  • (??? ),Hello我是祐言QAQ
  • 我的博客主頁:C/C++語言,Linux基礎,ARM開發(fā)板,軟件配置等領域博主??
  • 快上??,一起學習,讓我們成為一個強大的攻城獅!
  • 送給自己和讀者的一句雞湯??:集中起來的意志可以擊穿頑石!
  • 作者水平很有限,如果發(fā)現(xiàn)錯誤,可在評論區(qū)指正,感謝??

????????內核鏈表(Kernel Linked List)是操作系統(tǒng)內核中常用的一種數(shù)據(jù)結構,用于管理和維護一系列數(shù)據(jù)元素(節(jié)點)。它也是一種線性數(shù)據(jù)結構,其中每個節(jié)點包含了數(shù)據(jù)元素本身以及指向下一個節(jié)點的指針。內核鏈表在操作系統(tǒng)中廣泛應用于管理進程、文件描述符、內存分配等諸多場景。

一、內核鏈表概述

????????內核鏈表通常由一個特定的數(shù)據(jù)結構定義,該數(shù)據(jù)結構包含一個或多個指向鏈表中首個和最后一個節(jié)點的指針,以及其他用于操作和管理鏈表的屬性。在C語言中,內核鏈表的定義示例:

//數(shù)據(jù)
typedef int Datatype;

//節(jié)點(大結構體)
typedef struct Kernel_node
{
	Datatype data;			//數(shù)據(jù)域
	struct kernel_list list;	//指針域
}k_node;

//指針節(jié)點(小結構體)
struct kernel_list {
    struct kernel_list *prev;//前驅指針
    struct kernel_list *next;//后繼指針
};


? ? ? ? kernel_list結構體定義了一個內核鏈表的節(jié)點,其中prev指向前一個節(jié)點,next指向下一個節(jié)點,這一點在某種意義上與常規(guī)的雙向循環(huán)鏈表一致,但是還是有區(qū)別的。我們再來看看之前所學習的雙向循環(huán)鏈表的節(jié)點定義:

//數(shù)據(jù)
typedef int Datatype;

//節(jié)點
typedef struct Node
{
	DataType data;		//數(shù)據(jù)域
	struct Node *prev;	//指針域:前驅指針
	struct Node *next;	//指針域:后繼指針
}node;

? ? ? ? 這樣一對比,就會發(fā)現(xiàn)常規(guī)鏈表與內核鏈表最大的區(qū)別就是嵌套,內核鏈表的節(jié)點結構通常嵌套在某個容器數(shù)據(jù)結構中,可以理解為能單獨對指針域進行操作,而不影響數(shù)據(jù)。

【腳踢數(shù)據(jù)結構】內核鏈表,腳踢數(shù)據(jù)結構,數(shù)據(jù)結構,鏈表,算法,linux

?所以這也暴露了常規(guī)鏈表的缺陷:

????????(1)每一種應用中,節(jié)點都是特殊的,導致每一條鏈表都是特殊的,因此每一種鏈表的增刪查改這些算法也都是特殊的;

????????(2)當一個節(jié)點處于變化的數(shù)據(jù)結構網絡中的時候,節(jié)點指針無法指向穩(wěn)定不變的節(jié)點。

? ? ? ? 這樣的描述或許不能讓你有直觀的感覺,但當你往下看,真正去理解了內核鏈表再回過頭來,你就會豁然開朗。

二、內核鏈表的原理

????????內核鏈表的節(jié)點結構通常嵌套在某個容器數(shù)據(jù)結構中,以實現(xiàn)緊密關聯(lián)。節(jié)點結構中至少包含兩個指針,一個指向前一個節(jié)點,一個指向后一個節(jié)點。這樣的設計使得在鏈表中插入、刪除節(jié)點的操作更加高效,無需像數(shù)組那樣移動大量元素。我們可以這樣理解:

????????(1)將鏈表的結構抽象出來,去除節(jié)點中的具體數(shù)據(jù),只保留邏輯的雙向指針,形成一條只包含邏輯的“純粹的鏈表”。

????????(2)將鏈表“寄宿”于具體的數(shù)據(jù)節(jié)點之中,使他貫穿這些節(jié)點,可以借助一定的方式通過“純粹鏈表“的指針域得到數(shù)據(jù)節(jié)點。

【腳踢數(shù)據(jù)結構】內核鏈表,腳踢數(shù)據(jù)結構,數(shù)據(jù)結構,鏈表,算法,linux

?? ? ? ? ? ?內核鏈表做到了將數(shù)據(jù)和邏輯(指針)分開,在紅色方框內的這樣只有前后兩指針的鏈表形式被稱為Linux標準雙向循環(huán)鏈表。

三、內核鏈表的操作

? ? ? ? 在學習內核鏈表的操作之前,我們先要來了解一下list.h文件。list.h 是一個常見的頭文件,通常用于實現(xiàn)內核鏈表(雙向鏈表)的相關功能。在 Linux 內核中,list.h 提供了一種高效的方式來操作鏈表,包括插入、刪除、遍歷等操作。完整的該文件可從網上各處找到,接下來我們將只舉例用到的結構體。

1. 節(jié)點聲明

//數(shù)據(jù)
typedef int Datatype;

//鏈表節(jié)點(大結構體)
typedef struct Kernel_node
{
	Datatype data;			//數(shù)據(jù)域
	struct list_head list;	//指針域
}k_node;

?????????list_head 是在list.h中已經定義好的指針域部分,我們可以將其稱之為小結構體,用它來構建“純粹鏈表”。


 struct list_head {
 	struct list_head *next, *prev;
 };

2.初始化鏈表

//初始化鏈表
k_node *init_kernel_list()
{
	k_node *head = malloc(sizeof(k_node));
	if (head==NULL)
	{
		perror("malloc");
		exit(0);
	}
	else
	{		
		INIT_LIST_HEAD(&(head->list));//帶參宏,初始化小結構體里面的這兩個指針成員

	}
	return head;
}

????????INIT_LIST_HEAD也是list.h中已經定義好的帶參宏,原型如下:

#define INIT_LIST_HEAD(ptr) do { \
	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

3.創(chuàng)建節(jié)點

//創(chuàng)建節(jié)點
k_node *create_kernel_node(Datatype data)
{
	k_node *new = malloc(sizeof(k_node));
	if (new != NULL)
	{
		new->data = data;
		new->list.next = NULL;
		new->list.prev = NULL;
	}
	return new;
}

4.遍歷鏈表


//遍歷鏈表
void display(k_node *head)
{
	struct list_head *pos = NULL;
	k_node *Node = NULL;
	list_for_each(pos, &(head->list))
	{
		Node = list_entry(pos, k_node, list);
		printf("%d ", Node->data);
	}
	printf("\n");
}

????????其中list_for_each和list_entry也是在list.h中定義好的帶參宏:


//遍歷鏈表的for循環(huán),每一次循環(huán)體內得到的就是一個小結構體指針
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)


//小結構體指針ptr,大結構體類型type,小結構體在大結構體內部的成員名
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

????????做完這些操作,我們就可以通過一個實例來驗證我們的操作是否正確,我們可以創(chuàng)建一個10個節(jié)點的鏈表并打印。

【腳踢數(shù)據(jù)結構】內核鏈表,腳踢數(shù)據(jù)結構,數(shù)據(jù)結構,鏈表,算法,linux

?????????實例代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "list.h"

//數(shù)據(jù)
typedef int Datatype;

//鏈表節(jié)點
typedef struct Kernel_node
{
	Datatype data;			//數(shù)據(jù)域
	struct list_head list;	//指針域
}k_node;

//初始化鏈表
k_node *init_kernel_list()
{
	k_node *head = malloc(sizeof(k_node));
	if (head==NULL)
	{
		perror("malloc");
		exit(0);
	}
	else
	{
		INIT_LIST_HEAD(&(head->list));
	}
	return head;
}

//創(chuàng)建節(jié)點
k_node *create_kernel_node(Datatype data)
{
	k_node *new = malloc(sizeof(k_node));
	if (new != NULL)
	{
		new->data = data;
		new->list.next = NULL;
		new->list.prev = NULL;
	}
	return new;
}

//遍歷鏈表
void display(k_node *head)
{
	struct list_head *pos = NULL;
	k_node *Node = NULL;
	list_for_each(pos, &(head->list))
	{
		Node = list_entry(pos, k_node, list);
		printf("%d ", Node->data);
	}
	printf("\n");
}

int main(int argc, char const *argv[])
{
	k_node *head = init_kernel_list();
	for (int i = 0; i < 10; ++i)
	{
		k_node *new = create_kernel_node(i+1);

		//插入節(jié)點到鏈表
		list_add_tail(&(new->list), &(head->list));
	}

	//遍歷鏈表
	display(head);

	return 0;
}

? ? ? ? 更安全的遍歷列表方法補充:

void display2(k_node *head)
{
	struct list_head *pos = NULL;
	struct list_head *n = NULL;//為了防止你在遍歷的時候,刪除節(jié)點,找不到下一個節(jié)點的地址
	k_node *Node;
	list_for_each_safe(pos, n, &(head->list))
	{
		Node = list_entry(pos, k_node, list);
		printf("%d ", Node->data);
	}
	printf("\n");
}

void display3(k_node *head)
{
	k_node *pos = NULL;
	list_for_each_entry(pos, &(head->list), list)
	{
		printf("%d ", pos->data);
	}
	printf("\n");
}

void display4(k_node *head)
{
	k_node *pos = NULL;
	k_node *n = NULL;
	list_for_each_entry_safe(pos, n, &(head->list), list)
	{
		printf("%d ", pos->data);
	}
	printf("\n");
}

5.刪除節(jié)點

void delete_node(k_node *head, Datatype data)
{
	struct list_head *pos = NULL;
	struct list_head *n = NULL;//為了防止你在遍歷的時候,刪除節(jié)點,找不到下一個節(jié)點的地址
	k_node *Node = NULL;
	list_for_each_safe(pos, n, &(head->list))
	{
		Node = list_entry(pos, k_node, list);
		if (Node->data == data)
		{
			list_del(&(Node->list));
		}		
	}
}

6.移動節(jié)點

void move_node_head(k_node *head, Datatype d1, Datatype d2)
{
	k_node *p1 = find_node(head, d1);
	k_node *p2 = find_node(head, d2);
	if (p1==NULL || p2==NULL)
	{
		return;
	}
	list_move(&(p1->list), &(p2->list));
}

void move_node_tail(k_node *head, Datatype d1, Datatype d2)
{
	k_node *p1 = find_node(head, d1);
	k_node *p2 = find_node(head, d2);
	if (p1==NULL || p2==NULL)
	{
		return;
	}
	list_move_tail(&(p1->list), &(p2->list));//尾插
}
	//移動節(jié)點
	move_node_head(head, 1, 7);
	display4(head);

【腳踢數(shù)據(jù)結構】內核鏈表,腳踢數(shù)據(jù)結構,數(shù)據(jù)結構,鏈表,算法,linux

7.判斷是否為空鏈表

k_node *list_empty(k_node *head)
{
	return head->next == head;
}

8.合并鏈表

int main(int argc, char const *argv[])
{
	k_node *head = init_kernel_list();
	for (int i = 0; i < 10; ++i)
	{
		k_node *new = create_kernel_node(i+1);

		//插入節(jié)點到鏈表
		list_add_tail(&(new->list), &(head->list));//尾插
	}
	display4(head);

	k_node *head1 = init_kernel_list();
	for (int i = 10; i < 15; ++i)
	{
		k_node *new = create_kernel_node(i+1);

		// 插入節(jié)點到鏈表
		list_add_tail(&(new->list), &(head1->list));//尾插
	}
	display4(head1);

	if (list_empty(&(head1->list)))
	{
		printf("這是空鏈表\n");
	}
	else
	{
		printf("非空,可合并\n");
	}
	// head的頭節(jié)點下面的第一個節(jié)點的前驅指針會斷開,head的尾節(jié)點的后繼指針會斷開,head后面不能在使用
	list_splice_init(&(head->list), &(head1->list));

	display4(head1);

	return 0;
}

????????運行結果:

【腳踢數(shù)據(jù)結構】內核鏈表,腳踢數(shù)據(jù)結構,數(shù)據(jù)結構,鏈表,算法,linux

?

留個作業(yè)吧

????????用內核鏈表創(chuàng)建一個數(shù)據(jù)集合,初始包含數(shù)據(jù):1 2 3 4 5 6 7 8 9 ,將其重新排列成:9 7 5 3 1 2 4 6 8 (奇數(shù)降序,偶數(shù)升序)并顯示出來。

????????答案評論區(qū)見!

四、總結

????????與一般鏈表相比,內核鏈表有一些特點和優(yōu)勢:

????????1.容器結構體: 在內核鏈表中,節(jié)點通常嵌套在某個數(shù)據(jù)結構中,這個數(shù)據(jù)結構即所謂的容器結構體。這種設計可以讓數(shù)據(jù)元素和鏈表節(jié)點緊密關聯(lián),方便數(shù)據(jù)的操作和管理。

????????2.穩(wěn)定性和預測性: 內核鏈表在操作系統(tǒng)內核中廣泛應用,而且內核鏈表的實現(xiàn)通常被優(yōu)化為在各種情況下都能夠穩(wěn)定和預測地工作,不容易受到異常情況的影響。

????????3.特定操作: 內核鏈表通常提供一系列針對特定操作的函數(shù),如插入、刪除、遍歷等。這些函數(shù)經過精心的設計和優(yōu)化,能夠高效地處理鏈表操作。

????????總之,內核鏈表是操作系統(tǒng)內核中的一種重要數(shù)據(jù)結構,用于高效地管理各種資源和數(shù)據(jù)。它與一般鏈表相比,更注重穩(wěn)定性和性能優(yōu)化,以滿足操作系統(tǒng)的特定需求。

????????更多C語言Linux系統(tǒng)、ARM板實戰(zhàn)數(shù)據(jù)結構相關文章,關注專欄:

? ?手撕C語言

? ? ? ? ? ? 玩轉linux

????????????????????腳踢數(shù)據(jù)結構

?? ? ? ? ? ? ? ? ?? ? ? ? ? 6818(ARM)開發(fā)板實戰(zhàn)文章來源地址http://www.zghlxwxcb.cn/news/detail-637404.html

??寫在最后

  • 今天的分享就到這啦~
  • 覺得博主寫的還不錯的煩勞?一鍵三連喔~
  • ??感謝關注??

到了這里,關于【腳踢數(shù)據(jù)結構】內核鏈表的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【腳踢數(shù)據(jù)結構】圖(純享版)

    【腳踢數(shù)據(jù)結構】圖(純享版)

    (??? ),Hello我是 祐言QAQ 我的博客主頁:C/C++語言,Linux基礎,ARM開發(fā)板,軟件配置等領域博主?? 快上??,一起學習,讓我們成為一個強大的攻城獅! 送給自己和讀者的一句雞湯??: 集中起來的意志可以擊穿頑石! 作者水平很有限,如果發(fā)現(xiàn)錯誤,可在評論區(qū)指正,感謝

    2024年02月12日
    瀏覽(18)
  • 【腳踢數(shù)據(jù)結構】隊列(順序和鏈式)

    【腳踢數(shù)據(jù)結構】隊列(順序和鏈式)

    (??? ),Hello我是 祐言QAQ 我的博客主頁:C/C++語言,Linux基礎,ARM開發(fā)板,軟件配置等領域博主?? 快上??,一起學習,讓我們成為一個強大的攻城獅! 送給自己和讀者的一句雞湯??: 集中起來的意志可以擊穿頑石! 作者水平很有限,如果發(fā)現(xiàn)錯誤,可在評論區(qū)指正,感謝??

    2024年02月12日
    瀏覽(31)
  • Linux內核數(shù)據(jù)結構 散列表

    Linux內核數(shù)據(jù)結構 散列表

    在Linux內核中,散列表(哈希表)使用非常廣泛。本文將對其數(shù)據(jù)結構和核心函數(shù)進行分析。和散列表相關的數(shù)據(jù)結構有兩個: hlist_head 和 hlist_node 對應的結構如下 hash_table 為散列表(數(shù)組),其中的元素類型為 struct hlist_head 。以 hlist_head 為鏈表頭的鏈表,其中的節(jié)點 hash 值

    2024年02月10日
    瀏覽(25)
  • 【數(shù)據(jù)結構與算法】鏈表

    【數(shù)據(jù)結構與算法】鏈表

    對于順序表存在一些缺陷: 中間/頭部的插入刪除,時間復雜度為O(N) 。頭部插入需要挪動后面的元素 增容需要申請新空間,拷貝數(shù)據(jù),釋放舊空間。會有不小的消耗。 增容一般是呈2倍的增長,勢必會有一定的空間浪費。例如當前容量為100,滿了以后增容到200,我們再繼續(xù)插

    2023年04月09日
    瀏覽(26)
  • 【算法與數(shù)據(jù)結構】鏈表

    【算法與數(shù)據(jù)結構】鏈表

    鏈表是由一串節(jié)點串聯(lián)在一起的,鏈表的每個節(jié)點存儲兩個信息:數(shù)據(jù)+下一個節(jié)點的地址 分清楚兩個概念:什么是內存內部,什么是程序內部 內存內部: 信息存儲在內存空間里的 程序內部: 通過什么信息,去操作結構 如果想操作鏈表的話,我們依靠的是程序內部的信息,

    2024年02月03日
    瀏覽(27)
  • 02-鏈表 (數(shù)據(jù)結構和算法)

    3.1 鏈表的基本概念 前面我們在學習順序表時,線性表的順序存儲結構的特點是邏輯關系上相鄰的兩個數(shù)據(jù)元素在物理位置上也是相鄰的。我們會發(fā)現(xiàn)雖然順序表的查詢很快,時間復雜度為O(1),但是增刪的效率是比較低的,因為每一次增刪操作都伴隨著大量的數(shù)據(jù)元素移動。為

    2024年02月16日
    瀏覽(26)
  • Python數(shù)據(jù)結構與算法-數(shù)據(jù)結構(列表、棧、隊列、鏈表)

    Python數(shù)據(jù)結構與算法-數(shù)據(jù)結構(列表、棧、隊列、鏈表)

    數(shù)據(jù)結構是指相互之間存在這一種或者多種關系的數(shù)據(jù)元素的集合和該集合中元素之間的關系組成。 簡單來說,數(shù)據(jù)結構就是設計數(shù)據(jù)以何種方式組織并存儲在計算機中。 比如:列表、集合與字典等都是一種數(shù)據(jù)結構。 N.Wirth:“程序=數(shù)據(jù)結構+算法” 數(shù)據(jù)結構按照其 邏輯結

    2024年02月08日
    瀏覽(36)
  • Linux內核代碼中常用的數(shù)據(jù)結構

    Linux內核代碼中常用的數(shù)據(jù)結構

    Linux內核代碼中廣泛使用了數(shù)據(jù)結構和算法,其中最常用的兩個是鏈表和紅黑樹。 Linux內核代碼大量使用了鏈表這種數(shù)據(jù)結構。鏈表是在解決數(shù)組不能動態(tài)擴展這個缺陷而產生的一種數(shù)據(jù)結構。鏈表所包含的元素可以動態(tài)創(chuàng)建并插入和刪除。 鏈表的每個元素都是離散存放的,

    2024年02月12日
    瀏覽(18)
  • 【數(shù)據(jù)結構和算法】奇偶鏈表

    【數(shù)據(jù)結構和算法】奇偶鏈表

    Java基礎合集 數(shù)據(jù)結構與算法合集 設計模式合集 多線程合集 分布式合集 ES合集 其他系列文章導航 文章目錄 前言 一、題目描述 二、題解 2.1?方法一:分離節(jié)點后合并 三、代碼 3.1?方法一:分離節(jié)點后合并 四、復雜度分析 4.1?方法一:分離節(jié)點后合并 這是力扣的 328 題,難

    2024年01月20日
    瀏覽(36)
  • 【數(shù)據(jù)結構與算法】雙向鏈表

    【數(shù)據(jù)結構與算法】雙向鏈表

    作者:舊夢拾遺186 專欄:數(shù)據(jù)結構成長日記 ? 帶頭雙向循環(huán)鏈表:結構最復雜,一般用在單獨存儲數(shù)據(jù)。實際中使用的鏈表數(shù)據(jù)結構,都是帶頭雙向循環(huán)鏈表。另外這個結構雖然結構復雜,但是使用代碼實現(xiàn)以后會發(fā)現(xiàn)結構會帶來很多優(yōu)勢,實現(xiàn)反而簡單了。 現(xiàn)在我們來通

    2024年02月11日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包