鏈表中最簡單的一種是單向鏈表,它包含兩個域,一個信息域和一個指針域。這個鏈接指向列表中的下一個節點,而最後一個節點則指向一個空值。
一個單向鏈表包含兩個值: 當前節點的值和一個指向下一個節點的鏈接
一個單向鏈表的節點被分成兩個部分。第一個部分保存或者顯示關於節點的信息,第二個部分存儲下一個節點的地址。單向鏈表只可向一個方向遍歷。
鏈表最基本的結構是在每個節點保存數據和到下一個節點的地址,在最後一個節點保存一個特殊的結束標記,另外在一個固定的位置保存指向第一個節點的指針,有的時候也會同時儲存指向最後一個節點的指針。一般查找一個節點的時候需要從第一個節點開始每次訪問下一個節點,一直訪問到需要的位置。但是也可以提前把一個節點的位置另外保存起來,然後直接訪問。當然如果只是訪問數據就沒必要了,不如在鏈表上儲存指向實際數據的指針。這樣一般是爲了訪問鏈表中的下一個或者前一個(需要儲存反向的指針,見下面的雙向鏈表)節點。
相對於下面的雙向鏈表,這種普通的,每個節點只有一個指針的鏈表也叫單向鏈表,或者單鏈表,通常用在每次都只會按順序遍歷這個鏈表的時候(例如圖的鄰接表,通常都是按固定順序訪問的)。
例1,建立鏈表保存學生的信息,並且可以進行,插入,刪除操作,並將學生的信息輸出
#include <stdio.h>
#include<malloc.h>
#define LEN sizeof(struct student )
#define NULL 0
struct student
{
int num;
float score;
struct student *next;
};
int n;
//建立鏈表
struct student *create(void)
{
struct student *head, *p1,*p2;
n=0;
p1=p2=(struct student *)malloc(LEN);
scanf("%d %f",&p1->next,&p1->score);
head=NULL;
while(p1->num!=0)
{
n=n+1;
if(n==1) head=p1; //p1是指向新開闢的結點
else p2->next=p1;
p2=p1; //p2指向鏈表中的最後一個基點
p1=(struct student *)malloc(LEN); //開闢新的結點,並且使p1指向他
scanf("%d %f",&p1->num,&p1->score);
}
p2->next=NULL;
return (head);
}
//刪除結點
struct student *del(struct student *head,long num)
{
struct student *p1,*p2;
if(head==NULL) {printf("\nlist null!\n");goto end;}
p1=head;
while(num!=p1->num && p1->next!=NULL) //p1指向不是所要找的結點,並且後面還有結點
{
p2=p1;
p1=p1->next; //p1後移一個及誒單
} //p1後移一個結點
if(num==p1->num) //找到了
{
if(p1==head) head=p1->next; //若p1指向的是首結點,把第二個結點的地址head
else p2->next=p1->next; //or 將下一個結點的地址賦給前一個結點地址
printf("delete:%d\n",num);
n=n-1;
free(p1);
}
else printf("%dnot been found !\n",num);
end:
return(head);
}
//插入學生信息
struct student *insert(struct student *head ,struct student *stud)
{
struct student *p0,*p1,*p2;
p1=head; //使p1指向第一個結點
p0=stud; //p0指向要插入的結點
if(head==NULL) //原來的鏈表是空表
{
head=p0,p0->next=NULL; //使p0指向的結點作爲頭結點
}
else
{
while ((p1->num>p1->num)&&(p1->next!=NULL))
{
p2=p1; //使p2指向剛纔p1指向的及誒按
p1=p1->next; //p1後移一個結點
}
if(p0->num<=p1->num)
{
if(head==p1) head=p0; //插到原來第一個結點之前
else p2->next=p0; //插到p2指向的結點之後
p0->next=p1;
}
else
{
p1->next=p0;p0->next=NULL; //插到最後的結點之後
}
}
n=n+1; //結點數加1
return (head);
}
//輸出鏈表
void print(struct student *head)
{
struct student *p;
p=head;
if(head!=NULL)
do
{
printf("%d %f\n",p->num,p->score);
p=p->next;
}
while(p!=NULL);
}
//main函數
void main()
{
struct student *head,stu;
long del_num;
printf("Input records:\n");
head=create(); //建立鏈表,返回頭指針
print(head); //輸出全部結點
printf("\nInput the deleted number:\n");
scanf("%ld",&del_num); //輸入要刪除的學號
while(del_num!=0)
{
head=del(head,del_num); //刪除後鏈表的頭指針
print(head); //輸出全部結點
printf("Input the deleted number:\n");
scanf("%ld",&del_num);
}
printf("\nInput the inserted record:\n");
stu=(struct student *)malloc(LEN);
scanf("%d %f",&stu->num,&stu->score); //輸入要插入的結點
{
head=insert(head,&stu); //插入一個結點,返回頭指針的
print(head); //輸出全部結點
printf("\nInput the inserted record:\n");
stu=(struct student *)malloc(LEN);
scanf("%d %f",&stu->num,&stu->score);
}
}