鏈表概述
鏈表是一種常見的重要的數據結構。它是動態地進行存儲分配的一種結構。
鏈表有一個 頭指針 變量,它存放一個地址,該地址指向一個元素,鏈表中每一個元素稱爲 結點,每個結點都應包括兩個部分,一爲用戶需要用的實際數據,二爲下一個結點的地址。可以看出,頭指針 head 指向第一個元素,第一個元素又指向第二個元素,。。。。直到最後一個元素,該元素不再指向其他元素,它稱爲 表尾,它的地址部分放一個 NULL(表示 空地址)鏈表到此結束。
可以看到鏈表中各元素在內存中可以不是連續存放的,要找某一元素,必須先找到上一個元素,根據它提供的下一元素地址才能找到下一個元素。如果不提供 頭指針 head 則整個鏈表無法訪問。
可以看到。這種鏈表的數據結構,必須利用指針變量才能實現,即一個結點中應包含一個指針變量,用它存放下一結點的地址。
前面介紹了結構體變量,用它作鏈表中的結點是最合適的,一個結構體變量包含若干成員,這些成員可以是數值類型,字符類型,數組類型,也可以是指針類型,我們用這個指針類型成員來存放下一個結點的地址。例如可以設計這樣一個結構體類型:
struct student
{
int num;
float score;
struct student *next;
};
其中成員 num 和 score 用來存放結點中的有用數據(用戶需要用到的數據),next 是指針類型成員,它指向 struct student 類型數據(這是 next 所在結構體類型)。一個指針類型的成員既可以指向其他類型的結構體數據,也可以指向自己所在的結構體類型的數據。現在 next 是 struct student 類型中的一個成員,它又指向 struct student 類型的數據。用這種方法就可以建立鏈表。
請注意:只是定義一個 struct student 類型,並未實際分配存儲空間,只有定義了變量才分配內存單元。
7.2 簡單鏈表
下面通過一個例子來說明如何建立和輸出一個簡單鏈表
#include <stdio.h>
#include <stdlib.h>
#define NULL 0
struct student
{
long num;
float score;
struct student *next;
};
void main()
{
struct student a, b, c, *head, *p;
a.num = 99101; a.score = 89.5;
b.num = 99103; b.score = 90;
c.num = 99107; c.score = 85;//對結點的 num 和 score 成員賦值
head = &a;//將結點 a 的起始地址賦給頭指針 head
a.next = &b;//將結點 b 的起始地址賦給 a 結點的 next 成員
b.next = &c;
c.next = NULL;// c 結點的 next 成員不存放其他結點地址
p = head;//使 p 指針指向 a 結點
do
{
printf("%ld %5.1f\n", p->num, p->score);// 輸出 p 指向的結點的數據
p = p->next;//使 p 指向下一結點
}while(p != NULL);//輸出完 c 結點後 p 的值爲 NULL
system("pause");
}
運行結果
99101 89.5
99103 90.0
99107 85.0
7.3 處理動態鏈表所需的函數
(1)malloc 函數
void *malloc(unsigned int size);
作用是在內存的動態存儲區中分配一個長度爲 size 的連接空間。些函數的值(即返回值)是一個指向分配空間起始地址的指針(基類型爲 void)。如果些函數未能成功地執行(例如內存空間不足)則返回空指針 NULL。
(2)calloc 函數
void *calloc(unsigned n, unsigned size);
其作用是在內存的動態區存儲中分配 n 個長度爲 size 的連續空間。函數返回一個指向分配空間起始地址的指針,如果分配不成功,返回 NULL。
用 calloc 函數可以爲一維數組開闢動態存儲空間, n 爲數組元素個數,每個元素長度爲 size。
(3)free 函數
void free(void *p);
其作用是釋放由 p 指向的內存區,使這部分內存區能被其它變量使用, p 是最後一次調用 calloc 或 malloc 函數時返回的值。free 函數無返回值。
請注意:以前的C版本提供的 malloc 和 calloc 函數得到的是指向字符型數據的指針。ANSI C 提供的 malloc 和 calloc 函數規定爲 void * 類型。
7.4 建立動態鏈表
所謂建立動態鏈表是指在程序執行過程中從無到有地建立起一個鍵表,即一個一個地開闢結點和輸入各結點數據,並建立起前後相鏈的關係。
#include <stdio.h>
#include <stdlib.h>#define NULL 0
#define LEN sizeof(struct student)
struct student
{
long num;
float score;
struct student *next;
};
struct student *create()
{
struct student *p1, *p2, *head;
int num;
float score;
int n = 0;
head = NULL;
p1 = p2 = (struct student *)malloc(LEN);
printf("please input num and score.\n");
scanf("%d,%f", &p1->num, &p1->score);
while(p1->num != 0)
{
n ++;
if(n == 1)
head = p1;
else
p2->next = p1;
p2 = p1;
p1 = (struct student *)malloc(sizeof(struct student));
printf("please input num and score.\n");
scanf("%d,%f", &p1->num, &p1->score);
}
p2->next = NULL;
return head;
}
void printlist(struct student *head)
{
struct student *p;
p = head;
if(head != NULL)
{
do
{
printf("num=%d score=%f\n", p->num, p->score);
p = p->next;
}while(p != NULL);
}
}
void main()
{
struct student *head;
head = create();
printlist(head);
system("pause");
}
以下是對鏈表的各種操作
打印鏈表
void printlist(struct student *head)
{
struct student *p;
p = head;
if(head != NULL)
{
do
{
printf("num=%d score=%5.2f\n", p->num, p->score);
p = p->next;
} while (p != NULL);
}
/* while(p -> next != NULL)
{
printf("num=%d score=%f\n", p->num, p->score);
p = p->next;
}*/
}
刪除節點
struct student *delNode(struct student *head, int num)
{
printf("delNode.\n");
struct student *p1, *p2;
if(head == NULL)
{
printf("The List is NULL.\n");
}
else
{
p1 = head;
while(p1->next != NULL && p1->num != num)
{
p2 = p1;
p1 = p1->next;
}
if(p1->num == num)
{
if(p1 == head)
head = p1->next;
else
p2->next = p1->next;
}
else
printf("Can not find list num.\n");
}
return head;
}
更新節點
struct student *update(struct student *head, int index, int num, float score)
{
printf("update.\n");
struct student *p;
if(head == NULL)
{
printf("The List is NULL.\n");
}
else
{
p = head;
while(p->next != NULL && p->num != index)
{
p = p->next;
}
if(p->num == index)
{
p->num = num;
p->score = score;
}
else
printf("Can not find list index.\n");
}
return head;
}
增加節點
struct student *add(struct student *head, int index, int num, float score)
{
printf("add.\n");
struct student *p1, *p2, *p3;
if(head == NULL)
{
printf("The List is NULL.\n");
}
else
{
p1 = p2 = head;
while(p1->next != NULL && p1->num != index)
{
p1 = p1->next;
p2 = p1;
}
if(p1->num == index)
{
p3 = (struct student *)malloc(LEN);
p3->num = num;
p3->score = score;
if(p2->next == NULL)
{
p2->next = p3;
p3->next = NULL;
}
else
{
p3->next = p2->next;
p2->next = p3;
}
}
else
printf("Can not find list index.\n");
}
return head;
}