单向链表实现增删改查
1.数据结构
typedef struct item
{
item *prev = NULL;
item *next = NULL;
char name[20];
int math;
int cna;
int eng;
int avg;
bool flag = false;//有内容标志,可以忽略掉第一个数据得问题
}date;
*prev------------->指向上一个数据存储空间的指针
*next------------->是指向下一个数据存储空间的指针
name------------>姓名char数组
cna--------------->语文成绩
eng--------------->英语成绩
math------------->数学成绩
avg--------------->平均分
flag-------------->是否具有数据标志,可以避免释放表头出现的内存泄漏问题
2.链表增加项目
void additem()//增
{
date *head;
date *ptr;
ptr = &first;
while (true)
{
if (ptr->flag == false)//该内存区域下没有数据
{
printf("name:\n");
fflush(stdin);//清除缓存空间 否则gets_s会因为检测缓存空间的空字符而跳过
gets_s(ptr->name);
printf("Math:\n");
scanf_s("%d", &ptr->math);
printf("Chinese:\n");
scanf_s("%d", &ptr->cna);
printf("English:\n");
scanf_s("%d", &ptr->eng);
ptr->avg = (ptr->cna + ptr->eng + ptr->math) / 3;
ptr->flag = true;
printf("write succed!\n\n\n");
break;
}
else//如果没有数据
{
if (ptr->next == NULL)//尚无开空间,开新空间
{
head = ptr;//记录前一个数据存储空间
ptr->next = (date*)malloc(sizeof(date));//开辟一个存储空间
ptr = ptr->next;
ptr->next = NULL;//初始化部分变量
ptr->prev = head;//记录上一个数据
ptr->flag = false;
}
else
{
ptr = ptr->next;//还有数据只想下一个数据存储空间
}
}
}
}
沿着 *next寻找空的数据,找到则分配存储空间,将有内容标志初始化为 false
3.展示数据
遍历整个链表,并将数据打印出来
void display()
{
date *ptr;
ptr = &first;//指向第一个存储空间
if (ptr->flag == false)
{
printf("no data in the link list\n");
return;
}
printf("***********************************************\n");
printf("Name Math Chinese English AVG\n");
while (true)
{
printf("%-9s%-9d%-12d%-12d%-3d\n", ptr->name, ptr->math, ptr->cna, ptr->eng, ptr->avg);
if (ptr->next == NULL)break;
else ptr = ptr->next;
}
printf("**********************************************\n");
}
初始化一个*ptr ptr等于first(第一个数据)的地址,通过*next指针遍历整个链表当*next指向空遍历结束
输入数据打印效果如下:
4.查找元素
date* search()//查
{
date *ptr;
ptr = &first;//指向第一个存储空间
char name[20];
printf("name:\n");
fflush(stdin);
gets_s(name);
while (true)
{
if (strcmp(ptr->name, name) == 0)break;//找到结果结束遍历
else if (ptr->next == NULL)///遍历结束未找到结果
{
printf("no date!\n");
return NULL;
}
else ptr = ptr->next;
}
printf("check the information\n");
printf("***********************************************\n");
printf("Name Math Chinese English AVG\n");
printf("%-9s%-9d%-12d%-12d%-3d\n", ptr->name, ptr->math, ptr->cna, ptr->eng, ptr->avg);
printf("**********************************************\n\n");
return ptr;
}
因为后面删,改多需要查询元素,该函数需要在后面进行调用,所以返回一个date类型指针即查找的结果。
date类型指针ptr最初指向first,之后进行遍历直到找到name与输入值相同的项,返回ptr指针(即指向匹配项地址)
查询效果如下:
5.修改链表内的元素
有了查找的基础,修改就非常容易实现了。
只需要查找获取匹配项的指针后,修改其值然后返回即可。
void modify()//改
{
char k=0;
date*ptr;
ptr = search();
printf("sure?(Y/N)\n");
k=_getch();
if (k == 'Y' || k == 'y')
{
printf("name:\n");
fflush(stdin);
gets_s(ptr->name);
printf("Math:\n");
scanf_s("%d",&ptr->math);
printf("Chinese:\n");
scanf_s("%d", &ptr->cna);
printf("English:\n", &ptr->eng);
scanf_s("%d", &ptr->eng);
printf("modify complete!\n");
}
}
6.删除链表中元素
首先还是需要调用search()函数获取匹配项指针,然后会出现多种情况:
1.
*prev不为空时
prev->next=ptr->next
2.若*prev为空 则说明已经是指向第一个数据first first=ptr->next即可
void delitem()//删
{
date *ptr;
ptr = search();
if (ptr == NULL)return;//没有搜寻到相关元素
printf("Are you sure?(Y/N)\n");
char key= _getch();
if (key == 'Y' || key == 'y')
{
if (ptr->prev != NULL)
{
ptr->prev->next = ptr->next;
ptr->next->prev = ptr->prev;
free(ptr);
}
else//如果是表头元素将其重新初始化即可
{
if (ptr->next != NULL)
{
first = *ptr->next;
first.prev = NULL;
}
else
{
printf("already no data in link list\n");
first.flag = false;
}
}
}
}