单向通用链表
封装的链表结构
该图纯手画,头结点不存放数据,data指针为空,Next指向下一个结点。(也可以封装成头结点存放数据,代码稍作修改即可)
这里用一个用户结构体作为例子,进行测试。
typedef struct user
{
char acNo[20]; // 用户账号
char acName[20]; // 用户姓名
char acPsw[10]; // 登入密码
}USER_T;
当获取对应结点后,只需将其中的data指针强转成对应结构体类型,即可获取数据
例如获取用户结构体中的用户名
( (USER_T*)(pTemp->data) )->acName
封装链表常用函数
- NODE_T* List_Init(void); //初始化结点
- void List_Add(NODE_T* pHead,void* data); //添加结点
- int List_GetCount(NODE_T* head); //获取链表结点个数
- NODE_T* List_GetNode(NODE_T* head,int iIndex); //获得指定结点位置
- void List_DelNode(NODE_T* head,int iIndex); //删除结点
- void List_Free(NODE_T* head); // 释放链表
代码如下
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct user
{
char acNo[20]; // 用户账号
char acName[20]; // 用户姓名
char acPsw[10]; // 登入密码
}USER_T;
typedef struct node
{
void* data;//数据指针
struct node* pNext;//指向下一个结点
}NODE_T;
////////////////////////////////////
NODE_T* List_Init(void); //初始化结点
void List_Add(NODE_T* pHead,void* data); //添加结点
int List_GetCount(NODE_T* head); //获取链表结点个数
NODE_T* List_GetNode(NODE_T* head,int iIndex); //获得指定结点位置
void List_DelNode(NODE_T* head,int iIndex); //删除结点
void List_Free(NODE_T* head); // 释放链表
void List_PrintUser(NODE_T* head); //打印用户(测试用)
///////////////////////////////////
int main()
{
NODE_T* pHead;
USER_T* pUser0=(USER_T*)malloc(sizeof(USER_T));
USER_T* pUser1=(USER_T*)malloc(sizeof(USER_T));
USER_T* pUser2=(USER_T*)malloc(sizeof(USER_T));
//初始化数据为0
memset(pUser0,0,sizeof(USER_T));
memset(pUser1,0,sizeof(USER_T));
memset(pUser2,0,sizeof(USER_T));
strcpy(pUser0->acName,"张全蛋");
strcpy(pUser1->acName,"张一蛋");
strcpy(pUser2->acName,"张二蛋");
pHead=List_Init();//初始化头结点
List_Add(pHead,pUser0);
List_Add(pHead,pUser1);
List_Add(pHead,pUser2);
printf("%d\n",List_GetCount(pHead)); //获取长度
List_PrintUser(pHead);//打印用户
return 0;
}
/**********************************************
函数名:
List_Init
功能:
初始化一个结点
参数:
void
返回值;
NODE_T* node
************************************************/
NODE_T* List_Init(void)
{
NODE_T* node=(NODE_T*)malloc(sizeof(NODE_T));
memset(node,0,sizeof(NODE_T));
return node;
}
/**********************************************
函数名:
List_Add
功能:
添加结点至链表
参数:
NODE_T* head(头结点指针)
void* pData (数据指针)
返回值;
void
************************************************/
void List_Add(NODE_T* pHead,void* pData)
{
NODE_T* pTemp=pHead;
NODE_T* pNew=List_Init();
pNew->data=pData;
pNew->pNext=NULL;
while(NULL!=pTemp->pNext) //下一个结点是否为空
{
pTemp=pTemp->pNext;
}
pTemp->pNext=pNew;
}
/**********************************************
函数名:
List_GetCount
功能:
获得链表结点个数 注意(结点个数包括头结点,头结点不放数据)
参数:
NODE_T* head(头结点指针)
返回值;
int iCount
************************************************/
int List_GetCount(NODE_T* head)
{
int iCount=1;//头结点初始化为空,默认长度为1
NODE_T* pTemp = head;
while(NULL!=pTemp->pNext) //下一个结点是否为空
{
pTemp=pTemp->pNext;
iCount++;
}
return iCount;
}
/**********************************************
函数名:
List_GetNode
功能:
获得指定结点 注意(获取长度不符合逻辑则返回NULL)
参数:
NODE_T* head(头结点指针)
int iIndex(链表结点)
返回值;
NODE_T* pTemp
************************************************/
NODE_T* List_GetNode(NODE_T* head,int iIndex)
{
NODE_T* pTemp = head;
int num = List_GetCount(head); //获得链表总长度
int iPos = 1;
if(iIndex > num || iIndex<1) //该节点大于或小于链表总长度
{
printf("get error\n");
getch();
return NULL; //注意!!错误时注意返回值为空
}
while(NULL != pTemp->pNext) //下一个结点不为空则进入循环
{
if(iIndex == 1)
{
return head; //取头节点
}
pTemp = pTemp->pNext;
iPos++;
if(iPos == iIndex )
{
return pTemp;
}
}
return pTemp; //若为尾部直接返回
}
/**********************************************
函数名:
List_DelNode
功能:
删除链表结点,注意(若删除头结点则直接结束函数)
参数:
NODE_T* head(头结点指针)
int iIndex(链表结点)
返回值;
void
************************************************/
void List_DelNode(NODE_T* head,int iIndex)
{
NODE_T* pTemp1 = head; //临时移动的节点
NODE_T* pTemp2 = NULL; //保存移动之前的节点
int iPos = 1;
if(iIndex == 1 || iIndex > List_GetCount(head) || iIndex < 1 ) //是否删除头结点 或者 删除长度 大于链表长度或是小于链表长度
{
return;
}
while(iPos < iIndex)
{
pTemp2=pTemp1;
pTemp1 = pTemp1->pNext;
iPos++;
}
pTemp2->pNext = pTemp1->pNext;
free(pTemp1->data);
free(pTemp1);
}
/**********************************************
函数名:
List_Free
功能:
释放链表
参数:
NODE_T* head(头结点指针)
返回值;
void
************************************************/
void List_Free(NODE_T* head)
{
NODE_T* pTemp =head;
if(NULL==pTemp->pNext) //判断是否只有头结点
{
free(head->data);
free(head);
return;
}
while(NULL != pTemp->pNext) //判断下一个结点是否为空
{
pTemp = pTemp->pNext;
free(head->data);
free(head);
head = pTemp;
}
free(pTemp->data); //释放最后一个结点
free(pTemp);
return;
}
/**********************************************
函数名:
List_PrintUser
功能:
从头结点开始打印链表
参数:
NODE_T* head(头结点指针)
返回值;
void
************************************************/
void List_PrintUser(NODE_T* head)
{
NODE_T* pTemp = head;
while(NULL != pTemp->pNext) //判断下一个结点是否为空
{
printf("%s\n",((USER_T*)(pTemp->pNext->data))->acName);
pTemp = pTemp->pNext;
}
}