c语言链表中何时用点何时用箭头,链表基本操作及其过程详细叙述
鏈表概述:鏈表是一種常見的數據結構。數組可以存放數據,但是使用數組時要先指定數組中包含元素的個數,即數組長度。但是如果向這個數組中加入的元素個數超過了數組的大小時,便不能將內容完全保存。例如在定義一個班級的人數時,如果小班是30人,普通班是50人,且定義班級人數時使用數組,那么要定義數組的個數為最大,也就是最少為50個元素,否則不滿足最大時的情況。這種方式非常浪費空間。而鏈表,其存儲元素的個數不受限定的,當進行添加元素的時候存儲的個數就會隨之改變。
如圖1所示為鏈表結構的示意圖
在鏈表中有一個頭指針變量,圖中head表示的就是頭指針,這個指針變量保存一個地址。從圖中的箭頭可以看到該地址為一個變量的地址,也就是說頭指針指向一個變量。這個變量稱為元素,在鏈表中每一個元素包括兩個部分:數據部分和指針部分。數據部分用來存放元素所包含的數據,而指針部分用來指向下一個元素。最后一個元素指針指向NULL,表示指向的地址為空。從圖1可以看到,head頭結點指向第一個元素,第一個元素中的指針又指向第二個元素,第二個元素的指針又指向第三個元素的地址,第三個元素的指針就指向為空。
根據對鏈表的描述,可以想象到鏈表就像一個鐵鏈,一環扣一環。然后通過頭指針尋找鏈表中的元素,這就好比在一個幼兒園中,老師拉著第一個小朋友的手,第一個小朋友又拉著第二個小朋友的手,這樣下去在幼兒園中的小朋友就連成了一條線。最后一個小朋友沒有拉著任何人,他的手是空著的,他就好像是鏈表中鏈尾,而老師就是頭指針,通過老師就可以找到這個隊伍中的任何一個小朋友。
注意:在鏈表這種結構中,必須利用指針才能實現。因此鏈表中的結點應該包含一個指針變量來保存下一個結點的地址。
三個函數:
void *malloc(unsigned int size);
該函數的功能是在內存中動態地分配一塊size大小的內存空間。malloc函數會返回一個指針,該指針指向分配的內存空間,如果出現錯誤則返回NULL。
void *calloc(unsigned int n,unsigned int size);
該函數的功能是在內存中動態分配n個長度為size的連續內存空間數組。calloc函數會返回一個指針,該指針指向動態分配的連續內存空間地址。當分配空間錯誤時,返回NULL。
void free(void *ptr);
該函數的功能是使用由指針ptr指向的內存區,使部分內存區能被其他變量使用(簡單來說就是釋放不需要的內存空間)。ptr是最近一次調用calloc或malloc函數時返回的值,free函數無返回值。
鏈表的插入操作:鏈表的插入操作可以在鏈表的頭指針位置進行(圖3),也可以在某個結點的位置進行,或者可以像創建結構時在鏈表的后面添加結點(圖2)。這三種插入操作的思想都是一樣的。
鏈表頭插入結點的過程就比如手拉手的小朋友連成一條線,這時又來了一個小朋友他要站在老師和一個小朋友的中間,那么老師就要放開原來的小朋友,拉住新加入的小朋友。這個新加入的小朋友就拉住原來的那個小朋友。這樣,這條連成的線還是連在一起。
鏈表的刪除操作:當希望刪除鏈表中的結點時,應該怎么辦?還是通過前文中小朋友手拉手的比喻進行理解。例如隊伍中的一個小朋友離開隊伍了,并且這個隊伍不會斷開的方法只需他兩邊的小朋友將手拉起來就可以了。
例如在一個鏈表中刪除其中的一點:
通過圖4可以發現要刪除一個結點,首先要找到這個結點的位置,例如圖中的NO2結點。然后將NO1結點的指針指向NO3結點,最后將NO2結點的內存空間釋放掉,這樣就完成了結點的刪除操作。
實例:
#include
#include
struct student//學生結構體
{
char name[20];//姓名
int number;//學號
struct student * next;//指向下一個結點的指針
};
int count;//全局變量表示鏈表長度
/*
create函數的功能是創建鏈表,在create的外部可以看到一個整型的全局變量count,這個變量
的作用是表示鏈表中結點的數量。在create函數中,首先定義需要用到的指針變量,head用來表示頭
指針,end用來指向原來的尾結點,new指向新創建的結點。
使用malloc函數分配內存,先用end和new兩個指針都指向第一個分配的內存。然后顯示提示信息,
先輸入一個學生的姓名,再輸入學生的學號。使用while進行判斷,如果學號為0,則不執行循環語句。
在while循環中,count++自加操作表示鏈表中結點的增加。然后要判斷新加入的結點是否是第一次
加入的結點,如果是第一次加入結點則執行if語句塊中的代碼,否則執行else語句塊中的代碼。
在if語句塊中,因為第一次加入結點時其中沒有結點,所以新結點即為首結點也為最后一個結點,
并且要將新加入的結點的指針指向NULL,即為head指向。else語句實現的是鏈表中已經有結點存在時的
操作。首先將新結點new的指針指向NULL,然后將原來最后一個結點的指針指向新結點,最后將end指針
指向最后一個結點。
這樣一個結點創建完之后,要再進行分配內存,然后向其中輸入數據,通過while語句再次判斷輸入
的數據是否符合結點的要求。當結點不符合要求時,執行下面的代碼,調用free函數將不符合要求的結點
空間進行釋放。
*/
struct student * create()
{
struct student * head = NULL;//初始化鏈表頭指針為空
struct student * end,* new;
count = 0;//初始化鏈表長度
end = new = (struct student *)malloc(sizeof(struct student));
printf("please first enter name,then nember\n");
scanf("%s",new->name);
scanf("%d",&new->number);
while(0 != new->number)
{
count++;
if(1 == count)
{
new->next = head;//使得指向為空
end = new;//跟蹤新加入的結點
head = new;//頭指針指向首結點
}
else
{
new->next = NULL;//新結點的指針為空
end->next = new;//原來的尾結點指向新結點
end = new;//end指向新結點
}
new = (struct student *)malloc(sizeof(struct student));//再次分配結點內存空間
scanf("%s",new->name);
scanf("%d",&new->number);
}
free(new);//釋放沒用到的空間
return head;
}
/*
print函數是用來將鏈表中的數據進行輸出。在函數的參數中,head表示一個鏈表的頭結點。
在函數中,定義一個臨時的指針temp用來進行循環操作。定義一個整型變量表示鏈表中的結點序號。
然后將臨時指針temp指針變量保存首結點的地址。
使用while語句將所有的結點中保存的數據都顯示輸出。其中每輸出一個結點的內容后,就移動
temp指針變量指向下一個結點的地址。當最后一個結點時,所擁有的指針指向NULL,此時循環結束。
*/
void print(struct student * head)
{
struct student *temp;//循環所用的臨時指針
int index = 1;//表示鏈表中結點的序號
printf("---the list has %d members:---\n\n",count);
temp = head;//指針得到首結點的地址
while(NULL != temp)
{
printf("the NO%d member is:\n",index); //輸出結點序號
printf("the name is:%s\n",temp->name);//輸出姓名
printf("the number is:%d\n\n",temp->number); //輸出學號
temp = temp->next;//移動臨時指針到下一個結點
index++;
}
}
/*
insert函數為鏈表頭插入操作函數,在代碼中,為要插入的新結點分配內存,然后向新結點中輸入數據。這樣
一個結點就創建完成了,接下來就是將這個結果插入到鏈表中。首先將新結點的指針指向原來的首結點,保存首結
點的地址。然后將頭指針指向新結點,這樣就完成了結點的連接操作,最后增加鏈表的結點數量。
*/
struct student * insert(struct student * head)
{
struct student * new;//指向新分配的空間
printf("---insert member at first---\n");
new = (struct student *)malloc(sizeof(struct student));//分配內存空間,并返回指向該內存空間的指針
scanf("%s",new->name);
scanf("%d",&new->number);
new->next = head;//新結點指針指向原來的首結點
head = new;//頭指針指向新結點
count++;//增加鏈表結點數量
return head;
}
/*
為delete函數傳遞兩個參數,head表示鏈表的頭指針,index表示要刪除結點在鏈表中的位置。
定義整型變量i用來控制循環的次數,然后定義兩個指針,分別用來表示要刪除的結點和這個結點
之前的結點。
輸出一行提示信息表示要進行刪除操作,之后利用for語句進行循環操作找到要刪除的結點,
使用temp保存要刪除結點的地址,pre保存前一個結點的地址。找到要刪除的結點后,連接刪除結點
兩邊的結點,并使用free函數將temp指向的內存空間進行釋放。
*/
void delete(struct student * head,int index)//head表示頭結點,index表示要刪除的結點下標
{
int i;//控制循環變量
struct student * temp;//臨時指針
struct student * pre;//表示要刪除結點前的結點
temp = head;//得到頭結點
pre = temp;
printf("---delete NO%d member---\n\n\n",index);
for(i=1;i
{
pre = temp;
temp = temp->next;
}
pre->next = temp->next;//連接刪除結點兩邊的結點
free(temp);//釋放掉要刪除結點的內存空間
count--;//減少鏈表中的元素個數
}
/*
在main函數中,先定義一個頭結點指針head,然后調用create函數創建鏈表,并將鏈表的頭結點
返回給head指針變量。利用得到的頭結點head作為print函數的參數。
在main函數中分別添加代碼執行插入和刪除操作。
*/
int main()
{
struct student * head;//定義頭結點
head = create();//創建結點
print(head);//輸出鏈表
head = insert(head);//插入結點
print(head);//輸出鏈表
delete(head,2);//刪除第二個結點
print(head);//輸出鏈表
return 0;
}
參考文獻:[C語言從入門到精通].王娣等
[C語言從入門到精通].王娣等PDF文檔下載地址:
總結
以上是生活随笔為你收集整理的c语言链表中何时用点何时用箭头,链表基本操作及其过程详细叙述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 管理类联考笔试还是计算机考,干货来了!管
- 下一篇: 小马哥---高仿苹果6s 主板H339