生活随笔
收集整理的這篇文章主要介紹了
Linux C 数据结构---链表(单向链表)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?上一篇我們講到了線性表,線性表就是數據元素都一一對應,除只有唯一的前驅,唯一的后繼。
???????線性表存儲結構分為順序存儲、鏈式存儲。
???????順序存儲的優點:
?????? 順序存儲的缺點:
???????鏈表就是典型的鏈式存儲,將線性表L = (a0,a1,a2,........an-1)中個元素分布在存儲器的不同存儲塊,成為結點(Node),通過地址或指針建立他們之間的練習,所得到的存儲結構為鏈表結構。表中元素ai的結點形式如下:
其中,結點的data域存放數據元素ai,而next域是一個指針,指向ai的直接后繼a(i+1)所在的結點。于是,線性表L=(a0,a1,......an-1)的結構如圖:
?
一、節點類型描述:
[cpp]?view plaincopy
typedef?struct?node_t?? {?? ????data_t?data;??? ????struct?node_t?*next;?? }linknode_t,*linklist_t;??
也可這樣表示:
[cpp]?view plaincopy
struct?node_t?? {?? ????data_t?data;??? ????struct?node_t?*next;?? }?? typedef?struct?node_t?linknode_t;?? typedef?struct?node_t?*linklist_t;??
若說明
linknode_t? A;
linklist_t p? = &A;
則結構變量A為所描述的節點,而指針變量P為指向此類型節點的指針(p的值為節點的地址);
這樣看來 linknode_t? linklist_t 的作用是一樣的,那為什么我們要定義兩個數據類型(同一種)呢?主要為了代碼的可讀性,我們要求標識符要望文識義,便于理解;
1、linknode_t? *pnode? 指向一個節點;
2、linklist_t list? 指向一個整體
二、頭結點 head
??????? 我們在前篇提到的順序存儲線性表,如何表達一個空表{ },是通過list->last = -1來表現的,所謂的空表就是數據域為NULL,而我們的鏈表有數據域和指針域,我們如何表現空鏈表呢?這時,就引入了頭結點的概念,頭結點和其他節點數據類型一樣,只是數據域為NULL,head->next = NULL,下面我們看一個創建空鏈表的函數,如何利用頭結點來創建一個空鏈表:
[cpp]?view plaincopy
linklist_t?CreateEmptyLinklist()?? {?? ????linklist_t?list;?? ?? ????list?=?(linklist_t)malloc(sizeof(linknode_t));?? ????if?(NULL?!=?list)?{?? ????????list->next?=?NULL;?? ????}?? ????return?list;?? }??
只要頭結點,鏈表就還在!
?
三、鏈表基本運算的相關算法
???????? 鏈表的運算除了上面的創建空鏈表,還有數據的插入,刪除,查找等函數,鏈表的運算有各種實現方法,如何寫出一個高效的,封裝性較好的函數是我們要考慮的,比如數據插入函數,我們就要盡可能考慮所有能出現的結果,比如:1)如果需插入數據的鏈表是個空表;2)所插入的位置超過了鏈表的長度;如果我們的函數能包含所有能出現的情況,不僅能大大提高我們的開發效率,也會減少代碼的錯誤率。下面,我們來看看下面的這個鏈表的插入函數的實現:
[cpp]?view plaincopy
int?InsertLinklist(linklist_t?list,?int?at,?data_t?x)?? {?? ????linknode_t?*node_prev,?*node_at,?*node_new;?? ????int?pos_at;?? ????int?found?=?0;?? ?? ????if?(NULL?==?list)?return?-1;?? ?? ?????? ????if?(at?<?0)?return?-1;?? ?????? ?????? ????node_new?=?malloc(sizeof(linknode_t));?? ????if?(NULL?==?node_new)??? ????{?? ????????return?-1;?? ????}?? ????node_new->data?=?x;??? ????node_new->next?=?NULL;??? ?? ?????? ????node_prev?=?list;?? ????node_at?=?list->next;??? ????pos_at?=?0;?? ????while?(NULL?!=?node_at)??? ????{?? ????????if?(pos_at?==?at)?? ????????{?? ????????????found?=?1;??? ????????????break;???????????? ????????}?? ?? ?????????? ????????node_prev?=?node_at;??? ????????node_at?=?node_at->next;?? ????????pos_at++;?? ????}?? ?? ???????? ????if?(found)??? ????{?? ?????????? ????????node_new->next?=?node_at;?? ????????node_prev->next?=?node_new;?? ????}??? ????else??? ????{?? ?????????? ????????node_prev->next?=?node_new;?? ????}?? ??????
這個插入函數可利用性就非常高。
?
下面講一個完整鏈表代碼貼出:
listlink.h
[cpp]?view plaincopy
#ifndef?_LNK_LIST_H_?? #define?_LNK_LIST_H_?? ?? typedef?int?data_t;?? ?? typedef?struct?node_t?{?? ????data_t?data;?? ????struct?node_t?*next;?? }?linknode_t,?*linklist_t;?? ?? linklist_t?CreateEmptyLinklist();?? ?? void?DestroyLinklist(linklist_t?list);?? ?? void?ClearLinklist(linklist_t?list);?? ?? int?EmptyLinklist(linklist_t?list);?? ?? int?LengthLinklist(linklist_t?list);?? ?? int?GetLinklist(linklist_t?list,?int?at,?data_t?*x);?? ?? int?SetLinklist(linklist_t?list,?int?at,?data_t?x);?? ?? int?InsertLinklist(linklist_t?list,?int?at,?data_t?x);?? ?? int?DeleteLinklist(linklist_t?list,?int?at);?? ?? linklist_t?ReverseLinklist(linklist_t?list);?? ?? #endif?/*?_LNK_LIST_H_?*/??
linklist.c
[cpp]?view plaincopy
#include?<stdio.h>?? #include?<stdlib.h>?? #include?"linklist.h"?? ?? linklist_t?CreateEmptyLinklist()?? {?? ????linklist_t?list;?? ????list?=?(linklist_t)malloc(sizeof(linknode_t));?? ?? ????if?(NULL?!=?list)?{?? ????????list->next?=?NULL;?? ????}?? ?? ????return?list;?? }?? ?? void?DestroyLinklist(linklist_t?list)?? {?? ????if?(NULL?!=?list)?{?? ????????ClearLinklist(list);?? ????????free(list);?? ????}?? }?? ?? void?ClearLinklist(linklist_t?list)?? {?? ????linknode_t?*node;??? ????if?(NULL?==?list)?return;?? ?? ????while?(NULL?!=?list->next)?{?? ????????node?=?list->next;?? ????????list->next?=?node->next;?? ????????free(node);?? ????}?? ????return;?? }?? ?? int?LengthLinklist(linklist_t?list)?? {?? ????int?len?=?0;?? ????linknode_t?*node;??? ?? ????if?(NULL?==?list)?return?-1;?? ?? ????node?=?list->next;??? ????while?(NULL?!=?node)?{?? ????????len++;?? ????????node?=?node->next;?? ????}?? ????return?len;?? }?? ?? int?EmptyLinklist(linklist_t?list)?? {?? ????if?(NULL?!=?list)?{?? ????????if?(NULL?==?list->next)?{?? ????????????return?1;?? ????????}?else?{?? ????????????return?0;?? ????????}?? ????}?else?{?? ????????return?-1;?? ????}?? }?? ?? int?GetLinklist(linklist_t?list,?int?at,?data_t?*x)?? {?? ????linknode_t?*node;????? ????int?pos;?????????? ?? ????if?(NULL?==?list)?return?-1;?? ?????? ????if?(at?<?0)?return?-1;?? ?????? ????node?=?list->next;?? ????pos?=?0;?? ????while?(NULL?!=?node)?{?? ????????if?(at?==?pos)?{?? ????????????if?(NULL?!=?x)?{?? ????????????????*x?=?node->data;?? ????????????}?? ????????????return?0;????????????? ????????}?? ?????????? ????????node?=?node->next;?? ????????pos++;?? ????}?? ????return?-1;?? }?? ?? ?? ?? int?SetLinklist(linklist_t?list,?int?at,?data_t?x)?? {?? ????linknode_t?*node;??? ????int?pos;?? ????int?found?=?0;?? ?? ????if?(!list)?return?-1;?? ?????? ????if?(at?<?0)?return?-1;?? ?????? ????node?=?list->next;?? ????pos?=?0;?? ????while?(NULL?!=?node)?{?? ????????if?(at?==?pos)?{??? ????????????found?=?1;??? ????????????node->data?=?x;?? ????????????break;???????????? ????????}?? ?????????? ????????node?=?node->next;?? ????????pos++;?? ????}?? ????if?(1?==?found)?{?? ????????return?0;?? ????}?else?{?? ????????return?-1;?? ????}?? }?? ?? int?InsertLinklist(linklist_t?list,?int?at,?data_t?x)?? {?? ????? ? ? ? ? ?? ????linknode_t??*node_prev,?*node_at,?*node_new;?? ????int?????pos_at;?? ????int?????????found?=?0;?? ?? ????if?(NULL?==?list)?return?-1;?? ?? ?????? ????if?(at?<?0)?return?-1;?? ?? ????node_new?=?malloc(sizeof(linknode_t));?? ????if?(NULL?==?node_new)?{?? ????????return?-1;?? ????}?? ????node_new->data?=?x;??? ????node_new->next?=?NULL;?? ?? ????node_prev?=?list;?? ????node_at?=?list->next;?? ????pos_at?=?0;?? ????while?(NULL?!=?node_at)?{?? ????????if?(pos_at?==?at)?{?? ????????????? ? ??? ????????????found?=?1;?? ????????????break;???????????? ????????}?? ?????????? ????????node_prev?=?node_at;?? ????????node_at?=?node_at->next;?? ????????pos_at++;?? ????}?? ?????? ????if?(found)?{?? ?????????? ????????node_new->next?=?node_at;?? ????????node_prev->next?=?node_new;?? ????}?else?{?? ????????? ? ? ? ?? ????????node_prev->next?=?node_new;?? ????}?? ????return?0;?? }?? ?? int?DeleteLinklist(linklist_t?list,?int?at)?? {?? ????? ? ? ? ?? ?? ????linknode_t??*node_prev,?*node_at;?? ????int?????pos_at;?? ????int?????????found?=?0;?? ?? ????if?(!list)?return?-1;?? ?????? ????if?(at?<?0)?return?-1;?? ?? ????node_prev?=?list;?? ????node_at?=?list->next;?? ????pos_at?=?0;??? ?? ????while?(NULL?!=?node_at)?{?? ????????if?(pos_at?==?at)?{?? ????????????? ? ??? ????????????found?=?1;?? ????????????break;???????????? ????????}?? ?????????? ????????node_prev?=?node_at;?? ????????node_at?=?node_at->next;?? ????????pos_at++;?? ????}?? ????if?(found)?{?? ?????????? ????????node_prev->next?=?node_at->next;?? ????????free(node_at);?? ????????return??0;?? ????}?else?{?? ????????return?-1;?? ????}?? }?? ?? linklist_t?ReverseLinklist(linklist_t?list)?? {?? ????linknode_t?*node;????? ????linknode_t?*node_prev;???? ????linknode_t?*node_next;??? ? ?? ????if?(NULL?==?list)?return?NULL;?? ????node_prev?=?NULL;?? ????node?=?list->next;?? ????while?(NULL?!=?node)?{?? ????????? ? ? ? ?? ????????node_next?=?node->next;?? ????????? ? ? ? ? ?? ?? ????????if?(NULL?==?node_next)?{?? ????????????list->next?=?node;?? ????????}?? ?? ????????? ? ? ? ??????? ????????node->next?=?node_prev;???????? ????????? ? ?? ?? ????????node_prev?=?node;?? ????????node?=?node_next;?? ????}?? ????return?list;?? }??
main.c
[cpp]?view plaincopy
#include?<stdio.h>?? #include?<stdlib.h>?? #include?"linklist.h"?? ?? int?main()?? {?? ????int?i;?? ????data_t?x;?? ????linklist_t?p;?? ????p?=?CreateEmptyLinklist();?? ????data_t?a[10]?=?{1,3,5,7,9,11,13,15,17,19};?? ?? ????for(i?=?0;i?<?10;i++)?? ????{?? ????????InsertLinklist(p,i,a[i]);?? ????}?? ?? ????ReverseLinklist(p);?? ????printf("The?length?of?the?list?is:%d\n",LengthLinklist(p));?? ?????? ????GetLinklist(p,4,&x);?? ????printf("The?NO.4?of?this?list?is:%d\n",x);?? ?? ????SetLinklist(p,4,100);?? ????GetLinklist(p,4,&x);?? ????printf("After?updating!The?No.4?0f?this?list?is:%d\n",x);?? ?? ????DeleteLinklist(p,4);?? ????printf("After?updating!The?length?of?the?list?is:%d\n",LengthLinklist(p));?? ????GetLinklist(p,4,&x);?? ????printf("After?updating!The?No.4?0f?this?list?is:%d\n",x);?? ?? ????ReverseLinklist(p);?? ?????? ????ClearLinklist(p);?? ????if(EmptyLinklist(p))?? ????????printf("This?list?is?empty!\n");?? ????DestroyLinklist(p);?? ????printf("This?list?is?destroyed!\n");?? ?? ????return?0;?? ?????? }??
執行結果如下:
[cpp]?view plaincopy
fs@ubuntu:~/qiang/list/list2$?./Test?? The?length?of?the?list?is:10?? The?NO.4?of?this?list?is:11?? After?updating!The?No.4?0f?this?list?is:100?? After?updating!The?length?of?the?list?is:9?? After?updating!The?No.4?0f?this?list?is:9?? This?list?is?empty!?? This?list?is?destroyed! ?
總結
以上是生活随笔為你收集整理的Linux C 数据结构---链表(单向链表)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。