链表
动态地进行存储的一种结构
其每一个元素(节点)分为两部分,数据域和指针域
n个节点离散分配,彼此通过指针相连
每个节点都只有一个前驱节点,都只有一个后继结点
专业术语:
头结点
头结点的数据类型和首节点的类型一模一样
头结点是首节点前面的那个节点
头结点并不存放有效数据
设置头结点的目的是为了方便对链表的操作
头指针
存放头结点地址的指针变量(即指向头结点的指针变量,下同)
首节点
存放第一个有效数据的结点
尾节点
存放最后一个有效数据的结点
下面举一个例子
例1:
# include <stdio.h>
# include <malloc.h>
# include <stdlib.h>
//定义可一个链表节点的数据类型
struct Node
{
int data; //8行 数据域
struct Node * pNext; //9行 指针域
};
//函数声明
struct Node * create_list(void);
void traverse_list(struct Node *);
int main(void)
{
struct Node * pHead = NULL; //18行
pHead = create_list(); //20行
traverse_list(pHead); //21行
return 0;
}
struct Node * create_list(void)
{
int len; //28行
int i;
int val; //30行
struct Node * pHead = (struct Node *)malloc(sizeof(struct Node))//32行
if (NULL == pHead)
{
printf("分配失败, 程序终止!\n");
exit(-1);
}
struct Node * pTail = pHead;
pTail->pNext = NULL;
printf("请输入您需要生成的链表节点的个数: len = ");
scanf("%d", &len);
for (i=0; i<len; ++i)
{
printf("请输入第%d个节点的值: ", i+1);
scanf("%d", &val);
struct Node * pNew = (struct Node *)malloc(sizeof(struct Node));
if (NULL == pNew)
{
printf("分配失败, 程序终止!\n");
exit(-1); //终止程序
}
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
void traverse_list(struct Node * pHead)
{
struct Node * p = pHead->pNext;
while (NULL != p)
{
printf("%d ", p->data);
p = p->pNext;
}
printf("\n");
return;
}
输出结果为:
当输入一个整数数字时(假设为3),则会提示输入要存储的整数,请输入第1个节点的值:,然后输入一个整数数字,接着就是输入第二个、第三个,最终是将输入的数字保存在链表中并输出
对于链表,一个元素(节点)分为数据域和指针域,数据域存储数据,指针域存储下一个元素的地址,
本程序中,第8行和第9行表示的就是一个元素的数据域和指针域,而它们所在的结构体表示链表中的一个元素;而第18行的pHead则是用来存放链表头结点的地址;第20行 create_list() 的功能是:创建一个非循环单链表,并将该链表的头结点的地址付给pHead,第21行是将链表输出,traverse的意思就是遍历,而遍历的意思是依次访问每个节点,这里可以理解为输出
接下来,28行和30行分别表示“存放有效节点的个数”和“临时存放用户输入的结点的值”;32行是分配了一个不存放有效数据的头结点
对了,还要说的是一个关键字typedef,这是个类型别名,具体用法见下例
例2:
# include <stdio.h>
int main(void)
{
typedef int LISI;
LISI i= 0; //等价于int i = 0;
printf("%d\n", i);
return 0;
}
输出结果为:
由上可知typedef是为int再多取一个名字字(这里是LISI),在以下的代码里而LISI和int,用哪个都行,这么做为的是简单,当然,上面那个程序看不到什么简单,下面再举一个例子
例3:
# include <stdio.h>
typedef struct student
{
int sid;
char name[100];
char sex;
}ST;
int main(void)
{
struct student a;
ST s;
a.sid = 333;
s.sid = 100;
printf("%d %d\n",a.sid, s.sid);
return 0;
}
输出结果为:
由上可知,ST等价于struct student
如果将ST变为* PST,则* PST等价于struct student *
另外,这样写也可以
typedef struct student
{
int sid;
char name[100];
char sex;
}ST, *PST;
这时同时声明了ST和* PST两个类型
需要说明的是,ST和PST这样的名字可以随便取(只要不是关键字),但一般都大写
【所有代码均在windows系统下C-Free5.0下运行通过】
(如有错误,敬请指正)