单链表的实际应用

  • Post author:
  • Post category:其他



首先问一个问题:算法是什么?


在我看来,算法就是一个解决问题的方法,当你的问题越复杂,你需要的算法就更复杂。需要更多更复杂的代码来实现。在下面的例子中就有算法的体现。

下面以一个例子来讲解单链表的应用级操作。其实在做具体项目时,跟这个例子也相似,你要明白实现这个功能要做哪些事情,这个是重点。当你明白之后再去写代码,这时就要选择好的语句来实现功能(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

欢迎一起交流。



版权声明:本文为qq_41960161原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。