鏈表

單鏈表有一個頭節點h e a d,指向鏈表在內存的首地址。鏈表中的每一個節點的數據類型爲結構體類型,節點有兩個成員:整型成員(實際需要保存的數據)和指向下一個結構體類型節點的指針即下一個節點的地址(事實上,此單鏈表是用於存放整型數據的動態數組)。鏈表按此結構對各節點的訪問需從鏈表的頭找起,後續節點的地址由當前節點給出。無論在表中訪問那一個節點,都需要從鏈表的頭開始,順序向後查找。鏈表的尾節點由於無後續節點,其指針域爲空,寫作爲N U L L。


圖7 - 3還給出這樣一層含義,鏈表中的各節點在內存的存儲地址不是連續的,其各節點的地址是在需要時向系統申請分配的,系統根據內存的當前情況,既可以連續分配地址,也可以跳躍式分配地址。

看一下鏈表節點的數據結構定義:

struct node

{

int num;

struct node *p;

} ;

在鏈表節點的定義中,除一個整型的成員外,成員p是指向與節點類型完全相同的指針。 在鏈表節點的數據結構中,非常特殊的一點就是結構體內的指針域的數據類型使用了未定義成功的數據類型。這是在C中唯一規定可以先使用後定義的數據結構。

創建----單鏈表的創建過程有以下幾步:

1 ) 定義鏈表的數據結構。

2 ) 創建一個空表。

3 ) 利用m a l l o c ( )函數向系統申請分配一個節點。

4 ) 將新節點的指針成員賦值爲空。若是空表,將新節點連接到表頭;若是非空表,將新 節點接到表尾。

5 ) 判斷一下是否有後續節點要接入鏈表,若有轉到3 ),否則結束。

輸出---單鏈表的輸出過程有以下幾步

1) 找到表頭。

2) 若是非空表,輸出節點的值成員,是空表則退出。

3 ) 跟蹤鏈表的增長,即找到下一個節點的地址。

4) 轉到2 )。

[例7-5] 創建一個存放正整數(輸入- 9 9 9做結束標誌)的單鏈表,並打印輸出。 #include <stdlib.h> /包*含ma l l o c ( ) 的頭文件*/

#include <stdio.h>

struct node /*鏈表節點的結構* /

{

int num;

struct node *next;

} ;

m a i n ( )

{

struct node *creat(); / *函數聲明* /

void print();

struct node *head; / * 定義頭指針* /

head=NULL;/*建一個空表*/

head=creat(head);/*創建單鏈表*/

print(head);/*打印單鏈表*/

}

/******************************************/

/*函數返回的是與節點相同類型的指針*/

struct node*creat(structnode*head) {

struct node*p1,*p2;

p1=p2=(structnode*)malloc(sizeof(structnode));申請/*新節點*/

scanf("%d",&p1->num);/*輸入節點的值*/

p1->next=NULL;/*將新節點的指針置爲空*/

while(p1->num>0)/*輸入節點的數值大於0*/

{

if(head==NULL)head=p1;/*空表,接入表頭*/

elsep2->next=p1;/*非空表,接到表尾*/

p2=p1;

p1=(structnode*)malloc(sizeof(structnode));/*請下一個新節點*/

scanf("%d",&p1->num);/*輸入節點的值*/

}

return head;/*返回鏈表的頭指針*/

}

/*******************************************/

void print(struct node*head)輸/*出以head爲頭的鏈表各節點的值*/

{

struct node *temp;

temp=head;/*取得鏈表的頭指針*/

while(temp!=NULL)/*只要是非空表*/

{

printf("%6d",temp->num);/*輸出鏈表節點的值*/

temp=temp->next;/*跟蹤鏈表增長*/

}

}

在鏈表的創建過程中,鏈表的頭指針是非常重要的參數。因爲對鏈表的輸出和查找都要從鏈表的頭開始,所以鏈表創建成功後,要返回一個鏈表頭節點的地址,即頭指針。



7.4.2 單鏈表的插入與刪除

在鏈表這種特殊的數據結構中,鏈表的長短需要根據具體情況來設定,當需要保存數據時向系統申請存儲空間,並將數據接入鏈表中。對鏈表而言,表中的數據可以依此接到表尾或連結到表頭,也可以視情況插入表中;對不再需要的數據,將其從表中刪除並釋放其所佔空間,但不能破壞鏈表的結構。這就是下面將介紹的鏈表的插入與刪除。

