链表,顾名思义,有链有表。
形象点说,看起来像这样
一格一格的是表,线是链,两者加起来就是”链表“了。两个格子在一起把它叫做node(节点)
当我们把它放到计算机里的时候,其实它更像是这样的。
因为计算机里并没有绳子,连接他们的是指针。把指针跟数据放,到一起,让每个数据后面的指针指向下一个数据,以此来造出一条虚拟的绳子。
再完善一下模型,便是这样子
接下来,用C语言来实现这个单向链表。代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct _node{
int num;
struct _node *next;
} node;
void prtLLst(node *p);
node *create();
void freeLst(node *p);
int main(){
node *linkHead = NULL;
linkHead = create();
prtLLst(linkHead);
freeLst(linkHead);
return 0;
}
node *create(){
node *p1 = NULL;
node *last = NULL;
node *head = NULL;
int num;
printf("enter number:");
do{
scanf("%d",&num);
if (num != -1){
p1 = (node*)malloc(sizeof(node));
p1->num = num;
if (head == NULL){
head = p1;
}
else{
last->next = p1;
}
last = p1;
}
}while(num != -1);
last->next = NULL;
return head;
}
void prtLLst(node *p){
while(p != NULL){
printf("%d ",p->num);
p = p->next;
}
}
void freeLst(node *p){
node *q = NULL;
while(p != NULL){
q = p;
p = p->next;
free(q);
}
}
上面的代码中,用node *create()
来创建链表,void prtLLst(node *p)
来打印链表。
首先,用一个结构体来表达图中一个个的节点(里面有数据,还有指向下一个节点的指针)
typedef struct _node{
int num;
struct _node *next;
} node;
然后,在main()里面定义一个指针,用来指向链表的第一个节点。这样做便能够为后面的打印链表或者搜索元素提供第一个节点。(就像在遍历数组的时候从第一个下标开始一样,又由于这个链表是单向的,要遍历只能从第一个开始)
node *linkHead = NULL;
接下来在node *create()
中,
定义三个指针,p1将指向新创建的节点,last指向最后一个节点(这样就可以在添加节点的时候实现将最后一个节点的指针指向下一个新创建的节点了),head指向链表的第一个节点,用来返回这个节点给main()里面的linkhead。
node *p1 = NULL;
node *last = NULL;
node *head = NULL;
在do……while()循环中,先读入用户输入,如果不是“-1”(在这里用-1表示输入结束),便创建一个节点。
这里通过malloc()申请一块内存空间来创建节点,并将p1指向这个新的节点
往节点写入数据后,判断是否是第一个节点,如果只有一个,那么last->next = p1
是没意义的,因为这里是为了把新的节点链接进原来的后面。
do{
scanf("%d",&num);
if (num != -1){
p1 = (node*)malloc(sizeof(node));//创建节点
p1->num = num;//将输入的数据写入节点
if (head == NULL){ //判断是否是第一个节点
head = p1; //把head指向第一个
}
else{
last->next = p1; //原来最后一个指向新的
}
last = p1;//让它永远指向最后一个
}
}while(num != -1);
一但输入完成了,将最后一个节点的next指向NULL,后面可以通过这个指针是否为NULL判断链表是否到头了。
last->next = NULL;
最后,返回
return head;
这样便建立好了一个链表。
接下来是读取链表的方法
void prtLLst(node *p){
while(p != NULL){ //如果p不为NULL,说明还有下一个节点
printf("%d ",p->num);//打印这个节点的数据
p = p->next;
}
}
最后,释放空间
void freeLst(node *p){
node *q = NULL;
while(p != NULL){
q = p;
p = p->next;
free(q);
}
}