药店的药品销售统计系统(排序应用)
问题描述
设计一系统,实现医药公司定期对销售各药品的记录进行统计,可按药品的编号,单价,销售量或销售额做出排名。
实现提示
在本设计中,首先从数据文件中读出各药品的信息记录,存储在顺序表中。各药品的信息包括:药品编号、药名、药品单价、销出数量、销售额。药品编号共4位,采用字母和数字混合编号,如:A125,前一位为大写字母,后三位为数字,按药品编号进行排序时,可采用基数排序法。对各药品的单价、销售量或销售额进行排序时,可采用多种排序方法,如直接插入排序、冒泡排序、快速排序,直接选择排序等方法。在本设计中,对单价的排序采用冒泡排序法,对销售量的排序采用快速排序法,对销售额的排序采用堆排序法。
需求分析
- 对药品单价的排序采用——冒泡排序
- 对药品销售量排序采用——快速排序
- 对药品销售额的排序用——堆排序
- 对药品编号的排序采用——基数排序
品信息的元素类型定义
typedef struct node //药品信息的元素类型定义
{
char num[30]; //药品的编号
char name[50]; //药品名称
float price; //药品单价
int amount; //销售量
float sales; //销售额
}Elemtype; //定义结构体类型(名称)
存储药品信息的顺序表的定义
typedef struct //存储药品信息的顺序表的定义
{
Elemtype data[Maxsize]; //定义Elemtype类型的结构体数组,存储Maxsize种药的信息 (存放顺序表的元素)
int length; //药品种类数 (顺序表的实际长度)
}Sqlist; //顺序表类型 (名称)
算法设计
首先需要定义一个顺序表类型指针L,并为这个指针L的指向动态分配内存空间。接着从文件里读取数据并存储到指针L所指向的内存空间。然后再把这些刚刚读取到的原始数据进行排序处理并显示出来。
因为要用到文件操作,所以需要将文件和程序放到一起
文件内容(药品数据)
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Maxsize 100
typedef struct node //药品信息的元素类型定义
{
char num[30]; //药品的编号
char name[50]; //药品名称
float price; //药品单价
int amount; //销售量
float sales; //销售额
}Elemtype; //定义结构体类型(名称)
typedef struct //存储药品信息的顺序表的定义
{
Elemtype data[Maxsize]; //定义Elemtype类型的结构体数组,存储Maxsize种药的信息 (存放顺序表的元素)
int length; //药品种类数 (顺序表的实际长度)
}Sqlist; //顺序表类型 (名称)
/* 读取文件数据 */
void Read(Sqlist *L)
{
FILE *fp;
int i = 0;
if((fp = fopen("medicine.txt","r")) == NULL)
{
printf("Sorry! open file error!\n");
exit(0);
}
else
printf("文件读取成功\n");
while(fscanf(fp, "%s %s %f %d %f", &L->data[i].num, &L->data[i].name, &L->data[i].price, &L->data[i].amount, &L->data[i].sales) != EOF)
{
++i;
}
L->length = i;
fclose(fp);
}
/* 打印数据 */
void print(Sqlist *L)
{
int i;
printf("----------------------------------------------------------------------------------\n");
printf("药品种类数:%d\n",L->length);
printf("药品编号\t 药名\t\t 药品单价\t\t销售量\t\t销售额\n");
for(i = 0; i < L->length;i ++)
{
printf("%s\t\t %s\t\t %0.1f\t\t %d\t\t %0.1f\n",L->data[i].num, L->data[i].name, L->data[i].price, L->data[i].amount, L->data[i].sales);
}
printf("----------------------------------------------------------------------------------\n\n");
}
/* 基数排序算法 */
void Single(Sqlist *L,char cmp,int len,int index)
{
int i, x;
Sqlist T[len+1];
for(i = 0; i <= len; ++ i)
T[i].length = 0;
for(i = 1; i < L->length; ++ i)
{
x = L->data[i].num[index] - cmp;
T[x].data[++T[x].length] = L->data[i];
}
int k = 0, j;
for(i = 0; i <= len; ++ i)
for(j = 1; j <= T[i].length; ++ j)
L->data[++k] = T[i].data[j];
}
/* 基数排序实现 */
void Radixsort(Sqlist *L)
{
int i;
for(i = 3; i >= 1; -- i)
Single(L,'0',9,i); /*药品后三位为数字型字符*/
Single(L,'A',25,0); /*第一位为大写字符*/
printf("按照药品编号排序(基数排序)后的结果为:\n");
print(L);
printf(">>Enter键返回主界面\n");
system("pause");
system("cls");
}
/* 冒泡排序 */
void Bubblesort(Sqlist *L)
{
int i, j;
Elemtype tmp;
for(i = 0; i < L->length-1; i ++) //控制排序趟数 length为药品种类数,因为排序到length-1次最后一位数实际上已经是最大值
{
for(j = L->length-1; j > i; j --) //从最后一位往前排,此时i为需要排序的最前面一位
{
if(L->data[j].price < L->data[j - 1].price)
{
tmp = L->data[j]; //交换Elemtype类型的结构体
L->data[j]= L->data[j-1];
L->data[j-1]= tmp;
}
}
}
printf("按药品单价排序(冒泡排序)后如下:\n");
print(L);
printf(">>>Enter键返回主菜单\n");
system("pause");
system("cls"); //清屏操作
}
/* 快速排序 */
void Quicksort(Sqlist *L, int s, int t)
{
int i = s, j = t;
Elemtype tmp;
if(s < t)
{
tmp = L->data[s];
while(i != j)
{
while(j > i && L->data[j].amount >= tmp.amount)
j --;
L->data[i] = L->data[j];
while(i < j && L->data[i].amount <= tmp.amount)
i ++;
L->data[j]= L->data[i];
}
L->data[i] = tmp;
Quicksort(L, s, i-1);
Quicksort(L, i+1, t);
}
}
/* 筛选法调整堆*/
void Sift(Elemtype R[], int low, int high) //对L->data[low...high]进行筛选
{
int i = low, j = 2 * i; //L->data[j]是L->data[i]的左孩子
Elemtype tmp = R[i];
while(j <= high)
{
if(j < high && R[j].sales < R[j + 1].sales)
j ++; //若右孩子较大,把j指向右孩子
if(tmp.sales < R[j].sales)
{
R[i] = R[j]; //将L->data[j]调整到双亲结点位置上
i = j; //修改i和j的值,以便继续向下筛选
j = 2 * i;
}
else break; //已经是大根堆,筛选结束
}
R[i] = tmp; //被筛选的结点的值放入最终位置
}
/* 堆排序 */ /* 因为堆排序时数组的下标是从1开始,因此这里我们用重新定义的结构体数组 */
void Heapsort(Sqlist *L,Elemtype R[], int n)
{
int i;
Elemtype tmp;
for(i = n/2; i >= 1; i --) //n/2次循环建立初始堆
Sift(R, i, n);
for(i = n; i >= 2; i --) //进行n - 1 次循环,完成堆排序
{
tmp = R[1]; //R[1] 和R[i]交换
R[1] = R[i];
R[i] = tmp;
Sift(R, 1, i-1); //筛选
}
/* 打印排序完之后的数据信息 */
printf("按药品销售额排序(冒堆排序)后如下:\n");
printf("----------------------------------------------------------------------------------\n");
printf("药品种类数:%d\n",L->length);
printf("药品编号\t 药名\t\t 药品单价\t\t销售量\t\t销售额\n");
for(i = 1; i < L->length;i ++)
{
printf("%s\t\t %s\t\t %0.1f\t\t %d\t\t %0.1f\n",R[i].num, R[i].name, R[i].price, R[i].amount, R[i].sales);
}
printf("----------------------------------------------------------------------------------\n\n");
printf(">>>Enter键返回主菜单\n");
system("pause");
system("cls");
}
/* 显示主菜单 */
void Menu()
{
printf("\n");
printf("*--------------------药店的药品销售统计系统--------------------*\n");
printf("* 1.按药品编号排序(基数排序) *\n");
printf("* 2.按药品单价排序(冒泡排序) *\n");
printf("* 3.按药品销售量排序(快速排序) *\n");
printf("* 4.按药品销售额排序(堆排序) *\n");
printf("* 5.退出系统 *\n");
printf("*--------------------------------------------------------------*\n");
printf(">>>请输入您的选择:\n");
}
int main()
{
int a, i;
Sqlist *L; //定义指向顺序表类型的指针
Elemtype R[Maxsize]; //定义一个结构体数组
L = (Sqlist *)malloc(sizeof(Sqlist)); //给指针L指向的地址动态分配存储空间
Read(L);
print(L);
for(i = 0; i < L->length; i ++) //R[]用于存放堆排序时的各药品的数据信息
R[i + 1] = L->data[i];
while(1)
{
Menu();
scanf("%d",&a);
printf("\n");
switch(a) //多分支选择结构
{
case 1 : Radixsort(L); break;
case 2 : Bubblesort(L); break;
case 3 : Quicksort(L,0,L->length-1);
printf("按药品销售量排序(快速排序)后如下:\n");
print(L);
printf("Enter键返回主菜单\n");
system("pause");
system("cls");
break;
case 4 : Heapsort(L, R, L->length); break;
case 5 : exit(0); break;
default: {
printf("\n您的输入有误,请进入主界面重新输入\n");
printf(">>>Enter重新输入\n");
system("pause");
printf("\n");
system("cls"); //清屏操作
break;
}
}
}
return 0;
}
简单展示
来源:CSDN
作者:北冥有鱼_鲲
链接:https://blog.csdn.net/qq_45034206/article/details/104447249