一.定义:
链表(listed list)就是一些包含数据的独立数据结构(通常成为节点)的集合。链表中的每个节点通过链或者指针连接起来。程序通过指针访问链表中的节点。通常节点是动态分配的,但是有的时候也能看到由节点数组构建的链表。(此定义来自《c与指针》的第12章)。
我自己理解就是链表的特点就是方便通过指针遍历所有节点,特别是双链,可以通过一个指针向前或者向后遍历所有节点,链表使得数据的结构更加清晰,另外链表一般使用动态内存,根据需求分配空间。单链表和双链表并没有固定的格式,可以根据自己的理解去设计。
二.下面分享单链表和双链表的示意图
三.接下来分别介绍如下的功能:
1.结构体定义
/*每个节点的结构体*/
typedef struct stDoubleLink {
struct stDoubleLink *pPre ; /*指向前一个节点*/
struct stDoubleLink *pNext ; /*指下一个一个节点*/
Uint u32Worknum ; /*员工工号*/
Uint u32Wage ; /*员工工资*/
}stDoubleLink;
/*为了输入参数准备的结构体*/
typedef struct Double_link_Value {
Uint u32Worknum_Value ; /*员工工号*/
Uint u32Wage_Value ; /*员工工资*/
}Double_link_Value;
2.新建链表
主要就是把链表的前后对应关系搭建好。
/*
* 函数名称:mag_link_creat
* 函数功能描述:新建链表,并把头节点返回。
* 函数传递变量:Uint u32Link_Length
* 函数返回值:pHead
* 函数作者:Mr.shang
* 时间:2019.9.8
* 修改记录:
* 修改原因 修改内容 修改时间 修改人
*
*/
stDoubleLink *mag_link_creat(Uint u32Link_Length)
{
stDoubleLink *pHead,*pN_Temp,*pM_Temp;
Double_link_Value stValue_Temp;
Uint u32i=0;
pHead=(stDoubleLink *)malloc(sizeof(stDoubleLink));
memset(pHead,0,sizeof(stDoubleLink));
pHead->pNext=pHead;
pHead->pPre=pHead;
pM_Temp=pHead;
for(u32i=0;u32i<u32Link_Length;u32i++)
{
pN_Temp=(stDoubleLink *)malloc(sizeof(stDoubleLink));
memset(pN_Temp,0,sizeof(stDoubleLink));
memset(&stValue_Temp,0,sizeof(Double_link_Value));
stValue_Temp=mag_scanf_fun(stValue_Temp);
pN_Temp->u32Worknum=stValue_Temp.u32Worknum_Value;
pN_Temp->u32Wage=stValue_Temp.u32Wage_Value;
pM_Temp->pNext=pN_Temp;/*前一个节点指向下一个节点*/
pHead->pPre=pN_Temp; /*头节点的前一个节点为最新的节点*/
pN_Temp->pNext=pHead;/*新节点指向头节点*/
pN_Temp->pPre=pM_Temp;/*新节点指向前一个节点*/
pM_Temp=pN_Temp; /*前一个节点跳到本节点,为下次准备*/
}
return pHead;
}
2.查询链表
/*
* 函数名称:mag_link_inquire
* 函数功能描述:按照员工工号查询员工信息。
* 函数传递变量:stDoubleLink *pHead_Temp, Uint u32Worknum_Temp
* 函数返回值:无
* 函数作者:Mr.shang
* 时间:2019.9.8
* 修改记录:
* 修改原因 修改内容 修改时间 修改人
*
*/
void mag_link_inquire(stDoubleLink *pHead_Temp, Uint u32Worknum_Temp)
{
stDoubleLink *pN_Temp,*pM_Temp;
/*判断指针是否为空指针,在程序里面使用空指针会带来严重的后果*/
if(NULL==pHead_Temp)
{
return;
}
pN_Temp=pHead_Temp;
pN_Temp=pN_Temp->pNext;
while(pN_Temp!=pHead_Temp)
{
if(u32Worknum_Temp==pN_Temp->u32Worknum)
{
printf("查询到的员工信息:工号:%d,工资:%d\n",pN_Temp->u32Worknum,pN_Temp->u32Wage);
}
pN_Temp=pN_Temp->pNext;
}
}
3.按照员工工资排序
/*
* 函数名称:mag_link_rank
* 函数功能描述:根据员工工资从小到大进行排序。
* 函数传递变量:stDoubleLink *pHead_Temp
* 函数返回值:无
* 函数作者:Mr.shang
* 时间:2019.9.8
* 修改记录:
* 修改原因 修改内容 修改时间 修改人
*
*/
void mag_link_rank(stDoubleLink *pHead_Temp)
{
stDoubleLink *pN_Temp,*pM_Temp;
Double_link_Value stValue_Temp;
/*判断指针是否为空指针,在程序里面使用空指针会带来严重的后果*/
if(NULL==pHead_Temp)
{
return;
}
pN_Temp=pHead_Temp;
pN_Temp=pN_Temp->pNext;
for(;pN_Temp!=pHead_Temp;pN_Temp=pN_Temp->pNext)
{
for(pM_Temp=pN_Temp->pNext;pM_Temp!=pHead_Temp;pM_Temp=pM_Temp->pNext)
{
if(pN_Temp->u32Wage>pM_Temp->u32Wage)
{
stValue_Temp.u32Wage_Value=pN_Temp->u32Wage;
stValue_Temp.u32Worknum_Value=pN_Temp->u32Worknum;
pN_Temp->u32Wage=pM_Temp->u32Wage;
pN_Temp->u32Worknum=pM_Temp->u32Worknum;
pM_Temp->u32Wage=stValue_Temp.u32Wage_Value;
pM_Temp->u32Worknum=stValue_Temp.u32Worknum_Value;
}
}/* for(pM_Temp=pN_Temp->pNext;pM_Temp!=pHead_Temp;pM_Temp=pM_Temp->pNext)*/
}/*for(;pN_Temp!=pHead_Temp;pN_Temp=pN_Temp->pNext)*/
}
4.删除某个节点:
/*
* 函数名称:mag_link_delete_one
* 函数功能描述:根据员工工号删除该员工信息,并释放该节点的空间。
* 函数传递变量:stDoubleLink *pHead_Temp, Uint u32Worknum_Temp
* 函数返回值:无
* 函数作者:Mr.shang
* 时间:2019.9.8
* 修改记录:
* 修改原因 修改内容 修改时间 修改人
*
*/
void mag_link_delete_one(stDoubleLink *pHead_Temp,Uint u32Worknum_Temp)
{
stDoubleLink *pN_Temp=NULL;
stDoubleLink *pT_Temp=NULL;
/*判断指针是否为空指针,在程序里面使用空指针会带来严重的后果*/
if(NULL==pHead_Temp)
{
return;
}
pN_Temp=pHead_Temp;
pN_Temp=pN_Temp->pNext;
while(pN_Temp!=pHead_Temp)
{
if(u32Worknum_Temp==pN_Temp->u32Worknum)
{
printf("删除的员工信息:工号:%d,工资:%d\n",pN_Temp->u32Worknum,pN_Temp->u32Wage);
pT_Temp=pN_Temp;/*记住要删除链表*/
pN_Temp=pN_Temp->pNext;/*到下一个节点*/
(pT_Temp->pPre)->pNext =pN_Temp;/*将本节点的上一个节点和下一个节点连接*/
pN_Temp->pPre=pT_Temp->pPre;/*将本节点下一个点与上一个节点连接*/
free(pT_Temp);/*释放节点*/
}
else
{
pN_Temp=pN_Temp->pNext;/*到下一个节点*/
}
}/*while(pN_Temp!=pHead_Temp)*/
}
5.scanf函数的使用(人机交互)
/*
* 函数名称:mag_scanf_fun
* 函数功能描述:用键盘输入员工信息,并判断输入是否正确。
* 函数传递变量:Double_link_Value stLink_Value_Temp
* 函数返回值:Double_link_Value stLink_Value_Temp
* 函数作者:Mr.shang
* 时间:2019.9.8
* 修改记录:
* 修改原因 修改内容 修改时间 修改人
*
*/
Double_link_Value mag_scanf_fun(Double_link_Value stLink_Value_Temp)
{
Uchar u8Scanf_flag=0;
Int s32Scanf_Return=0;
while(0==u8Scanf_flag)
{
printf("请输入员工工号\n");
s32Scanf_Return=scanf("%d",&stLink_Value_Temp.u32Worknum_Value);
if(EOF==s32Scanf_Return)
{
while(getchar()!='\n');
printf("scanf输入异常\n");
}
else if(0==s32Scanf_Return)
{
while(getchar()!='\n');
printf("scanf输入异常\n");
}
else if(1==s32Scanf_Return)
{
u8Scanf_flag=1;
}
}/* while(0==u8Scanf_flag)*/
u8Scanf_flag=0;
while(0==u8Scanf_flag)
{
printf("请输入员工工资\n");
s32Scanf_Return=scanf("%d",&stLink_Value_Temp.u32Wage_Value);
if(EOF==s32Scanf_Return)
{
while(getchar()!='\n');
printf("scanf输入异常\n");
}
else if(0==s32Scanf_Return)
{
while(getchar()!='\n');
printf("scanf输入异常\n");
}
else if(1==s32Scanf_Return)
{
u8Scanf_flag=1;
}
}/* while(0==u8Scanf_flag)*/
return stLink_Value_Temp;
}
四.总述
链表的难点:
1.就是需要理清楚每个节点的关系。
2.堆空间的申请和释放。