1. 鏈表的刪除

在鏈表中刪除一個節點,用圖7 - 4描述如下:

[例7-6] 創建一個學生學號及姓名的單鏈表,即節點包括學生學號、姓名及指向下一個節點的指針,鏈表按學生的學號排列。再從鍵盤輸入某一學生姓名,將其從鏈表中刪除。 首先定義鏈表的結構:

struct

從圖7 - 4中看到,從鏈表中刪除一個節點有三種情況,即刪除鏈表頭節點、刪除鏈表的中 間節點、刪除鏈表的尾節點。題目給出的是學生姓名,則應在鏈表中從頭到尾依此查找各節 點,並與各節點的學生姓名比較,若相同,則查找成功,否則,找不到節點。由於刪除的節 點可能在鏈表的頭,會對鏈表的頭指針造成丟失,所以定義刪除節點的函數的返回值定義爲

返回結構體類型的指針。

struct node *delet(head,pstr)以/*he a d 爲頭指針,刪除ps t r 所在節點*/

struct node *head;

char *pstr;

{

struct node *temp,*p;

t e m p = h e a d ; / * 鏈表的頭指針* /

if (head==NULL) / *鏈表爲空* /

printf("\nList is null!\n");

else /*非空表* /

{

t e m p = h e a d ;

while (strcmp(temp->str,pstr)!=0&&temp->next!=NULL)

/ * 若節點的字符串與輸入字符串不同,並且未到鏈表尾* /

{

p = t e m p ;

t e m p = t e m p - > n e x t ; / * 跟蹤鏈表的增長,即指針後移* / }

if(strcmp(temp->str,pstr)==0 ) / *找到字符串* /

{

if(temp==head) { / * 表頭節點* /

printf("delete string :%s\n",temp->str);

h e a d = h e a d - > n e x t ;

f r e e ( t e m p ) ; / *釋放被刪節點* /

}

e l s e

{

p->next=temp->next; /表*中節點*/

printf("delete string :%s\n",temp->str);

f r e e ( t e m p ) ;

}

}

else printf("\nno find string!\n");沒/找* 到要刪除的字符串*/

}

r e t u r n ( h e a d ) ; / *返回表頭指針* /

}

2. 鏈表的插入

首先定義鏈表的結構:

struct

{

int num; /*學生學號* /

char str[20]; /*姓名* /

struct node *next;

} ;

在建立的單鏈表中,插入節點有三種情況,如圖7 - 5所示。



插入的節點可以在表頭、表中或表尾。假定我們按照以學號爲順序建立鏈表,則插入的節點依次與表中節點相比較,找到插入位置。由於插入的節點可能在鏈表的頭,會對鏈表的頭指針造成修改,所以定義插入節點的函數的返回值定義爲返回結構體類型的指針。節點的插入函數如下:

struct node *insert(head,pstr,n) / *插入學號爲n、姓名爲p s t r 的節點* /

struct node *head; / *鏈表的頭指針* /

char *pstr;

int n;

{

struct node *p1,*p2,*p3;

p1=(struct node*)malloc(sizeof(struct node))分;配/*一個新節點*/

s t r c p y ( p 1 - > s t r , p s t r ) ; / * 寫入節點的姓名字串* /

p 1 - > n u m = n ; / * 學號* /

p 2 = h e a d ;

if (head==NULL) / * 空表* /

{

head=p1; p1->next=NULL;/ *新節點插入表頭* /

}

e l s e

{ /*非空表* /

while(n>p2->num&&p2->next!=NULL)

/ *輸入的學號小於節點的學號,並且未到表尾* /

{

p 3 = p 2 ;

p 2 = p 2 - > n e x t ; / * 跟蹤鏈表增長* /


if (n<=p2->num) / *找到插入位置* /  
if (head==p2) / * 插入位置在表頭* / 

  h e a d = p 1;

  p 1 - > n e x t = p 2;  


e l s e 

  /*插入位置在表中* /
 p 3 - > n e x t = p 1;  
p 1 - > n e x t = p 2 ;
 } 
e l s e 


/*插入位置在表尾* / 
p 2 - > n e x t = p 1 ; 

p 1 - > n e x t = N U L L ;


r e t u r n ( h e a d ) ;  / * 返回鏈表的頭指針* / }



發佈了28 篇原創文章 · 獲贊 15 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章