c语言 使用结构体链表实现信息管理系统/通讯录(增删改查)(含编号排序)
前言
本章主要介绍了使用链表存储信息,包括基本的增删改查功能。
1.增加成员功能
思路:先定义常规的头节点和尾节点,创建新节点接受信息,taii(尾部)要先遍历往后走,找到
下一个是空节点时停下,这个时候tail下一个就是新节点,新节点又变为tail。
tips:由于电话号码是11位的,因此要用long long来储存,不然会出现乱码现象。
附上代码:
struct Node* Add(Node* header)
{
int input = 0;
Node* tail = header;
while (tail->next != NULL)
{
tail = tail->next;
}
printf("请输入要添加的人数:>");
scanf("%d", &input);
for (int i = 0; i < input; i++)
{
Node* newnode = (Node*)malloc(sizeof(Node));//创建新节点
tail->next = newnode;
tail = newnode;
newnode->next = NULL;
printf("请输入姓名:>\n");
while (1)
{
scanf("%s", &newnode->name);
char c = getchar();
if (c == '\n')
{
break;
}
}
printf("请输入编号:>\n");
scanf("%d", &newnode->number);
printf("请输入年龄:>\n");
scanf("%d", &newnode->age);
printf("请输入电话号码:>\n");
scanf("%lld", &newnode->phonenumber);
}
return header;
}
2.删除成员功能
思路:通过查找删除信息的编号寻找,基本思路也是遍历之后找到就free删除,找不到就说找不到。
tips:由于删除后保持链表的完整性,因此要创造两个节点,即front(前部节点)与back(后部节点),
删除特定节点后应有front的下一个节点为back的下一个节点,让我画图来解释。
附上代码:
void Delete(Node* header)
{
int delnumber = 0;
printf("请输入你想删除信息的编号:>");
scanf("%d", &delnumber);
if (NULL == header)
{
return;
}
Node* front = header;
Node* back = header->next;
while (back != NULL)
{
if (back->number == delnumber)
{
break;
}
//遍历找delnumber
front = back;
back = back->next;
}
//找到了就删除,找不到就退出。
if (back == NULL)
{
printf("未找到该名队员\n");
printf("*****************************\n");
return;
}
front->next = back->next;
free(back);
back = NULL;
printf("删除成功!\n");
}
3.展示全部成员信息
思路:当下一个节点不为空时,就遍历输出,有点想循环的原理。
void Display(Node* header)
{
Node* receiver = header->next;
if (NULL == receiver)
{
printf("无信息\n");
return;
}
while (receiver != NULL)
{
printf("姓名:%s\n", receiver->name);
printf("编号:%d\n", receiver->number);
printf("年龄:%d\n", receiver->age);
printf("电话号码:%lld\n", receiver->phonenumber);
receiver = receiver->next;
printf("\n");
printf("*********************************************\n");
}
}
4.使用姓名查找某一特定成员
思路:依旧是遍历,使用了strcmp函数判断姓名字符串是否相等(注意引用头文件string.h)
我在这里处理了重名情况,找到名字后没有跳出遍历过程,而是继续寻找,并且定义了一个sum变量,sum
大于0时就会打印特定内容
附上代码:
void Find(Node* header)
{
int sum = 0;
printf("请输入要查找的名字:>");
char name_1[30] = { 0 };
scanf("%s", name_1);
struct Node* pCurrent = header->next;
if (NULL == header)
{
return;
}
while (pCurrent != NULL)
{
if (strcmp(pCurrent->name, name_1) == 0)
{
printf("姓名:%s\n", pCurrent->name);
printf("编号:%d\n", pCurrent->number);
printf("年龄:%d\n", pCurrent->age);
printf("电话号码:%lld\n", pCurrent->phonenumber);
printf("\n");
printf("*********************************************\n");
sum++;//处理重名
}
pCurrent = pCurrent->next;
}
if (sum > 0)
{
printf("找到了重名的队员\n");
printf("******************************\n");
}
if (NULL == pCurrent)
{
return;
}
}
5.修改成员信息:
思路:还是遍历找特定成员,之后将其拆分为四个板块,分别可以修改四个模块的信息,这样比较清晰。
tips:由于传了节点过去,所以重新输入节点的信息就好。
void ReviseName(Node* node)
{
char name_2[25] = { 0 };
printf("请输入更改后的姓名:>");
scanf("%s", name_2);
strcpy(node->name, name_2);
}
void ReviseNumber(Node* node)
{
printf("请输入更改后的编号:>");
scanf("%d", &node->number);
}
void ReviseAge(Node* node)
{
printf("请输入更改后的编号:>");
scanf("%d", &node->age);
}
void RevisePhonenumber(Node* node)
{
printf("请输入更改后的手机号码:>");
while (1)
{
scanf("%lld", &node->phonenumber);
char c = getchar();
if (c == '\n')
{
break;
}
}
}
void Revise(Node* header)
{
if (NULL == header)
{
return;
}
int input = 0;
int input2 = 0;
printf("请输入需要修改信息的队员的编号:>");
scanf("%d", &input);
Node* node = header->next;
while (node != NULL)
{
if (node->number == input)
{
break;
}
node = node->next;
}
if (NULL == node)
{
return;
}
do
{
printf("请输入对应的编号\n");
printf("*******1.修改姓名******\n");
printf("*******2.修改编号******\n");
printf("*******3.修改年龄******\n");
printf("*******4.修改电话号码******\n");
printf("*******0.退出修改**********\n");
scanf("%d", &input2);
switch (input2)
{
case 1:
ReviseName(node);
break;
case 2:
ReviseNumber(node);
break;
case 3:
ReviseAge(node);
break;
case 4:
RevisePhonenumber(node);
break;
}
} while (input2);
}
6.将编号进行冒泡排序
思路:分为两部分,一个为遍历部分,一个为交换部分。
①遍历部分
思路:找到前一个节点编号比后一个大的,就进入函数Exchange。
特别提示!!!:由于交换了前后节点,所以需要借助外在节点来实现调整后的后节点成为
front节点,调整后的前节点成为后节点,不然的话外部的遍历过程就进行不下去了。建议
读者亲自调试一下,有点难理解。
void BubblingsSorting(Node* header)
{
Node* front = header->next;
if (NULL == front)
{
return;
}
while (front != NULL)
{
Node* back = front->next;
while (back != NULL)
{
if (front->number > back->number)
{
Exchange(header, front, back);
Node* help = front;//需设置一个辅助节点调整前后顺序。
front = back;
back = help;
}
back = back->next;
}
front = front->next;
}
}
②:交换部分
思路:大体分为两种主要情况,即node1和node2相岭与不相邻的过程
α.相邻
只需借助两个节点,即node1前一个节点和node2后一个节点。再按照以下顺序prenode1->node2->
node1->postnode2
β.不相邻
需要四个辅助节点,即从一开始的prenode1->node1->postnode1变为prenode1>node2->postnode2
另外一个同理。
建议画图理解
void Exchange(Node* header, Node* node1, Node* node2)
{
Node* prenode1 = NULL; //node1的前一个节点
Node* postnode1 = NULL; //node1的后一个节点
Node* prenode2 = NULL; //node2的前一个节点
Node* postnode2 = NULL; //node2的后一个节点
Node* tmp = header;
if (node1 == header)
{
return;
}
else if (node2 == header)
{
return;
}
if (node1 == node2)
{
return;
}
if (node1->next == node2)//node1与node2相邻的情况。
{
tmp = header;
while (tmp->next != node1)
{
tmp = tmp->next;
}//只需使用prenode1和postnode2
prenode1 = tmp;//node1前一个
postnode2 = node2->next;
prenode1->next = node2;
node2->next = node1;
node1->next = postnode2;
return;
}
while (tmp->next != node1)
{
tmp = tmp->next;
}
prenode1 = tmp;//遍历找node1
while (tmp->next != node2)
{
tmp = tmp->next;
}
prenode2 = tmp;//遍历找node2
postnode1 = node1->next;
postnode2 = node2->next;
//交换节点
prenode1->next = node2;
node2->next = postnode1;
prenode2->next = node1;
node1->next = postnode2;
}
最后附上全部代码
头文件
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
typedef struct Node
{
char name[30];
int number;
int age;
long long phonenumber;
struct Node* next;
}Node;
struct Node* Add(Node* header);
void Display(Node* header);
void Delete(Node* header);
void Find(Node* header);
void Revise(Node* header);
void ReviseName(Node* node);
void ReviseNumber(Node* node);
void ReviseAge(Node* node);
void RevisePhonenumber(Node* node);
void BubblingsSorting(Node* header);
void Exchange(Node* header, Node* node1, Node* node2);
主函数
#include"TeamMembers.h"
void menu()
{
printf("************简约版信息管理系统*********\n");
printf("*****************请选择****************\n");
printf("***************1.添加队员**************\n");
printf("***************2.删除队员**************\n");
printf("***********3.按照姓名查找队员**********\n");
printf("***********4.修改队员信息**************\n");
printf("***********5.显示所有联系人信息********\n");
printf("*************0.退出程序****************\n");
}
int main()
{
int Choice = 0;
printf("请先创建一个信息\n");
Node* header = (Node*)malloc(sizeof(Node));
header->next = NULL;
header = Add(header);
BubblingsSorting(header);
do
{
printf("可以选择以下操作\n");
menu();
scanf("%d", &Choice);
system("cls");
switch(Choice)
{
case 1:
header = Add(header);
BubblingsSorting(header);
break;
case 2:
Delete(header);
break;
case 3:
Find(header);
break;
case 4:
Revise(header);
BubblingsSorting(header);
break;
case 5:
Display(header);
break;
}
} while (Choice);
return 0;
}
函数文件
#include"TeamMembers.h"
struct Node* Add(Node* header)
{
int input = 0;
Node* tail = header;
while (tail->next != NULL)
{
tail = tail->next;
}
printf("请输入要添加的人数:>");
scanf("%d", &input);
for (int i = 0; i < input; i++)
{
Node* newnode = (Node*)malloc(sizeof(Node));//创建新节点
tail->next = newnode;
tail = newnode;
newnode->next = NULL;
printf("请输入姓名:>\n");
while (1)
{
scanf("%s", &newnode->name);
char c = getchar();
if (c == '\n')
{
break;
}
}
printf("请输入编号:>\n");
scanf("%d", &newnode->number);
printf("请输入年龄:>\n");
scanf("%d", &newnode->age);
printf("请输入电话号码:>\n");
scanf("%lld", &newnode->phonenumber);
}
return header;
}
void Delete(Node* header)
{
int delnumber = 0;
printf("请输入你想删除信息的编号:>");
scanf("%d", &delnumber);
if (NULL == header)
{
return;
}
Node* front = header;
Node* back = header->next;
while (back != NULL)
{
if (back->number == delnumber)
{
break;
}
//遍历找delnumber
front = back;
back = back->next;
}
//找到了就删除,找不到就退出。
if (back == NULL)
{
printf("未找到该名队员\n");
printf("*****************************\n");
return;
}
front->next = back->next;
free(back);
back = NULL;
printf("删除成功!\n");
}
void Display(Node* header)
{
Node* receiver = header->next;
if (NULL == receiver)
{
printf("无信息\n");
return;
}
while (receiver != NULL)
{
printf("姓名:%s\n", receiver->name);
printf("编号:%d\n", receiver->number);
printf("年龄:%d\n", receiver->age);
printf("电话号码:%lld\n", receiver->phonenumber);
receiver = receiver->next;
printf("\n");
printf("*********************************************\n");
}
}
void Find(Node* header)
{
int sum = 0;
printf("请输入要查找的名字:>");
char name_1[30] = { 0 };
scanf("%s", name_1);
struct Node* pCurrent = header->next;
if (NULL == header)
{
return;
}
while (pCurrent != NULL)
{
if (strcmp(pCurrent->name, name_1) == 0)
{
printf("姓名:%s\n", pCurrent->name);
printf("编号:%d\n", pCurrent->number);
printf("年龄:%d\n", pCurrent->age);
printf("电话号码:%lld\n", pCurrent->phonenumber);
printf("\n");
printf("*********************************************\n");
sum++;//处理重名
}
pCurrent = pCurrent->next;
}
if (sum > 0)
{
printf("找到了重名的队员\n");
printf("******************************\n");
}
if (NULL == pCurrent)
{
return;
}
}
void ReviseName(Node* node)
{
char name_2[25] = { 0 };
printf("请输入更改后的姓名:>");
scanf("%s", name_2);
strcpy(node->name, name_2);
}
void ReviseNumber(Node* node)
{
printf("请输入更改后的编号:>");
scanf("%d", &node->number);
}
void ReviseAge(Node* node)
{
printf("请输入更改后的编号:>");
scanf("%d", &node->age);
}
void RevisePhonenumber(Node* node)
{
printf("请输入更改后的手机号码:>");
while (1)
{
scanf("%lld", &node->phonenumber);
char c = getchar();
if (c == '\n')
{
break;
}
}
}
void Revise(Node* header)
{
if (NULL == header)
{
return;
}
int input = 0;
int input2 = 0;
printf("请输入需要修改信息的队员的编号:>");
scanf("%d", &input);
Node* node = header->next;
while (node != NULL)
{
if (node->number == input)
{
break;
}
node = node->next;
}
if (NULL == node)
{
return;
}
do
{
printf("请输入对应的编号\n");
printf("*******1.修改姓名******\n");
printf("*******2.修改编号******\n");
printf("*******3.修改年龄******\n");
printf("*******4.修改电话号码******\n");
printf("*******0.退出修改**********\n");
scanf("%d", &input2);
switch (input2)
{
case 1:
ReviseName(node);
break;
case 2:
ReviseNumber(node);
break;
case 3:
ReviseAge(node);
break;
case 4:
RevisePhonenumber(node);
break;
}
} while (input2);
}
void Exchange(Node* header, Node* node1, Node* node2)
{
Node* prenode1 = NULL; //node1的前一个节点
Node* postnode1 = NULL; //node1的后一个节点
Node* prenode2 = NULL; //node2的前一个节点
Node* postnode2 = NULL; //node2的后一个节点
Node* tmp = header;
if (node1 == header)
{
return;
}
else if (node2 == header)
{
return;
}
if (node1 == node2)
{
return;
}
if (node1->next == node2)//node1与node2相邻的情况。
{
tmp = header;
while (tmp->next != node1)
{
tmp = tmp->next;
}//只需使用prenode1和postnode2
prenode1 = tmp;//node1前一个
postnode2 = node2->next;
prenode1->next = node2;
node2->next = node1;
node1->next = postnode2;
return;
}
while (tmp->next != node1)
{
tmp = tmp->next;
}
prenode1 = tmp;//遍历找node1
while (tmp->next != node2)
{
tmp = tmp->next;
}
prenode2 = tmp;//遍历找node2
postnode1 = node1->next;
postnode2 = node2->next;
//交换节点
prenode1->next = node2;
node2->next = postnode1;
prenode2->next = node1;
node1->next = postnode2;
}
void BubblingsSorting(Node* header)
{
Node* front = header->next;
if (NULL == front)
{
return;
}
while (front != NULL)
{
Node* back = front->next;
while (back != NULL)
{
if (front->number > back->number)
{
Exchange(header, front, back);
Node* help = front;//需设置一个辅助节点调整前后顺序。
front = back;
back = help;
}
back = back->next;
}
front = front->next;
}
}