首先问一个问题:算法是什么?
在我看来,算法就是一个解决问题的方法,当你的问题越复杂,你需要的算法就更复杂。需要更多更复杂的代码来实现。在下面的例子中就有算法的体现。
下面以一个例子来讲解单链表的应用级操作。其实在做具体项目时,跟这个例子也相似,你要明白实现这个功能要做哪些事情,这个是重点。当你明白之后再去写代码,这时就要选择好的语句来实现功能(if?while?switch?…),最后调试,查看自己写的程序有没有问题,在产品开发时也是如此。
如下所述:
设有一个emp.dat,每个职工记录包含职工编号(no),姓名(name),部门号(depno)和工资数(salary)信息。
设计一个程序完成以下功能
1、从emp.dat文件中读出职工记录,并建立一个带头结点的单链表L。
2、输入一个职工记录。
3、显示所有职工记录。
4、按编号no对所有职工记录进行递增排序。
5、按部门编号(depno)对所有职工记录进行递增排序。
6、按工资数salary对所有职工记录进行递增排序。
7、删除指定职工号的职工记录。
8、删除职工文件中的全部记录。
9、将单链表L中的所有职工记录存储到职工文件emp.dat中。
看到这个例子的时候先构思,怎么将这些内容跟链表结合起来,你的节点怎么定义,节点里的数据域怎么定义,都需要先思考。在实现的8点操作里,其实中心思想还是链表的增删改查,你需要很熟悉单链表的基本操作算法。
下面慢慢分析:
为了读取数据更直观,你需要
定义一个数据结构体
typedef struct
{
int no;
char name[10];
int depno;
float salary;
}EmpType;
再
定义一个节点类型
,类型里只有一个结构体数据。
typedef struct node
{
EmpType data;
struct node * next;
}EmpList;
变量定义这一块就完成了,下面介绍链表的实际操作
删除职工文件中全部记录
void DelAll(EmpList *&L)
{
FILE *fp;
if ((fp=fopen("emp.dat","wb"))==NULL) //重写清空emp.dat文件
{
printf(" 提示:不能打开职工文件\n");
return;
}
fclose(fp);
DestroyEmp(L); //释放职工单链表L
L=(EmpList *)malloc(sizeof(EmpList));
L->next=NULL; //建立一个空的职工单链表L
printf(" 提示:职工数据清除完毕\n");
}
释放职工单链表L
void DestroyEmp(EmpList *&L)
{
EmpList *pre=L,*p=pre->next;
while (p!=NULL)
{
free(pre);
pre=p;
p=p->next;
}
free(pre);
}
读emp.dat文件建立职工单键表L
void ReadFile(EmpList *&L)
{
FILE *fp;
EmpType emp;
EmpList *p,*r;
int n=0;
L=(EmpList *)malloc(sizeof(EmpList)); //建立头结点
r=L;
if ((fp=fopen("emp.dat","rb"))==NULL) //不存在emp.dat文件
{
if ((fp=fopen("emp.dat","wb"))==NULL)
printf(" 提示:不能创建emp.dat文件\n");
}
else //若存在emp.dat文件
{
while (fread(&emp,sizeof(EmpType),1,fp)==1)
{ //采用尾插法建立单链表L
p=(EmpList *)malloc(sizeof(EmpList));
p->data=emp;
r->next=p;
r=p;
n++;
}
}
r->next=NULL;
printf(" 提示:职工单键表L建立完毕,有%d个记录\n",n);
fclose(fp);
}
添加一个职工记录
void InputEmp(EmpList *&L)
{
EmpType p;
EmpList *s;
printf(" >>输入职工号(-1返回):");
scanf("%d",&p.no);
if (p.no==-1) return;
printf(" >>输入姓名 部门号 工资:");
scanf("%s%d%f",&p.name,&p.depno,&p.salary);
s=(EmpList *)malloc(sizeof(EmpList));
s->data=p;
s->next=L->next; //采用头插法插入结点s
L->next=s;
printf(" 提示:添加成功\n");
}
删除一个职工记录
void DelEmp(EmpList *&L)
{
EmpList *pre=L,*p=L->next;
int no;
printf(" >>输入职工号(-1返回):");
scanf("%d",&no);
if (no==-1) return;
while (p!=NULL && p->data.no!=no)
{
pre=p;
p=p->next;
}
if (p==NULL)
printf(" 提示:指定的职工记录不存在\n");
else
{
pre->next=p->next;
free(p);
printf(" 提示:删除成功\n");
}
}
采用直接插入法单链表L按salary递增有序排序
void Sortsalary(EmpList *&L)
{
EmpList *p,*pre,*q;
p=L->next->next;
if (p!=NULL)
{
L->next->next=NULL;
while (p!=NULL)
{
q=p->next;
pre=L;
while (pre->next!=NULL && pre->next->data.salary<p->data.salary)
pre=pre->next;
p->next=pre->next;
pre->next=p;
p=q;
}
}
printf(" 提示:按salary递增排序完毕\n");
}
输出所有职工记录
void DispEmp(EmpList *L)
{
EmpList *p=L->next;
if (p==NULL)
printf(" 提示:没有任何职工记录\n");
else
{
printf(" 职工号 姓名 部门号 工资\n");
printf(" ----------------------------------\n");
while (p!=NULL)
{
printf(" %3d%10s %-8d%7.2f\n",p->data.no,p->data.name,p->data.depno,p->data.salary);
p=p->next;
}
printf(" ----------------------------------\n");
}
}
最后就是
主函数
,主函数的写法比较经典,需要深入理解
int main()
{
EmpList *L;
int sel;
printf("由emp.dat文件建立职工单键表L\n");
ReadFile(L);
do
{
printf(">1:添加 2:显示 3:按职工号排序 4:按部门号排序 5:按工资数排序\n");
printf(">6:删除 9:全删 0:退出 请选择:");
scanf("%d",&sel);
switch(sel)
{
case 9:
DelAll(L);
break;
case 1:
InputEmp(L);
break;
case 2:
DispEmp(L);
break;
case 3:
Sortno(L);
break;
case 4:
Sortdepno(L);
break;
case 5:
Sortsalary(L);
break;
case 6:
DelEmp(L);
break;
}
} while (sel!=0);
SaveFile(L);
return 1;
}
大致程序就是这样写,实现了对应的功能。
下面是完整的工程链接:
链接:https://pan.baidu.com/s/1VHVtjDS12WwLajzbqg5KTA
提取码:lyqd
欢迎一起交流。