一、删除链表中指定的节点
1:先寻找删除点
代码体现:
STU* detele_link(STU *head,char *name)
{
//1、判断链表是否存在
if(head == NULL)//不存在
{
printf("link not foundn");
return head;
}
else//存在
{
//2、寻找删除点
STU *pf=head, *pb = head;
while(strcmp(pb->name,name)!=0 && pb->next != NULL)
{
pf = pb;
pb = pb->next;
}
//3、找到删除点
if(strcmp(pb->name,name)==0)//找到删除点
{
//4、判断删除的位置
if(pb == head)//删除头结点
{
head = pb->next;
free(pb);
}
else//中部 或 尾部节点
{
pf->next = pb->next;
free(pb);
}
printf("已成功删除%s的相关节点n",name);
return head;
}
else//没找到删除点
{
printf("链表中没有%s相关的数据节点信息n",name);
}
}
return head;
}
二、链表释放
代码体现:
STU* free_link(STU *head)
{
//判断链表是否存在
if(head == NULL)
{
printf("link not foundn");
return head;
}
else//链表存在
{
STU *pb = head;
//逐个节点释放
while(pb != NULL)
{
//head保存下一个节点的位置
head = pb->next;
//释放pb指向的节点
free(pb);
//pb 指向 head
pb = head;
}
printf("链表已经释放完毕n");
return head;
}
return head;
}
三、链表逆序
代码体现:
STU* reverse_link(STU *head)
{
//判断链表是否存在
if(head == NULL)
{
printf("link not founfn");
return head;
}
else//链表存在
{
//int *p,num;//p为int * , num为int
STU *pb,*pr;//pb为STU * , pr为STU *
//pb保存head->next(原因head->next会置NULL)
pb = head->next;
//将head->next置NULL (原因:头节点变尾节点)
head->next = NULL;
while(pb != NULL)
{
//pr保存pb->next (原因:pb->next会指向head)
pr = pb->next;
//pb->next 指向 head (原因:逆转方向)
pb->next = head;
//保存 逆转方向的代码 可以重复 执行
head = pb;
pb = pr;
}
return head;
}
return head;
}
四、回顾
1、链表插入:(三种)头部之前插入 尾部插入 有序插入
操作顺序:1、为插入的节点申请空间(calloc malloc都行)
2、将tmp的值赋给*pi
3、怕段链表是否存在(1):不存在,将此节点作为头节点 head=pi
(2):存在,(尾部插入,有序插入)安装具体的位置插入节点
2、链表的遍历:
判断链表是否存在,不存在:不执行任何操作;存在: 逐个节点去遍历, 注意 不能越界
3、链表的查询:
同样,判断链表是否存在,不存在:不执行任何操作;存在, 逐个节点进行比较 比较成功 返回位置 比较失败 返回NULL 注意 不能越界
4、链表节点的删除
判断链表是否存在,不存在:不执行任何操作;存在: 逐个节点去比较 删除指定节点, 注意 不能越界
5、链表的释放
判断链表是否存在,不存在:不执行任何操作;存在: 逐个节点去释放, 注意 不能越界
五、该系统的完整代码
main.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"link.h"
void stu_help(void);
int main(int argc,char *argv[])
{
//定义链表头,赋值为NULL
STU * head = NULL;
printf("欢迎使用学生信息系统n");
while(1)
{
char a[32]="";
printf("请输入指令:");
scanf("%s",a);
printf("n");
if(strcmp(a,"begin")==0)
{
stu_help();
}
else if(strcmp(a,"help")==0)
{
stu_help();
}
else if(strcmp(a,"insert")==0)
{
STU tmp;
printf("请输入需要插入的数据");
scanf("%d %s %d",&tmp.num,tmp.name,&tmp.score);
//将tmp数据 插入head所指向的链表中
head = insert_link(head,tmp);
}
else if(strcmp(a,"print")==0)
{
print_link(head);
}
else if(strcmp(a,"search")==0)
{
char name[32]="";
STU * ret =NULL;
printf("请输入你要查询的姓名:");
scanf("%s",name);
ret = search_link(head,name);
if(ret!=NULL)
{
printf("%s的信息为 学号:%d 姓名:%s 成绩:%d",name,ret->num,ret->name,ret->score);
}
else
{
printf("对不起 没有查询到%s的信息n",name);
}
}
else if(strcmp(a,"delete")==0)
{
char name[32]="";
printf("请输入需要删除信息的姓名:");
scanf("%s",name);
head=delete_link(head,name);
}
else if(strcmp(a,"reverse")==0)
{
head=reverse_link(head);
}
else if(strcmp(a,"free")==0)
{
head=free_link(head);
}
else if(strcmp(a,"quit")==0)
{
break;
}
else
{
printf("----错误信息----n");
}
}
return 0;
}
void stu_help(void)
{
printf("*********************************************n");
printf("** help:打印帮助信息 **n");
printf("** insert:插入链表节点 **n");
printf("** print:遍历链表节点信息 **n");
printf("** search:查询链表节点 **n");
printf("** delete:删除链表节点 **n");
printf("** free:释放链表 **n");
printf("** reverse:释放逆序 **n");
printf("** quit:退出 **n");
printf("*********************************************n");
return;
}
link .c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"link.h"
#if 0
//插入函数
STU *insert_link(STU *head,STU tmp)//链表头部的插入
{
//从堆区申请一个待插入的空间
STU *pi=(STU *)calloc(1,sizeof(STU));
if(pi==NULL)
{
perror("calloc");
return head;
}
//将tmp的值赋给 *pi
*pi=tmp;
pi->next=NULL;
//将pi插入到链表中
if(head==NULL)//表示链表不存在
{
head=pi;
return head;
}
else//表示链表存在,从头部之前插入节点
{
//先让pi指向旧的头节点
pi->next=head;
//再让head指向新的头节点
head=pi;
return head;
}
return head;
}
STU *insert_link(STU *head,STU tmp)//从链表尾部插入
{
//先申请待插入的节点(无论哪个插入方式,第一步都是这个)
STU *pi=(STU *)calloc(1,sizeof(STU));
if(pi==NULL)
{
perror("calloc"); //判断是否申请成功(同上,都需要用到)
return head;
}
//将tmp的值赋给*pi
*pi=tmp;
pi->next =NULL;
//将节点插入到链表的尾部
if(head==NULL)//判断不存在
{
head=pi;
return head;
}
else//说明链表存在
{
//先寻找到链表的尾节点
STU *pb=head;
while(pb->next !=NULL)//如果不是尾节点
pb=pb->next; //让Pb指向下一个节点
//用尾节点pb 链接上需要插入的节点pi
pb->next =pi;
return head;
}
return head;
}
#endif
//插入函数
STU *insert_link(STU *head,STU tmp)//有序插入节点,以学号num,从小到大
{
//首先在堆区申请空间给待插入的节点pi
STU *pi=(STU *)calloc(1,sizeof(STU));
if(pi==NULL) //判断是否申请成功
{
perror("calloc");
return head;
}
//将tmp的内容 赋给 *pi
*pi=tmp;
pi->next=NULL;
//链表节点pi的插入
if(head==NULL)//链表不存在
{
head=pi;
return head;
}
else//链表存在
{
//先寻找插入点
STU *pb =head;
STU *pf =head;
while(pb->num < pi->num && pb->next !=NULL)
{
pb=pf;
pb=pb->next;
}
//插入点的判断
if(pb->num >= pi->num )//头部、中部插入
{
if(pb==head)//头部之前插入
{
pi->next =head;
head=pi;
return head;
}
else //中部插入
{
pf->next =pi;
pi->next =pb;
return head;
}
}
else//尾部插入
{
pb->next =pi;
return head;
}
}
return head;
}
//遍历函数
void print_link(STU * head)
{
if(head == NULL)
{
printf("link not find !!!!!!n");
return;
}
else
{
STU *pb=head;
while(pb!=NULL)
{
printf("学号:%d 姓名:%s 成绩:%d n",pb->num,pb->name,pb->score);
//让pb指向下一个节点
pb=pb->next;
}
}
return;
}
//寻找函数
STU *search_link(STU *head,char *name)
{
//先判断链表是否存在
if(head==NULL)
{
printf("link not find!!!n");
return NULL;
}
else//代表链表存在
{
STU *pb=head;
//进行逐个将节点中的name和name进行比较,如果不相等的话,pb=pb->next
while(strcmp(pb->name,name)!=0 && pb->next!=NULL)
pb=pb->next;
//然后判断是否找到
if(strcmp(pb->name,name)==0)//表示找到
return pb;
else//表示没找到
return NULL;
}
return NULL;
}
//删除函数
STU *delete_link(STU *head,char *name)
{
//先判断链表是否存在
if(head==NULL)//表示链表不存在
{
printf("link not find !!!n");
return head;
}
else//表示链表存在,进行后续操作
{
//先寻找删除点
STU *pb=head;
STU *pf=head;
while(strcmp(pb->name,name)!=0 && pb->next!=NULL)
{
pf=pb;
pb=pb->next;
}
//找到删除点
if(strcmp(pb->name,name)==0)
{
//判断删除点的位置
if(pb==head)//表示删除的是头节点
{
head=pb->next;
free(pb);//找到删除点后,释放该节点
}
else//表示删除点在中部 或者尾部
{
pf->next=pb->next;
free(pb);
}
printf("已经成功删除%s的相关信息n",name);
return head;
}
else//表示没有找到删除点
{
printf("本链表中没有%s的相关信n",name);
}
}
return head;
}
//释放函数
STU *free_link(STU *head)
{
//先判断链表是否存在
if(head==NULL)
{
printf("link not find!!!n");
return head;
}
else//代表链表是存在的
{
STU *pb=head;
//要进行逐个节点的释放
while(pb!=NULL)
{
//head保存下一个节点的位置
head=pb->next;
//释放pb所指向的节点
free(pb);
//过后再让pb指向head
pb=head;
}
printf("本链表已经删除完毕!n");
return head;
}
return head;
}
//逆序函数
STU * reverse_link(STU * head)
{
//判断链表是否存在
if(head==NULL)
{
printf("link not find!!!n");
return head;
}
else//表示存在
{
STU *pb;
STU *pr;
//pb保存head->next(原因是head->next会置空)
pb=head->next;
//将head->next置空(将头节点变为尾节点)
head->next=NULL;
while(pb!=NULL)
{
//pr保存opb->next
pr=pb->next;
//保存 逆转方向的代码,可重复执行
head=pb;
pb=pr;
}
return head;
}
return head;
}
link .h
//防止头文件重复包含
#ifndef __LINK_H__
#define __LINK_H__
//链表节点类型 定义
typedef struct stu
{
//数据域
int num;
char name[32];
int score;
//指针域
struct stu *next;
}STU;
extern STU *insert_link(STU *head,STU tmp);
extern void print_link(STU * head);
extern STU *search_link(STU *head,char name);
extern STU *delete_link(STU *head,char *name);
extern STU *free_link(STU *head);
extern STU * reverse_link(STU * head);
#endif