数据结构⼩⽩必看:图书管理系统(C语⾔链表实现)本⽂对⼩⽩⾮常友好,⽤最基础的代码写的,
认真看,只需15分钟,包你看了之后就知道要怎么交作业了,看不懂我
代码及注释见下:
可能稍微有点长,可以各取所需,建议先看前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是跳过头结点指向第⼀个有⽤的节点,  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语⾔\\图书管理系统\\", "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和SearchKin  }
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指向中间某处, {
QsortKind(pbegin, partion);
QsortKind(parnext, pend);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。