带头节点的单向链表(联系人列表)(C)
程序员文章站
2022-03-15 17:37:02
...
首先定义结点和头结点的内容,普通结点的数据域包含姓名、电话、公司信息,地址域保存下一个结点的地址。头结点数据域保存表长,地址域保存第一个结点地址。
struct PersonNode //普通结点
{
char name[NameLen];
char phone[PhoneLen];
char company[CompanyLen];
struct PersonNode *pstNext; //指针域:指向下一个结点
};
struct PLHead //头结点
{
int len;
struct PersonNode *pstFirst;
};
普通结点动态分配内存和释放内存:
struct PersonNode *CreateNewNode(struct PersonNode *pstData) //新结点动态分配内存空间
{
struct PersonNode *pstNew = NULL;
pstNew = (struct PersonNode *)malloc(sizeof(struct PersonNode)); //需要强制转换成struct类型的指针
if(pstNew == NULL)
{
printf("Malloc failed!\n");
return NULL;
}
if(pstData != NULL)
{
memcpy(pstNew,pstData,sizeof(struct PersonNode)); //把结点内容复制到动态分配的新结点的内存空间
pstNew->pstNext = NULL; //并让新结点的指针域清零
}
else
{
memset(pstNew,0,sizeof(struct PersonNode));
}
return pstNew;
}
int DestroyNode(struct PersonNode *pstNode) //删除结点后释放内存空间
{
if(pstNode != NULL)
{
free(pstNode);
pstNode = NULL;
}
return 0;
}
头结点动态分配内存和释放内存,释放头结点即释放整个链表空间。
struct PLHead *CreatePLHead() //头结点动态内存分配
{
struct PLHead *pstNew = NULL;
pstNew = (struct PLHead *)malloc(sizeof(struct PLHead)); //需要强制转换成struct类型的指针
if(pstNew == NULL)
{
printf("Malloc failed!\n");
return NULL;
}
memset(pstNew,0,sizeof(struct PLHead));
return pstNew;
}
int DestroyPLHead(struct PLHead *pstHead) //释放头结点即释放整个链表
{
struct PersonNode *pstNode = NULL;
struct PersonNode *pstNext = NULL;
if(pstHead ==NULL)
{
return -1;
}
pstNode = pstHead->pstFirst;
while(pstNode != NULL)
{
pstNext = pstNode->pstNext;
DestoryNode(pstNode);
pstNode = pstNext;
}
free(pstHead); //最后不要忘了把头结点的内存释放掉
pstHead = NULL;
return 0;
}
在链表尾部插入一个新结点。
思路:用一个指针变量保存原链表的最后一个结点,让最后一个结点的指针域指向新结点,新结点的指针域指向NULL。最后不要忘了更新头结点中的表长信息。
int InsertPersonNodeAtTail(struct PLHead *pstHead,struct PersonNode *pstNewNode) //在尾部插入新结点
{
struct PersonNode *pstLast = NULL;
if(pstHead == NULL || pstNewNode == NULL)
{
return -1;
}
pstLast = pstHead->pstFirst;
while(pstLast != NULL) //从头结点移动到尾结点
{
if(pstLast->pstNext == NULL)
{
break;
}
pstLast = pstLast->pstNext;
}
if(pstLast == NULL)
{
pstHead->pstFirst = pstNewNode; //如果最后一个结点为空,证明这是个空表,新元素插入到头指针
}
else
{
pstLast->pstNext = pstNewNode; //非空表,最后一个结点地址域指向新结点
}
pstNewNode->pstNext = NULL;
pstHead->len++; //更改头结点中的表长
return 0;
}
移除结点:分为空表、移除第一个结点和移除一般结点三种考虑,最后不要忘了更新头结点中的表长信息。
int RemovePersonNode(struct PLHead *pstHead,struct PersonNode *pstNode)
{
struct PersonNode *pstPrev = NULL; //保存要删除的结点的上一个结点的地址
struct PersonNode *pstTemp = NULL; //保存头结点的地址
if(pstHead == NULL || pstNode == NULL)
{
return -1;
}
pstTemp = pstHead->pstFirst;
if(pstTemp == NULL)
{
return -1; //空表
}
if(pstTemp == pstNode)
{
pstHead->pstFirst = pstNode->pstNext; //要移除的结点是第一个结点
pstNode->pstNext = NULL;
}
else
{
while(pstTemp != NULL)
{
if(pstTemp->pstNext == pstNode)
{
pstPrev = pstTemp;
break;
}
pstTemp = pstTemp->pstNext;
}
if(pstPrev == NULL)
{
return -1;
}
else
{
pstPrev->pstNext = pstNode->pstNext;
pstNode->pstNext = NULL;
}
}
pstHead->len--;
return 0;
}
通过姓名查找结点:
struct PersonNode * SearchNodeByName(struct PLHead *pstHead,char *name) //返回查找结点位置
{
struct PersonNode *pstNode = NULL;
if(pstHead == NULL || name == NULL)
{
return NULL;
}
pstNode = pstHead->pstFirst;
while(pstNode != NULL)
{
if(strcmp(pstNode->name,name) == 0)
{
break;
}
pstNode = pstNode->pstNext;
}
return pstNode;
}
实现函数功能
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define NameLen 20
#define PhoneLen 12
#define CompanyLen 20
struct PersonNode //普通结点
{
char name[NameLen];
char phone[PhoneLen];
char company[CompanyLen];
struct PersonNode *pstNext; //指针域:指向下一个结点
};
struct PLHead //头结点
{
int len;
struct PersonNode *pstFirst;
};
int DestroyNode(struct PersonNode *pstNode);
int PrintAllNode(struct PLHead *pstHead);
struct PLHead *CreatePLHead() //头节点动态内存分配
{
struct PLHead *pstNew = NULL;
pstNew = (struct PLHead *)malloc(sizeof(struct PLHead)); //需要强制转换成struct类型的指针
if(pstNew == NULL)
{
printf("Malloc failed!\n");
return NULL;
}
memset(pstNew,0,sizeof(struct PLHead));
return pstNew;
}
int DestroyPLHead(struct PLHead *pstHead) //释放头节点即释放整个链表
{
struct PersonNode *pstNode = NULL;
struct PersonNode *pstNext = NULL;
if(pstHead ==NULL)
{
return -1;
}
pstNode = pstHead->pstFirst;
while(pstNode != NULL)
{
pstNext = pstNode->pstNext;
DestoryNode(pstNode);
pstNode = pstNext;
}
free(pstHead); //最后不要忘了把头节点的内存释放掉
pstHead = NULL;
return 0;
}
struct PersonNode *CreateNewNode(struct PersonNode *pstData) //新节点动态分配内存空间
{
struct PersonNode *pstNew = NULL;
pstNew = (struct PersonNode *)malloc(sizeof(struct PersonNode)); //需要强制转换成struct类型的指针
if(pstNew == NULL)
{
printf("Malloc failed!\n");
return NULL;
}
if(pstData != NULL)
{
memcpy(pstNew,pstData,sizeof(struct PersonNode)); //把节点内容复制到动态分配的新节点的内存空间
pstNew->pstNext = NULL; //并让新节点的指针域清零
}
else
{
memset(pstNew,0,sizeof(struct PersonNode));
}
return pstNew;
}
int DestroyNode(struct PersonNode *pstNode) //删除节点后释放内存空间
{
if(pstNode != NULL)
{
free(pstNode);
pstNode = NULL;
}
return 0;
}
int InsertPersonNodeAtTail(struct PLHead *pstHead,struct PersonNode *pstNewNode) //在尾部插入新节点
{
struct PersonNode *pstLast = NULL;
if(pstHead == NULL || pstNewNode == NULL)
{
return -1;
}
pstLast = pstHead->pstFirst;
while(pstLast != NULL) //从头节点移动到尾节点
{
if(pstLast->pstNext == NULL)
{
break;
}
pstLast = pstLast->pstNext;
}
if(pstLast == NULL)
{
pstHead->pstFirst = pstNewNode; //如果最后一个节点为空,证明这是个空表,新元素插入到头指针
}
else
{
pstLast->pstNext = pstNewNode; //非空表,最后一个节点地址域指向新节点
}
pstNewNode->pstNext = NULL;
pstHead->len++; //更改头节点中的表长
return 0;
}
int RemovePersonNode(struct PLHead *pstHead,struct PersonNode *pstNode)
{
struct PersonNode *pstPrev = NULL; //保存要删除的节点的上一个节点的地址
struct PersonNode *pstTemp = NULL; //保存头节点的地址
if(pstHead == NULL || pstNode == NULL)
{
return -1;
}
pstTemp = pstHead->pstFirst;
if(pstTemp == NULL)
{
return -1; //空表
}
if(pstTemp == pstNode)
{
pstHead->pstFirst = pstNode->pstNext; //要移除的节点是第一个节点
pstNode->pstNext = NULL;
}
else
{
while(pstTemp != NULL)
{
if(pstTemp->pstNext == pstNode)
{
pstPrev = pstTemp;
break;
}
pstTemp = pstTemp->pstNext;
}
if(pstPrev == NULL)
{
return -1;
}
else
{
pstPrev->pstNext = pstNode->pstNext;
pstNode->pstNext = NULL;
}
}
pstHead->len--;
return 0;
}
struct PersonNode * SearchNodeByName(struct PLHead *pstHead,char *name) //返回查找节点位置
{
struct PersonNode *pstNode = NULL;
if(pstHead == NULL || name == NULL)
{
return NULL;
}
pstNode = pstHead->pstFirst;
while(pstNode != NULL)
{
if(strcmp(pstNode->name,name) == 0)
{
break;
}
pstNode = pstNode->pstNext;
}
return pstNode;
}
int main(int agrc,char *argv[])
{
struct PLHead *pstHead = CreatePLHead(); //创造头节点
struct PersonNode *pstNew = NULL;
struct PersonNode NodeData = {""};
strcpy(NodeData.name,"PiQi");
strcpy(NodeData.name,"15600663787");
strcpy(NodeData.company,"MicroSoft");
pstNew = CreateNewNode(&NodeData);
InsertPersonNodeAtTail(pstHead,pstNew);
strcpy(NodeData.name,"ChenXinxin");
strcpy(NodeData.name,"15600665727");
strcpy(NodeData.company,"IBM");
pstNew = CreateNewNode(&NodeData);
InsertPersonNodeAtTail(pstHead,pstNew);
strcpy(NodeData.name,"SuDongpo");
strcpy(NodeData.name,"16619951990");
strcpy(NodeData.company,"Microsoft");
pstNew = CreateNewNode(&NodeData);
InsertPersonNodeAtTail(pstHead,pstNew);
PrintAllNode(pstHead);
return 0;
}
int PrintAllNode(struct PLHead *pstHead)
{
struct PersonNode *pstNode = NULL;
if(pstHead == NULL)
{
return -1;
}
pstNode = pstHead->pstFirst;
while(pstNode != NULL)
{
printf("Name:%s PhoneNumber:%s Company:%s\n",pstNode->name,pstNode->phone,pstNode->company);
pstNode = pstNode->pstNext;
}
return 0;
}
上一篇: 不带头结点单链表的基本操作
下一篇: 定时执行函数