可能稍微有点长,可以各取所需,建议先看前80行,或者直接看创建链表,查找和删除等模块
加油朋友,加油朋友,加油朋友,加油朋友
#include<stdio.h>
#include<stdlib.h>//包含动态内存分配malloch函数
#include<string.h>//包含字符串处理函数
typedef struct Book {//声明节点
int num;
char name[30];
int amount;
int kind;//种类0-5表示不同类别:专必专选、公必公选、大英小说
struct Book* next;//节点数据结构
} Book;
void menu(); //声明各个函数
Book* creat();
void print(Book*);
void insert(Book*);
void Delete(Book*);
void SearchName(Book*);
void DeleteKind(Book*);
void Modify(Book*);
void SearchKind(Book*);
void QsortKind(Book*, Book*);
Book* GetPartion(Book*, Book*);
void Swap(Book*, Book*);
Book* Gettail(Book*);
void QsortNum(Book*, Book*);
Book* GetPartion2(Book*, Book*);
void QsortAmount(Book*, Book*);
Book* GetPartion3(Book*, Book*);
int main() //主函数
{
menu();
return 0;
}
void menu() //菜单函数
{
int n, i = 1;
Book* head; //定义头尾指针
Book* tail;
double time;
while (i == 1)
{
printf("\n");
printf("|-----------------------------------------------------------------|\n");
printf("|欢迎使用李氏图书管理系统 |\n");
printf("|输入1创建链表并导入图书信息、输入2输出链表、输入3插入 |\n");
printf("|输入4删除、输入5查找、输入6按种类排序、输入7修改 |\n");
printf("|输入8按类别删除、输入9按类别查找、10按编号排序、11按数量排序 |\n");
printf("|-----------------------------------------------------------------|\n");
printf("请输入:");
scanf("%d", &n);
printf("\n");
switch (n)
{
case 1:head = creat(); break;
case 2:print(head); break;
case 3:insert(head); break;
case 4:Delete(head); break;
case 5:SearchName(head); break;
case 6:tail = Gettail(head); QsortKind(head->next, tail); printf("排序完成\n"); break;//排序函数传入链表头尾节点,head->next是跳过头结点指向第一个有用的节点,tail指向链表末尾最后一个节点
case 7:Modify(head);break;
case 8:DeleteKind(head); break;
case 9:SearchKind(head); break;
case 10:tail = Gettail(head); QsortNum(head->next, tail); printf("排序完成\n"); break;
case 11:tail = Gettail(head); QsortAmount(head->next, tail); printf("排序完成\n"); break;
default:printf("输入错误\n"); i = 0;
}
}
}
/*********************************************************************
先用creat函数创建链表并导入图书文件信息,然后返回指向所创建链表的指针,
就能根据该指针找到所创建的链表并执行各种操作;
这些各种操作的函数基本都是在顺序遍历链表的同时外加一个判断条件,
符合该条件就执行一组操作,否则就继续遍历,直到遍历完全
另,给字符数组赋初值可用strcpy函数
*********************************************************************/
Book* creat() //创建链表并导入图书信息的函数,返回指向所创建链表的指针
{
Book* p1, * p2; //h为头结点,p1用来开辟新节点,p2用来指向当前链表最后一个节点;用p2->next=p1建立连接关系
Book* head;
Book* h;
h = (Book*)malloc(sizeof(Book));
h->num = h->amount = h->kind = -1; //给头结点赋初值,并初始化h->next为空
strcpy(h->name, "null"); //用字符串复制函数给头结点的name数组赋初值,直接赋值的话会有错
h->next = NULL;
head = p2 = h; //head和p2指向头结点h
p1 = (Book*)malloc(sizeof(Book)); //开辟新单元,并使p1指向它
printf("链表创建成功\n");
FILE* fp;
fp = fopen("D:\\Grade2_a\\数据结构c语言\\图书管理系统\\Book.txt", "r");
if (fp == NULL)
printf("error\n");
while (1) //把文件信息逐个导入;fscanf函数的返回值是导入参数的个数,如果每行都导入了4个参数就是正确的,否则就说明全部信息已导入完成
{
if (fscanf(fp, "%d %s %d %d", &p1->num, p1->name, &p1->amount, &p1->kind) == 4)//注意字符数组不用取址符
{
p2->next = p1;
p2 = p1;
p1 = (Book*)malloc(sizeof(Book));
}
else
{
p2->next = NULL;
break;
}
}
fclose(fp);
printf("图书信息导入成功\n");
printf("\n");
return(head);
}
void print(Book* head) //打印链表的函数(参数是指向链表的指针);先使p指向头结点,如果p->next!=NULL,就把p的下一个节点打印出来
{
Book* p = head;
printf("输出的图书信息为:\n");
printf("\n");
printf("编号 书名 数量 种类\n"); //在打印前加这句话是用来说明接下来打印出的图书信息
while (p->next != NULL)
{
p = p->next;
printf("%-7d %-30s %-10d %-10d\n", p->num, p->name, p->amount, p->kind);//这格式控制和上面加的一行说明都是凭感觉搞的,print、SearchName和SearchKind函数都用到这两个输出语句
}
printf("\n");
}
void insert(Book* head) //插入到表尾的函数,用while(p->next!=NULL)这个循环条件遍历链表并找到链表最后一个节点
{
Book* p = head;
Book* r;
r = (Book*)malloc(sizeof(Book));
printf("请输入要插入的书籍信息(按编号、书名、数量、种类的顺序输入):\n");
scanf("%d %s %d %d", &r->num, r->name, &r->amount, &r->kind);
while (p->next != NULL)
{
p = p->next;
}
p->next = r; //插入到表尾的核心语句
r->next = NULL;
printf("已插入\n");
printf("\n");
}
void SearchName(Book*head) //按书名搜索的函数;用while (strcmp(p->name, name) != 0 && p->next != NULL)作为循环条件遍历链表查找书名
{
Book* p = head;
char name[30];
printf("请输入你想查找的书名:\n");
scanf("%s", name);
if (p->next == NULL) printf("链表为空,无法查询\n");//表空时直接打印链表为空无法查询
p = p->next;
while (strcmp(p->name, name) != 0 && p->next != NULL) //注意是p->nex!=NULL,不是p!=NULL
{
p = p->next;
} //退出循环有两种可能:一是在前面的节点就找到了;一是前面的节点都不是,已经遍历到链表的最后一个节点,这种情况要对最后一个节点再进行一次判断
if (strcmp(p->name, name) == 0)
{
printf("已为你查找,书籍信息如下:\n");
printf("\n");
printf("编号 书名 数量 种类\n");
printf("%-7d %-30s %-10d %-10d\n", p->num, p->name, p->amount, p->kind);
}
else printf("查无此书\n");
printf("\n");
}
void DeleteKind(Book* head) //按类别删除的函数;遍历每个节点,对每个节点都进行判断,如果是要删的就删掉,再判断下一个;不是的话就直接判断下一个
{
int kind;
Book* p1, * p2;
p1 = p2 = head;
printf("请输入你想删除的类别:");
scanf("%d", &kind);
if (p1->next == NULL) printf("链表为空,无法删除\n");
p1 = p1->next;
while (p1 != NULL)
{
if (p1->kind == kind)
{
p2->next = p1->next;
free(p1);
p1 = p2->next;
}
else
{
p2 = p1;
p1 = p1->next;
}
}
printf("已删除\n");
printf("\n");
}
void SearchKind(Book* head) //按类别查找的函数;遍历每个节点,对每个节点都进行判断,如果类别一样就打印出来再判断下一个;类别不一样就跳过,接着判断下一个
{
int kind;
Book* p = head;
printf("请输入你想查找的类别:");
scanf("%d", &kind);
if (p->next == NULL) printf("链表为空,无法查找\n");
p = p->next;
printf("已为你查找,书籍信息如下:\n");
printf("\n");
printf("编号 书名 数量 种类\n");
while (p != NULL)
{
if (p->kind == kind)
{
printf("%-7d %-30s %-10d %-10d\n", p->num, p->name, p->amount, p->kind);
p = p->next;
}
else p = p->next;
}
printf("\n");
}
void Delete(Book* head) //按编号删除的函数
{
Book* p1, * p2;
p1 = p2 = head;
int num;
printf("请输入你想删除的书本编号:");
scanf("%d", &num);
if (p1->next == NULL) printf("链表为空,无法删除\n");
p1 = p1->next;
while (p1 != NULL && p1->num != num) //这里有个细节,写p1!=NULL和写p1->next!=NULL,这两种情况后面的if语句不一样,需要自己画个链表流程判断该怎么写
{
p2 = p1;
p1 = p1->next;
}
if (p1 == NULL) printf("找不到你要删的图书编号\n");
else
{
p2->next = p1->next;
free(p1);
printf("已删除\n");
}
printf("\n");
}
void Modify(Book* head) //按编号修改的函数
{
Book* p = head;
int num;
printf("请输入你想修改的图书编号:");
scanf("%d", &num);
if (p->next == NULL) printf("链表为空,无法修改\n");
p = p->next;
while (p->next != NULL && p->num != num)
{
p = p->next;
}
if (p->num == num)
{
printf("请输入修改后的书籍信息(按编号、书名、数量、种类的顺序输入):\n");
scanf("%d %s %d %d", &p->num, p->name, &p->amount, &p->kind);
printf("已修改\n");
printf("\n");
}
else printf("找不到你要修改的图书编号\n");
printf("\n");
}
/*************************************************************
排序函数用快速排序的方法,分成值交换交换模块、找到支点模块和排序核心递归模块
**************************************************************/
Book* Gettail(Book* head)//得到链表尾指针的函数
{
Book* p = head;
while (p->next != NULL)
p = p->next;
return p;//返回链表尾指针
}
void Swap(Book* p1, Book* p2)//两个指针所指向的值的值交换函数
{
Book* tmp;
tmp = (Book*)malloc(sizeof(Book));
tmp->next = NULL;
tmp->num = p1->num;
strcpy(tmp->name, p1->name);
tmp->amount = p1->amount;
tmp->kind = p1->kind;
p1->num = p2->num;
strcpy(p1->name, p2->name);
p1->amount = p2->amount;
p1->kind = p2->kind;
p2->num = tmp->num;
strcpy(p2->name, tmp->name);
p2->amount = tmp->amount;
p2->kind = tmp->kind;
free(tmp);
}
Book* GetPartion(Book* pbegin, Book* pend)//找到支点的函数
{
int kind = pbegin->kind;
Book* p1 = pbegin;
Book* p2 = p1->next;
while(p2 != pend->next)//p2 != pend->next说明还未遍历到链表末尾,继续循环
{
if(p2->kind < kind) // 比较,交换链表值,这里是按种类排序所以就比较种类
{
p1 = p1->next;
Swap(p1, p2);
p2 = p2->next;
}
else
p2 = p2->next;
}
Swap(pbegin, p1);
return p1;
}
void QsortKind(Book* pbegin, Book* pend)//排序核心递归函数,一开始只需传入(head->next,tail)即可,执行一组操作(把链表值交换,没有改变指针的指向),不需要返回值
{
Book* partion;
Book* parnext;
partion = GetPartion(pbegin, pend);//调用函数找partion
parnext = partion->next;
if (partion != pbegin && partion != pend)//下面分三种情况,GetPartion函数结束时,返回的指针p1的位置分为3种:p1指向pbegin;p1指向pend;p1指向中间某处,这里是指向中间的情况,这时p1两边都要继续排序
{
QsortKind(pbegin, partion);
QsortKind(parnext, pend);
}
else if (partion != pbegin && partion == pend)//这时p1指针已经移到pend处,说明这次的p2一直小于pbegin,导致p1一直往后移;这时只需排p1前面的
QsortKind(pbegin, partion);
else if (partion == pbegin && parnext != pend)//这时p1指针还在初始pbegin的位置,说明这次的p2一直>=pbegin,导致p1一直没动;这时只需排p1后面的
QsortKind(parnext, pend);
}
void QsortNum(Book* pbegin, Book* pend)
{
Book* partion;
Book* parnext;
partion = GetPartion2(pbegin, pend);
parnext = partion->next;
if (partion != pbegin && partion != pend)
{
QsortNum(pbegin, partion);
QsortNum(parnext, pend);
}
else if (partion != pbegin && partion == pend)
QsortNum(pbegin, partion);
else if (partion == pbegin && partion != pend)
QsortNum(parnext, pend);
}
Book* GetPartion2(Book* pbegin, Book* pend)
{
int num = pbegin->num;
Book* p1 = pbegin;
Book* p2 = p1->next;
while (p2 != pend->next)
{
if (p2->num < num)
{
p1 = p1->next;
Swap(p1, p2);
p2 = p2->next;
}
else
p2 = p2->next;
}
Swap(pbegin, p1);
return p1;
}
void QsortAmount(Book* pbegin, Book*pend)
{
Book* partion, * parnext;
partion = GetPartion3(pbegin, pend);
parnext = partion->next;
if (partion != pbegin && partion != pend)
{
QsortAmount(pbegin, partion);
QsortAmount(parnext, pend);
}
else if (partion != pbegin && partion == pend)
QsortAmount(pbegin, partion);
else if (partion == pbegin && partion != pend)
QsortAmount(parnext, pend);
}
Book* GetPartion3(Book*pbegin, Book*pend)
{
int amount = pbegin->amount;
Book* p1 = pbegin;
Book* p2 = p1->next;
while (p2 != pend->next)
{
if (p2->amount >= amount)
p2 = p2->next;
else
{
p1 = p1->next;
Swap(p1, p2);
p2 = p2->next;
}
}
Swap(p1, pbegin);
return p1;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/73274.html