/**
* 职工信息的综合运算
* 目的:深入掌握单链表应用的算法设计
* @date:2018-01-14
* @author:xiezhi
*/
#include <stdio.h>
#include <malloc.h>
typedef struct employee
{
int no; //职工号
char name[10]; //姓名
int depno; //部门号
float salary; //薪水
}EmpType; //职工类型
typedef struct node
{
EmpType data; //存放职工信息
struct node *next; //指向下一个结点的指针
}EmpList; // 职工单链表结点类型
/*---------------------------释放职工单链表L----------------------------*/
static void destroy_employee(EmpList *&L)// 指针的引用
{
EmpList *pre = L; // pre指向单链表的头结点
EmpList *p = pre->next;// p指向单链表的第一个数据结点
while(p != NULL)
{
free(pre);
pre = p;
p = p->next;
}
free(pre);
}
/*---------------------------删除职工文件中的全部记录----------------------------*/
static void delete_all(EmpList *&L) // 指针的引用
{
FILE *fp = NULL;
// "wb" 只写打开或建立一个二进制文件,只允许写数据
// "rb" 只读打开一个二进制文件,只允许读数据
fp = fopen("emp.dat", "wb");
if(fp == NULL) // 重写清空emp.dat文件
{
printf(" 提示:不能打开职工文件\n");
return;
}
fclose(fp);
// 释放职工单链表
destroy_employee(L);
// 建立一个空的职工单链表L
L = (EmpList *)malloc(sizeof(EmpList));
L->next = NULL;
printf(" 提示:职工数据清除完毕\n");
}
/*---------------------------读emp.dat文件建立职工单链表L----------------------------*/
// 读取emp.dat文件中所有职工记录并建立带头结点的职工单链表L
static void read_file(EmpList *&L)
{
FILE *fp;
EmpType emp;
EmpList *p;
EmpList *r;
int n = 0;
// 建立头结点
L = (EmpList *)malloc(sizeof(EmpList));
r = L; // r指向新建立的头结点
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,分配内存空间
p->data = emp;
r->next = p;
r = p; // r指向新建的结点p
n++;
}
}
r->next = NULL;
printf("提示:职工单链表L建立完毕,有%d个记录\n", n);
fclose(fp);
}
/*---------------------------输出所有职工记录----------------------------*/
// 显示单链表L中的所有职工记录
static void display_employee(EmpList *L)
{
EmpList *p = L->next; // p指向链表中的第一个数据结点
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");
}
}
/*---------------------------添加一个职工记录----------------------------*/
// 向单链表L中添加一个职工记录
static void add_employee(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
s = (EmpList *)malloc(sizeof(EmpList));// 分配内存空间
s->data = p;
// 采用头插法插入结点s
s->next = L->next;
L->next = s;
printf(" 提示:添加成功\n");
}
/*---------------------------删除一个职工记录----------------------------*/
// 从单链表L中删除一个职工记录(根据职工编号删除职工记录)
static void delete_employee(EmpList *&L)
{
EmpList *pre = L; //pre指向单链表L的头结点
EmpList *p = L->next; //p指向单链表L的第一个数据结点
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
{
// 释放p结点,从单链表L中删除
pre->next = p->next;
free(p);
printf(" 提示:删除成功\n");
}
}
/*---------------------------采用直接插入法对单链表L按职工编号递增有序排列----------------------------*/
static void sort_no(EmpList *&L) //指针的引用
{
EmpList *p;
EmpList *pre;
EmpList *q;
p = L->next->next; // p指向单链表L中的第二个数据结点
if(p != NULL)
{
L->next->next = NULL;
while(p != NULL)
{
q = p->next;
pre = L;
while(pre->next != NULL && pre->next->data.no < p->data.no)
pre = pre->next;
p->next = pre->next;
pre->next = p;
p = q;
}
}
printf(" 提示:按no递增排序完毕\n");
}
/*---------------------------将职工单链表数据存入数据文件----------------------------*/
// 将职工单链表L中所有数据存入到职工文件emp.dat中
static void save_file(EmpList *L)
{
EmpList *p = L->next;
FILE *fp = NULL;
int n = 0;
fp = fopen("emp.dat", "wb");
if(fp == NULL)
{
printf(" 提示:不能创建文件emp.dat\n");
return;
}
while(p != NULL)
{
fwrite(&p->data, sizeof(EmpType), 1, fp);
p = p->next;
n++;
}
fclose(fp);
// 释放职工单链表L
destroy_employee(L);
if(n > 0)
{
printf(" 提示:%d个职工记录写入emp.dat文件\n", n);
}
else
{
printf(" 提示:没有任何职工记录写入emp.dat文件\n");
}
}
/*---------------------------采用直接插入法对单链表L按部门编号递增有序排列----------------------------*/
static void sort_depno(EmpList *&L) //指针的引用
{
EmpList *p;
EmpList *pre;
EmpList *q;
p = L->next->next; // p指向单链表L的第二个数据结点
if(p != NULL)
{
L->next->next = NULL;
while(p != NULL)
{
q = p->next;
pre = L;
while(pre->next != NULL && pre->next->data.depno < p->data.depno)
pre = pre->next;
p->next = pre->next;
pre->next = p;
p = q;
}
}
printf(" 提示:按depno递增排序完毕\n");
}
/*---------------------------采用直接插入法对单链表L按薪水递增有序排列----------------------------*/
static void sort_salary(EmpList *&L) //指针的引用
{
EmpList *p;
EmpList *pre;
EmpList *q;
p = L->next->next; // p指向单链表L的第二个数据结点
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");
}
int main(int argc, char *argv[])
{
EmpList *L;
int sel;
printf("由emp.dat文件建立职工单链表L\n");
read_file(L);
do
{
printf(">1:添加 2:显示 3:按职工号排序 4:按部门号排序 5:按薪水排序\n");
printf(">6:删除 9:全删 0:退出 请选择:");
scanf("%d", &sel);
switch(sel)
{
case 9:
delete_all(L);
break;
case 1:
add_employee(L);
break;
case 2:
display_employee(L);
break;
case 3:
sort_no(L);
break;
case 4:
sort_depno(L);
break;
case 5:
sort_salary(L);
break;
case 6:
delete_employee(L);
break;
}
}while(sel != 0);
save_file(L);
return 0;
}