生活随笔
收集整理的這篇文章主要介紹了
Linux C 数据结构---单向链表
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
線性表存儲(chǔ)結(jié)構(gòu)分為順序存儲(chǔ)、鏈?zhǔn)酱鎯?chǔ)。
???????順序存儲(chǔ)的優(yōu)點(diǎn):
?????? 順序存儲(chǔ)的缺點(diǎn):
???????鏈表就是典型的鏈?zhǔn)酱鎯?chǔ),將線性表L = (a0,a1,a2,........an-1)中個(gè)元素分布在存儲(chǔ)器的不同存儲(chǔ)塊,成為結(jié)點(diǎn)(Node),通過地址或指針建立他們之間的練習(xí),所得到的存儲(chǔ)結(jié)構(gòu)為鏈表結(jié)構(gòu)。表中元素ai的結(jié)點(diǎn)形式如下:
其中,結(jié)點(diǎn)的data域存放數(shù)據(jù)元素ai,而next域是一個(gè)指針,指向ai的直接后繼a(i+1)所在的結(jié)點(diǎn)。于是,線性表L=(a0,a1,......an-1)的結(jié)構(gòu)如圖:
?
一、節(jié)點(diǎn)類型描述:
[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;
則結(jié)構(gòu)變量A為所描述的節(jié)點(diǎn),而指針變量P為指向此類型節(jié)點(diǎn)的指針(p的值為節(jié)點(diǎn)的地址);
這樣看來 linknode_t? linklist_t 的作用是一樣的,那為什么我們要定義兩個(gè)數(shù)據(jù)類型(同一種)呢?主要為了代碼的可讀性,我們要求標(biāo)識(shí)符要望文識(shí)義,便于理解;
1、linknode_t? *pnode? 指向一個(gè)節(jié)點(diǎn);
2、linklist_t list? 指向一個(gè)整體
二、頭結(jié)點(diǎn) head
??????? 我們?cè)谇捌岬降捻樞虼鎯?chǔ)線性表,如何表達(dá)一個(gè)空表{ },是通過list->last = -1來表現(xiàn)的,所謂的空表就是數(shù)據(jù)域?yàn)镹ULL,而我們的鏈表有數(shù)據(jù)域和指針域,我們?nèi)绾伪憩F(xiàn)空鏈表呢?這時(shí),就引入了頭結(jié)點(diǎn)的概念,頭結(jié)點(diǎn)和其他節(jié)點(diǎn)數(shù)據(jù)類型一樣,只是數(shù)據(jù)域?yàn)镹ULL,head->next = NULL,下面我們看一個(gè)創(chuàng)建空鏈表的函數(shù),如何利用頭結(jié)點(diǎn)來創(chuàng)建一個(gè)空鏈表:
[cpp]?view plaincopy
linklist_t?CreateEmptyLinklist()?? {?? ????linklist_t?list;?? ?? ????list?=?(linklist_t)malloc(sizeof(linknode_t));?? ????if?(NULL?!=?list)?{?? ????????list->next?=?NULL;?? ????}?? ????return?list;?? }??
只要頭結(jié)點(diǎn),鏈表就還在!
?
三、鏈表基本運(yùn)算的相關(guān)算法
???????? 鏈表的運(yùn)算除了上面的創(chuàng)建空鏈表,還有數(shù)據(jù)的插入,刪除,查找等函數(shù),鏈表的運(yùn)算有各種實(shí)現(xiàn)方法,如何寫出一個(gè)高效的,封裝性較好的函數(shù)是我們要考慮的,比如數(shù)據(jù)插入函數(shù),我們就要盡可能考慮所有能出現(xiàn)的結(jié)果,比如:1)如果需插入數(shù)據(jù)的鏈表是個(gè)空表;2)所插入的位置超過了鏈表的長(zhǎng)度;如果我們的函數(shù)能包含所有能出現(xiàn)的情況,不僅能大大提高我們的開發(fā)效率,也會(huì)減少代碼的錯(cuò)誤率。下面,我們來看看下面的這個(gè)鏈表的插入函數(shù)的實(shí)現(xiàn):
[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;?? ????}?? ??????
這個(gè)插入函數(shù)可利用性就非常高。
?
下面講一個(gè)完整鏈表代碼貼出:
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;?? ?????? }??
執(zhí)行結(jié)果如下:
[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!?
總結(jié)
以上是生活随笔為你收集整理的Linux C 数据结构---单向链表的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。