使用快排和双链表的实验室管理系统
能够实现以下操作:添加,删除,查询人员信息,更新人员打卡情况,打印人员信息时的排序是按照打卡时长由大到小进行排序,如果打卡时长相同则按照学号先后排序。不多说,直接上码,注释详细到抓只猪来都能看懂
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//人员信息结构体
typedef struct STU {
unsigned long long id; //学号
char name[20]; //姓名
char temp0[2]; //解决莫名其妙的数组越界问题
char major[20]; //专业
float time; //打卡时间
}STU;
//链表节点
typedef struct LNode {
struct LNode* prior; //前节点
STU data; //数据域
struct LNode* next; //后节点
}LNode, * LinkList;
char printMenu();//打印主菜单
char printSub();//打印查询菜单
void addStuInfo(head);//输入人员信息
void insert(head, e);//插入人员信息
void outPutInfo(head);//输出人员信息
void reNewTime(head);//更新人员打卡时长
void deleteThem(head);//删除人员信息
void research_1(head, e);//根据学号查询
void research_2(head, e);//根据姓名查询
void research_3(head, e);//根据专业查询
void research_4(head, e);//根据打卡时长查询
LNode * LastPtr(head);//尾地址查询
void toSort(LNode * head, LinkList low, LinkList high);//快排
LNode * partion(LNode * head, LinkList low, LinkList high);//快排求中轴
void quicksort(head);//快排完成后对相同时长的信息再排序
void exchange(low,high);//我就纳闷了,为什么不允许我直接交换data???
void reply();//任意键返回(因为用了太多的清屏,不加个步骤就会把要显示的东西瞬间略过.....
STU e;
int menuID;//菜单栏选项,同样要求全局变量
int stuCount = 0;//人数,因为函数写太多了所以只能写成全局变量
int main()
{
LNode* head;
head = (LinkList)malloc(sizeof(LNode));
head->next = NULL;
head->prior = NULL;
while (1) {
menuID = printMenu();
switch (menuID) {
case '1': addStuInfo(head); break;
case '2': insert(head, e); break;
case '3': deleteThem(head, e); break;
case '5': outPutInfo(head); break;
case '6': reNewTime(head); break;
case '0': exit(EXIT_SUCCESS); break;
case '4':
while (1) {
menuID = printSub();
switch (menuID) {
case '1': research_1(head, e); break;
case '2': research_2(head, e); break;
case '3': research_3(head, e); break;
case '4': research_4(head, e); break;
}
if (menuID == '0') break;
}
}
}
return 0;
}
//打印主菜单
char printMenu() {
char menuID;
system("cls");//清屏
printf("*****欢迎使用实验室人员信息管理系统(当前共已录入%02d名人员信息)*****\n", stuCount);
printf("* *\n");
printf("* --------------------------------- *\n");
printf("* | GOD CALLS ME GOD | *\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");
fflush(stdin);//清空缓冲区以避免读取到其他东西
menuID = getchar();
return menuID;
}
//打印查询菜单
char printSub() {
char menuID;
system("cls");//清屏
printf("****************查询人员信息(当前共有%02d名人员)*****************\n", stuCount);
printf("* *\n");
printf("* (1)根据学号查询 *\n");
printf("* (2)根据姓名查询 *\n");
printf("* (3)根据专业查询 *\n");
printf("* (4)根据打卡时长查询 *\n");
printf("* (0)返回主菜单 *\n");
printf("* *\n");
printf("*******************************************************************\n");
fflush(stdin);//清空缓冲区以避免读取到其他东西
menuID = getchar();
return menuID;
}
//添加人员信息
void addStuInfo(LNode* head) {
LinkList p, r; //p指向新结点;r指向当前链表的尾结点
int i, n; //n表示人员数目
r = head;
printf("请输入人数:");
scanf("%d", &n);
stuCount = n;
printf("请输入下列信息:\n");
for (i = 1; i <= n; i++)
{
p = (LinkList)malloc(sizeof(LNode));
p->next = NULL;
printf("学号:\n");
scanf("%llu", &p->data.id);
printf("姓名:");
scanf("%s", p->data.name);
printf("专业:");
scanf("%s", p->data.major);
printf("打卡时长(小时):");
scanf("%f", &p->data.time);
p->prior = r;
r->next = p;
r = r->next;
printf("-----------------------------------------\n");
}
printf("********************************************************\n");
}
//人员信息插入(尾部插入)
void insert(LNode* head, STU e)
{
LinkList p, r;
r = head;
printf("请输入插入学生的信息:\n");
printf("学号:\n");
scanf("%llu", &e.id);
printf("姓名:\n");
scanf("%s", e.name);
printf("专业:\n");
scanf("%s", e.major);
printf("打卡时长:\n");
scanf("%f", &e.time);
while (r->next != NULL)
{
r = r->next;
}
p = (LinkList)malloc(sizeof(LNode));
p->data = e;
p->next = NULL;
p->prior = r;
r->next = p;
printf("插入成功!\n");
stuCount++;
reply();
}
//输出人员信息
void outPutInfo(LNode* head)
{
LinkList p,low,high;
p = head;
if(head->next==NULL){
printf("尚未录入任何人!");
reply();
return;
}
low=head->next;
high=LastPtr(head);
toSort(head,low,high);
quicksort(head);
system("cls");
printf("开始输出人员信息:\n\n");
printf("学号\t\t姓名\t\t专业\t\t打卡时长\n");
while (high->prior != NULL)
{
printf("%llu\t%s\t\t%s\t\t%.2f\t\n", high->data.id, high->data.name, high->data.major, high->data.time);
high = high->prior;
}
reply();
}
//更新人员打卡时长
void reNewTime(LNode* head)
{
LinkList r;
r = head;
while (r->next != NULL) {
r = r->next;
printf("原来%s的打卡时长为%.2f小时\n请输入新的打卡时长:", r->data.name, r->data.time);
scanf("%f", &r->data.time);
printf("\n输入成功!,现在%s的打卡时间为%.2f小时!\n", r->data.name, r->data.time);
}
printf("全部人员的打卡情况已经更新完毕!\n");
reply();
}
//人员信息删除
void deleteThem(LNode* head)
{
LinkList temp, r;
int i;
r = head;
printf("请输入你要删除的人员学号:\n");
scanf("%d", &i);
while (r->next != NULL && r->data.id != i)
r = r->next;
if (r->data.id != i)
{
printf("删除失败!学号不存在!\n");
return;
}
if (r->next == NULL) {
r = r->prior;
r->next = NULL;
printf("删除成功!\n");
stuCount--;
reply();
}
else {
temp = r;
r = r->prior;
r->next = temp->next;
temp = temp->next;
temp->prior = r;
printf("删除成功!\n");
stuCount--;
reply();
}
}
//人员信息查询
void research_1(LNode* head, STU e)
{
LinkList p;
p = head;
printf("请输入查找的学号:\n");
scanf("%llu", &e.id);
while ((p->next != NULL) && e.id != p->data.id)
{
p = p->next;
}
if (e.id == p->data.id)
printf("学号 %llu\t 姓名 %s\t 专业 %s\t 打卡时长 %.2f\n", p->data.id, p->data.name, p->data.major, p->data.time);
else
printf("尚未录入该人员信息!");
reply();
}
void research_2(LNode* head, STU e)
{
int a=0;
LinkList p;
p = head;
printf("请输入查找的姓名:\n");
scanf("%s", e.name);
loop1:while ((p->next != NULL) && strcmp(e.name, p->data.name) != 0)
{
p = p->next;
}
if (strcmp(e.name, p->data.name) == 0){
printf("学号 %llu\t 姓名 %s\t 专业 %s\t 打卡时长 %.2f\n", p->data.id, p->data.name, p->data.major, p->data.time);
a++:}
if (p->next != NULL) {
p = p->next;//防止有重名人员信息未被显示
goto loop1;
}
if(i==0)
printf("尚未录入该人员信息!");
reply();
}
void research_3(LNode* head, STU e)
{ int a=0;
LinkList p;
p = head;
printf("请输入查找的专业:\n");
scanf("%s", e.major);
loop2:while ((p->next != NULL) && strcmp(e.major, p->data.major) != 0)
{
p = p->next;
}
if (strcmp(e.major, p->data.major) == 0){
printf("学号 %llu\t 姓名 %s\t 专业 %s\t 打卡时长 %.2f\n", p->data.id, p->data.name, p->data.major, p->data.time);
a++;}
if (p->next != NULL) {
p = p->next;//同一专业显示全部人员
goto loop2;
}
if(i==0)
printf("尚未录入该人员信息!");
reply();
}
void research_4(LNode* head, STU e)
{ int a=0;
LinkList p;
p = head;
printf("请输入查找的打卡时长:\n");
scanf("%f", &e.time);
loop3:while ((p->next != NULL) && e.time != p->data.time)
{
p = p->next;
}
if (e.time == p->data.time){
printf("学号 %llu\t 姓名 %s\t 专业 %s\t 打卡时长 %.2f\n", p->data.id, p->data.name, p->data.major, p->data.time);
a++;}
if (p->next != NULL) {
p = p->next;//防止有打卡时长相同的信息未被显示
goto loop3;
}
if(i==0)
printf("尚未录入该人员信息!");
reply();
}
//获取尾地址
LNode * LastPtr(LNode* head) {
LinkList p;
p = head;
while (p->next != NULL)
p = p->next;
return p;
}
//快排中轴寻找
LNode * partion(LNode * head, LinkList low, LinkList high)
{
float pivot = 0;
if ( !head )
{
printf("错误,头节点为空!/n");
exit(1);
}
if ( !head->next )
{
return head->next;//就一个元素
}
pivot = low->data.time;
while ( low != high )
{
//从后面往前换
while ( low != high && high->data.time >= pivot )
{
high = high->prior;
}
//交换high low
exchange(low,high);
//从前往后换
while ( low != high && low->data.time <= pivot )
{
low = low->next;
}
//交换high low
exchange(low,high);
}
return low;
}
//快排
void toSort(LNode * head, LinkList low, LinkList high)
{
LNode * temp = NULL;
temp = partion(head, low, high);
if ( low != temp )
{
toSort(head, low, temp->prior);
}
if ( high != temp )
{
toSort(head, temp->next, high);
}
}
void quicksort(LNode * head){
LinkList p,temp;
p=head->next;
if(p->next!=NULL)//防止只录入了一个人报错
temp=p->next;
else
return;
while(temp->next!=NULL){
if(p->data.time==temp->data.time){//因为打印时是倒序打印,所以这里也需要把学号小的放在后面
if(p->data.id<temp->data.id){
exchange(p,temp);
}
}
p=p->next;
temp=p->next;
}
return;
}
//数据交换,难道是因为不是同一结构体???
void exchange(LinkList low,LinkList high){
unsigned long long ex_id; char ex_name[20]; char ex_temp0[2]; char ex_major[20]; float ex_time;
ex_id=low->data.id;strcpy(ex_temp0,low->data.temp0);strcpy(ex_name,low->data.name);strcpy(ex_major,low->data.major);ex_time=low->data.time;
low->data.id=high->data.id;strcpy(low->data.temp0,high->data.temp0);strcpy(low->data.name,high->data.name);strcpy(low->data.major,high->data.major);low->data.time=high->data.time;
high->data.id=ex_id;strcpy(high->data.temp0,ex_temp0);strcpy(high->data.name,ex_name);strcpy(high->data.major,ex_major);high->data.time=ex_time;
}
void reply()
{
char a;
fflush(stdin);//清空缓冲区以避免读取到先前的回车
printf("任意键继续");
if (scanf("%c", &a) == 13)//回车键返回
return;
else
return;//一时间想不到其他任意键返回的写法
}