C语言之单链表(头结点与节点结构不相同)
上代码:
头文件:
#ifndef __PLINK_H
#define __PLINK_H
#define NAME_LEN 20
#define PHONE_LEN 20
#define COMPANY_LEN 20
typedef struct PersonNode
{
char name[NAME_LEN];
char phone[PHONE_LEN];
char company[COMPANY_LEN];
struct PersonNode *pstNext;
}PersonNode;
typedef struct
{
int len;
PersonNode *pstFirst;
}PLHead;
int SingleLinkList(void);
int DestroyPLHead(PLHead *pstHead);
PLHead * CreatePLHead();
int DestroyNode(PersonNode *pstNode); //释放内存空间(free)
PersonNode *CreateNewNode(PersonNode *pstData); //申请内存空间(malloc)
PersonNode *SearchNodeName(PLHead *pstHead, char *name); //搜索第几个节点的信息
int AddPersonNode(PLHead *pstHead, PersonNode *pstNewNode); //追加一个节点
int RemovePersonNode(PLHead *pstHead, PersonNode *pstNode); //移除1个节点
int InsertPersonNode(PLHead *pstHead, PersonNode *pstNewNode, int addCount);//插入或追加1一个节点
源文件(.c)
/*
C语言数据结构与算法
带头结点的单链表
程序思路:
创建一个头结点
1.CreatePLHead()函数创建一个头结点
向单链表添加节点
1.定义PersonNode结构体变量存放节点的内容信息
2.使用CreateNewNode(&PersonNode)申请内存,将结构体PersonNode的内容信息复制到改内存中
3.使用AddPersonNode()或InsertPersonNode()函数向单链表添加节点
删除单链表的某一个节点
1.使用SearchNodeName()函数搜索你要删除的节点
2.使用RemovePersonNode()函数,将搜索到的节点从单链表中删除
3.使用DestroyNode()函数,将搜索到要删除的节点的内存free()释放掉
*/
#include "PLink.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//删除整条链表的内存空间
int DestroyPLHead(PLHead *pstHead)
{
PersonNode *pstNext = NULL;
PersonNode *pstNode = NULL;
if(pstHead == NULL)
{
return -1;
}
pstNode = pstHead->pstFirst;
while(pstNext != NULL)
{
pstNext = pstNode->pstNext;
DestroyNode(pstNode);
pstNode = pstNext;
}
free(pstHead);
pstHead = NULL;
return 0;
}
//创建头结点
PLHead * CreatePLHead()
{
PLHead *pstNew = NULL;
pstNew = (PLHead *)malloc(sizeof(PLHead) );
if(pstNew == NULL)
{
printf("Error malloc failed\n");
return NULL;
}
memset(pstNew, 0, sizeof(PLHead));
return pstNew;
}
//删除节点的内存
int DestroyNode(PersonNode *pstNode)
{
if(pstNode == NULL)
{
return -1;
}
else
{
free(pstNode);
pstNode = NULL;
}
return 0;
}
//创建节点申请内存
PersonNode *CreateNewNode(PersonNode *pstData) //申请内存空间(malloc)
{
PersonNode *pstNew = NULL;
pstNew = (PersonNode *)malloc(sizeof(PersonNode) );
if(pstNew == NULL)
{
printf("Error malloc failed\n");
return NULL;
}
if(pstData != NULL)
{
memcpy(pstNew, pstData, sizeof(PersonNode) );
}
else
{
memset(pstNew, 0, sizeof(PersonNode));
}
return pstNew;
}
//在链表末尾追加一个节点
int AddPersonNode(PLHead *pstHead, PersonNode *pstNewNode)
{
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(PLHead *pstHead, PersonNode *pstNode)
{
PersonNode *pstPrev = NULL;
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) //查询直到pstNode的上一个节点
{
pstPrev = pstTemp; //保存目标节点的上一个节点
pstTemp = pstTemp->pstNext; //目标节点
break;
}
pstTemp = pstTemp->pstNext; //目标节点
}
if(NULL == pstPrev)
{
return -1;
}
else
{
pstPrev->pstNext = pstTemp->pstNext;
pstNode->pstNext = NULL;
}
}
pstHead->len--;
return 0;
}
//在链表中搜索一个节点
PersonNode *SearchNodeName(PLHead *pstHead, char *name)
{
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 InsertPersonNode(PLHead *pstHead, PersonNode *pstNewNode, int addCount)
{
PersonNode *pst = NULL;
int count = addCount;
if(pstHead == NULL || pstNewNode == NULL || addCount <= 0 )//有头节点Head, addcount==0会把头节点移位
{
return -1;
}
if(addCount > pstHead->len)
{
if(addCount - pstHead->len == 1) //如果输入的addcount刚好在末尾处,则追加
{
AddPersonNode(pstHead, pstNewNode);
return 0;
}
else
{
return -1; //输入的addcount超出链表范围
}
}
pst = pstHead->pstFirst;
count--;
while (count--)
{
if(count == 0) break;
pst = pst->pstNext;
}
if(addCount == 1) //要插在第1个节点
{
pstNewNode->pstNext = pst;
pstHead->pstFirst = pstNewNode;
}
else
{
pstNewNode->pstNext = pst->pstNext;
pst->pstNext = pstNewNode;
}
pstHead->len++;
return 0;
}
测试代码:
//填写节点信息
int PersonData(PersonNode *pstData, char *name, char *phone, char *company)
{
strcpy(pstData->name, name);
strcpy(pstData->phone, phone);
strcpy(pstData->company, company);
return 0;
}
//打印链表
int PrintfPersonData(PLHead *pstHead)
{
PersonNode * pstNode = NULL;
if(pstHead == NULL) return -1;
pstNode = pstHead->pstFirst;
while(pstNode != NULL)
{
printf("name:%s phone:%s company:%s\n", pstNode->name, pstNode->phone, pstNode->company);
pstNode = pstNode->pstNext;
}
return 0;
}
//测试函数
int SingleLinkList(void)
{
PLHead *pstHead = CreatePLHead();
PersonNode *pstNew = NULL;
PersonNode personData ;
PersonNode *SearchName = NULL;
PersonData(&personData, "111", "1111111111", "Fly"); //节点数据
pstNew = CreateNewNode(&personData); //创建新的节点
// AddPersonNode(pstHead, pstNew);
InsertPersonNode(pstHead, pstNew, 1); //向链表添加新的节点
PersonData(&personData, "222", "22222222222", "NBA");
pstNew = CreateNewNode(&personData);
AddPersonNode(pstHead, pstNew); //自动追加到链表末尾
PersonData(&personData, "333", "33333333333", "FBI");
pstNew = CreateNewNode(&personData);
InsertPersonNode(pstHead, pstNew, 2);
PersonData(&personData, "444", "44444444444", "FBI");
pstNew = CreateNewNode(&personData);
InsertPersonNode(pstHead, pstNew, 4);
PrintfPersonData(pstHead); //打印链表信息
SearchName = SearchNodeName(pstHead, "444"); //查找name
printf("SearchName//name:%s phone:%s company:%s\n\n", SearchName->name, SearchName->phone, SearchName->company);
if(SearchName == NULL)
{
printf("Not find the name");
}
else
{
RemovePersonNode(pstHead, SearchName);
PrintfPersonData(pstHead); //打印链表信息
printf("\nhas been remove the Jack\n");
DestroyNode(SearchName);
}
PrintfPersonData(pstHead); //打印链表信息
return 0;
}
代码效果图: