功能: 1. 建立一个含有若干个整数的单链表存储结构;
2. 输出单链表各节点的值;
3. 查询第I个结点的值,并输出;
4. 在第I个结点之后插入一个值为X的结点。
5. 删除第I个结点。
要求: 利用指针、动态分配建立单链表。利用菜单可以循环完成各个操作。
进一步要求:能够实现单链表的逆序更好。
单链表的内容还不是很理解,但是基本的创建,排序,输出,插入等都能实现了,虽然有些功能也是看了很多博主的博客,看了书才写出来的,但对于自己来说也不错了,单链表的逆序是用的递归方法,在用什么头插法的时候,由于自己对链表的知识还不是很熟练,会出现头结点不能逆序的情况,看了几个博客之后,用递归的方法就能实现了。删除,一般是让删除第几个结点,而我写的是删除哪一个结点。
# include<stdio.h>
# include<stdlib.h>
# define LEN sizeof(stu)
typedef struct student
{
long num;
struct student *next;
}stu;
//创建链表
stu *creat()
{
int n=0;
stu *head;
stu *p1,*p2;
n=0;
p1=p2=(stu*)malloc(LEN);
printf("\n");
printf("输入学号为0时停止输入\n");
printf("输入学生信息\n");
printf("学号\n");
scanf("%ld",&p1->num);
head=NULL;
while(p1->num!=0)
{
n=n+1;
if(n==1) head=p1;
else p2->next=p1;
p2=p1;
p1=(stu*)malloc(LEN);
scanf("%ld",&p1->num);
}
p2->next=NULL;
return(head);
}
//输出链表
stu *output(stu *head)
{
stu *pt;
printf("学生信息如下\n");
pt=head;
printf("学号\n");
if(pt!=NULL)
while(pt!=NULL)
{
printf("%4ld\n",pt->num);
pt=pt->next;
}
printf("\n");
return(head);
}
//查找某个节点
stu *search(stu *head)
{
int n,flag=0;
long m;
stu *p;
p=head;
printf("输入你想要查询的学生学号:\n");
scanf("%ld",&m);
while(p!=NULL)
{
if(m==p->num)
{
printf("%3ld\n",p->num);
flag=1;
}
p=p->next;
}
if(!flag) printf(" 没有该学生\n");
return(head);
}
//删除某个节点
stu *dele(stu *head)
{
stu *p1,*p2;
long inum;
int find; //是否找到的标志
p1=head;
p2=p1;
printf("输入你想要删除的学生学号:");
scanf("%ld",&inum);
if(p1->num==inum) //链头是要删除的学号
{
p2=p1->next;
head=p1=p2;
find=1;
}
else //链头不是要删除的学号
p1=p1->next;
while(p1!=NULL)
{
if(p1->num==inum)
{
p2->next=p1->next;
find=1;
}
else
p2=p1;
p1=p1->next;
}
if(!find)
printf("没有该学生\n");
p1=head;
printf("学号\n");
while(p1!=NULL)
{
printf("%ld\n",p1->num);
p1=p1->next;
}
printf("\n");
return(head);
}
stu *sort(stu *head)
{
stu *pend,*begin;
long temp;
pend=NULL;
begin=head;
while((head)->next!=pend)
{
while(begin->next!=pend)
{
if(begin->num>begin->next->num)
{
temp=begin->num;
begin->num=begin->next->num;
begin->next->num=temp;
}
begin=begin->next;
}
pend=begin;
begin=head;
}
output(head);
return(head);
}
//在有序链表中插入
stu *insert(stu *head)
{
stu *p0,*p1,*p2,*stud,*Nhead;
p0=(stu *)malloc(LEN);
Nhead=sort(head);
p1=Nhead;
printf("插入的学号为:"); //p1指向第一个节点
scanf("%ld",&p0->num); //要插入的节点
if(head==NULL) //原来的表是空表
{
head=p0;p0->next=NULL;
}
else
{
while((p0->num>p1->num)&&(p1->next!=NULL)) //p1所指的不是表尾结点
{
p2=p1;
p1=p1->next;
}
if(p0->num<=p1->num) //插到第一个节点之前
{
if(head==p1) head=p0; //p1指向头指针 ,插到表头之前
else p2->next=p0; //插到表中间
p0->next=p1;
}
else //插到最后一个节点之后
{
p1->next=p0;
p0->next=NULL;
}
}
output(head);
}
//逆序(递归)
stu *reverse(stu *head)
{
if(head==NULL||head->next==NULL)
{
return(head);
}
stu *p=head->next;
stu *Newhead=reverse(p); //逆置后的
p->next=head;
head->next=NULL; //防止链表错乱
return(Newhead);
}
int main()
{
int m;
int n;
stu *head,*Newhead;
head=creat();
while(1)
{
printf(" ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆\n");
printf(" ◆◆◆◆◆学生联系方式管理系统◆◆◆◆◆◆◆\n");
printf(" ◆ 菜单 ◆\n");
printf(" ◆ 选项1:创建 ◆\n");
printf(" ◆ 选项2: 输出 ◆\n");
printf(" ◆ 选项3:查询 ◆\n");
printf(" ◆ 选项4:插入 ◆\n");
printf(" ◆ 选项5:删除 ◆\n");
printf(" ◆ 选项6:逆序 ◆\n");
printf(" ◆ 选项0:退出 ◆\n");
printf(" ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ ◆\n");
printf("\n");
printf(" 执行操作:");
scanf("%d",&m);
switch(m)
{
case 1: head=creat();break;
case 2: output(head);break;
case 3: search(head);break;
case 4: insert(head);break;
case 5: dele(head);break;
case 6: Newhead=reverse(head);
head=Newhead;
output(head);break;
case 0: exit(0);break;
default: printf(" 输入错误,请重新输入\n");break;
}
}
}