很纳闷,上次发的fifteen竟然说包含不适内容,就是程序而已啊,莫名其妙。
这个就是公开课上链表的程序,稍微改了下,没用他的头文件,同时添加了注释。用codeblocks编译通过。
链表这个确实挺麻烦,并不是不能理解,而是具体实施该怎么做。
主要要理解头指针,头节点,第一个节点的含义和怎么表示。
下面是程序:
/*
一个数字链表。可以实现插入(按大小),查询,删除等功能
输入1,用于删除;
输入2,用于寻找;
输入3,用于插入;
输入4,用于遍历;
输入0,用于退出;
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//定义链表
typedef struct node
{
int n;//注意这个n,和平时int n区别开来
struct node *next;
}
node;
//头指针
node *first=NULL;
//声明函数
void delete(void);
void find(void);
void insert(void);
void traverse(void);
int getint(void);//代替头文件里的GetInt
//主函数
int
main()
{
int c;
do
{
printf("\n菜单\n\n"
"输入1,删除链表内数字\n"
"输入2,寻找链表内数字\n"
"输入3,插入数字到链表中(自动排序)\n"
"输入4,遍历链表\n"
"输入0,退出\n");
//输入
printf("请输入命令:");
c=getint();
//分类
switch(c)
{
case 1:delete();break;
case 2:find();break;
case 3:insert();break;
case 4:traverse();break;
default:printf("请按照提示输入命令\n");
}
}
while(c!=0);
//释放链表空间
node *ptr=first;
while(ptr!=NULL)
{
node *predptr=ptr;
ptr=ptr->next;
free(predptr);
}
return 0;
}
//getint
int getint(void)
{
int p,m,num;
while(1)
{
p=scanf("%d",&num);//scanf的返回值
while((m=getchar())!='\n'&&m!=EOF);//清除输入缓存
if(p==1)//返回值是数字则为1,否则是其它的
return num;
else
printf("请确保输入的是整数,再试一次:");
}
}
//delete
void
delete(void)
{
printf("输入要删除的数字:");
int n=getint();
node *ptr=first;//为什么不直接用first
node *predptr=NULL;//
while(ptr!=NULL)//最后节点
{
if(ptr->n==n)//链表里面有这个数,这2个n是不一样的,一个是定义链表里的数据,一个是输入的数字
{
//if(ptr->n==first->n)
if(ptr==first)//ptr是在变化的,因为是个while循环,判断ptr变化了没?用这个if(ptr->n==first->n)可以不?实验后可以
{
first=ptr->next;
free(ptr);
}
else//在中间或是尾部
{
predptr->next=ptr->next;//predptr在这里已经不是NULL了,第一个节点不相等就会执行下面的predptr=ptr;而相等就不会进行这一步
free(ptr);
}
break;
}
else
{
predptr=ptr;
ptr=ptr->next;//同上面联系起来看,predptr与ptr相隔1个节点
}
}
if(ptr==NULL)
printf("你所要删除的数字不存在\n");
traverse();
}
//insert
void
insert(void)
{
node *newptr=malloc(sizeof(node));
if(newptr==NULL)
{
printf("申请空间出错\n");
return;
}
printf("输入插入的数字:");
//插入的链表节点
newptr->n=getint();
newptr->next=NULL;
//如果链表是空的,则直接是newptr
if(first==NULL)
first=newptr;//为什么不是first->next=newptr?因为first单纯是个指针,就是第一个节点,first->next是第二个节点了。
//插入链表头部
else if(newptr->n<first->n)//first->n?第一个数据?
{
newptr->next=first;//为什么不是first->next?同上,相当于将newptr和first链接起来
first=newptr;
}
//插入中间或底部
else
{
node *predptr=first;//为什么不直接用first而是新建一个指针predptr呢?
while(1)
{
//是否重复
if(predptr->n==newptr->n)
{
free(newptr);
break;
}
//判断是否在尾部
else if(predptr->next==NULL)
{
predptr->next=newptr;
break;
}
//在中间的情况
else if(predptr->next->n>newptr->n)//predptr->next->n?
{
newptr->next=predptr->next;
predptr->next=newptr;
break;
}
//循环
predptr=predptr->next;
}
}
//遍历一下
traverse();
}
//find
void
find(void)
{
printf("输入要查找的数字:");
int n=getint();
node *ptr=first;
while(ptr!=NULL)
{
if(ptr->n==n)
{
printf("\n已找到%d\n",n);
usleep(100000);
break;
}
ptr=ptr->next;
}
if(ptr==NULL)
printf("你所要寻找的数字不存在\n");
}
//traverse
void
traverse(void)
{
printf("现在列表中存在的数据有:");
node *ptr=first;
while(ptr!=NULL)
{
printf("%d ",ptr->n);
ptr=ptr->next;
}
fflush(stdout);
usleep(100000);
printf("\n\n");
}