前言
链表是数据结构中非常重要的一种线性结构,它在线性结构中是离散存储的。在讲链表之前,先谈下typedef(为数据类型取别名)的用法,因为typedef在定义结构体时经常用到,可以起到很好的简化数据类型书写的作用。
实例说明:
#include<stdio.h>
typedef struct Student
{
int sno;//学号
char name[20];//姓名
}*PST,ST;//PST代表了struct Student *,ST代表了struct Student,即分别为其数据类型取别名
int main()
{
ST s={1001,"张三"};
PST pst=&s;
printf("学号:%d\n姓名:%s\n",pst->sno,pst->name);
return 0;
}
链表
链表可理解为n个结点(由数据域和指针域两部分组成)离散分配,彼此通过指针相连,每个结点只有一个前驱结点(除首节点外),每个结点只有一个后继结点(除尾结点外),且每个结点的数据类型相同。
链表中常见的专业术语有:首节点(第一个有效结点,即存放了有效数据),尾结点(最后一个有效结点,指针域为NULL),头结点(是在首结点前附加的一个节点,它没有存放有效数据,也没有存放有效结点个数。在首结点前加一个实际含义的头结点,可以方便我们对链表进行操作),头指针(存放了头结点的地址,即指向了头结点),尾指针(指向结点的地址)。我们通常只需要头指针通过一个函数来对链表进行处理,通过头指针就可以推算出链表的其他信息。链表的分类有:单链表(每个结点指针只能指向后一个结点--尾结点除外),双链表(每个结点有两个指针域,前一个指针域指向前驱结点,后一个指针域指向后继结点),循环链表(能通过任何一个结点找到其它结点--尾结点可以指向头结点),还有非循环链表等;
结点的表示
typedef struct Node
{
int data;//数据域
struct Node *pNext;//指针域,指向本身和它一样的结构体(数据类型)
}NODE,*PNODE;//NODE等价于struct Node,PNODE等价于struct Node*
链表的创建和遍历
实例说明:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
int data;//数据域
struct Node *pNext;//指针域
}NODE,*PNODE;
PNODE CreateList(void);//void表示无形参
void TraverseList(PNODE);//此处省略形参名
int main()
{
PNODE pHead=NULL;
pHead=CreateList();//创建链表,并将返回的头结点的地址赋给pHead
TraverseList(pHead);//遍历链表
return 0;
}
PNODE CreateList(void)
{
int len;//用来存放有效结点的个数
int i;
int val;//用来临时存放用户输入结点的值
PNODE pHead=(PNODE)malloc(sizeof(NODE));//动态分配一个块内存,该内存用来存放头结点
PNODE pNew;
PNODE pTail=pHead;
pTail->pNext=NULL;
if(NULL==pHead)
{
printf("分配失败,程序终止!\n");
exit(-1);//终止程序运行
}
printf("请输入您要创建链表的结点个数:len=");
scanf("%d",&len);
for(i=0;i<len;i++)
{
printf("请输入第%d个结点的值:",i+1);
scanf("%d",&val);
pNew=(PNODE)malloc(sizeof(NODE));//每循环一次,动态分配一个新临时结点
if(NULL==pNew)
{
printf("分配失败,程序终止!\n");
exit(-1);
}
pNew->data=val;//为新节点数据域赋值
pTail->pNext=pNew;//将新节点挂到尾结点后面
pNew->pNext=NULL;//将新节点的指针域设为空
pTail=pNew;//每次循环,让新节点成为尾节点
}
return pHead;
}
void TraverseList(PNODE pHead)
{
PNODE p=pHead->pNext;//此时p指向首节点
while(p!=NULL)
{
printf("%d ",p->data);
p=p->pNext;//将p的指针域指向下一个结点(指针域为空时,说明已经到了尾结点)
}
printf("\n");
}
注意
1. 第一个结点的指针域指向下一个结点(地址)的整体信息。
2.若p指针指向某个结点(头结点和尾结点除外),则p本身没有指针域,p指向的那个结构体变量(结点)才有指针域。