[问题描述]
设计一系统,实现医药公司定期对销售各药品的记录进行统计,可按药品的编号、单价、销售量或销售额做出排名。
[实现提示]
在本设计中,首先从数据文件中读出各药品的信息记录,存储在顺序表中。各药品的信息包括:药品编号、药名、药品单价、销出数量、销售额。药品编号共4位,采用字母和数字混合编号,如:A125,前一位为大写字母,后三位为数字,按药品编号进行排序时,可采用基数排序法。对各药品的单价、销售量或销售额进行排序时,可采用多种排序方法,如直接插入排序、冒泡排序、快速排序,直接选择排序等方法。在本设计中,对单价的排序采用冒泡排序法,对销售量的排序采用快速排序法,对销售额的排序采用堆排序法。
药品信息的元素类型定义:
typedef struct node
{ char num[4]; /*药品编号*/
char name[10]; /*药品名称*/
float price; /*药品单价*/
int count; /*销售数量*/
float sale; /*本药品销售额*/
}DataType;
存储药品信息的顺序表的定义:
typedef struct
{ DataType r[MaxSize];
int length;
}SequenList;
#include<cstdio>
#include<iostream>
#define MaxSize 10
#define OVERFLOW -2
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef struct node{
char num[5]; /*药品编号*/
char name[10]; /*药品名称*/
float price; /*药品单价*/
int count; /*销售数量*/
float sale; /*本药品销售额*/
}DataType;
//存储药品信息的顺序表的定义:
typedef struct{
DataType r[MaxSize];
int length;
}SequenList;
SequenList L;
/**初始化一个空表*/
void InitList(){
// L.r=new DataType[MaxSize];//为顺序表分配一个大小为MaxSize的空间
if(!L.r) exit(OVERFLOW);
L.length=0;//空表长度为0
}
/**打印药品信息*/
void PrintMes(){
printf("------------------------------------------------------------------------------\n");
printf("药品编号\t 药名\t\t 药品单价\t 销出数量\t 销售额\n");
for(int i=1;i<=L.length;i++){
printf("%s\t\t %s\t %.2f\t %d\t\t %.2f\n",L.r[i].num,L.r[i].name,
L.r[i].price,L.r[i].count,L.r[i].sale);
}
printf("------------------------------------------------------------------------------\n");
}
/**交换两个药品的信息*/
void Swap(int i,int j){
//临时变量
char num[6]; /*药品编号*/
char name[20]; /*药品名称*/
float price; /*药品单价*/
int count; /*销售数量*/
float sale; /*药品销售额*/
//交换编号,名字
strcpy(num,L.r[i].num);strcpy(L.r[i].num,L.r[j].num);strcpy(L.r[j].num,num);
strcpy(name,L.r[i].name);strcpy(L.r[i].name,L.r[j].name);strcpy(L.r[j].name,name);
//交换单价,数量,销售额
price=L.r[i].price;L.r[i].price=L.r[j].price;L.r[j].price=price;
count=L.r[i].count;L.r[i].count=L.r[j].count;L.r[j].count=count;
sale=L.r[i].sale;L.r[i].sale=L.r[j].sale;L.r[j].sale=sale;
}
/**从文件中读取药品信息并输出*/
void ScanMes(){
FILE *fp;
char num[6]; /*文件中编号*/
char name[20]; /*文件中名称*/
float price; /*文件中单价*/
int count; /*文件中数量*/
float sale; /*文件中销售额*/
if((fp=fopen("C:\\Users\\admin\\Documents\\DS\\sort\\in.txt","r"))==NULL){
printf("文件读取发生错误,无法进行读入!");
exit(0);
}
while(!feof(fp)){
fscanf(fp,"%s%s%f%d%f",num,name,&price,&count,&sale);
L.length++;//0号单元不使用
strcpy(L.r[L.length].num,num);
strcpy(L.r[L.length].name,name);
L.r[L.length].price=price;
L.r[L.length].count=count;
L.r[L.length].sale=sale;
if(L.length==MaxSize)
break;
}
printf("从数据文件中读取的药品信息为:\n");
PrintMes();
printf(">>任意键进入主界面");
system("pause");
system("cls");
}
/**按照药品编号排序(基数排序)(假排序qwq)*/
void Distribute(){
int a[MaxSize];//字母作为关键字-转化为(0-26)
int b[MaxSize];//后面的数字作为关键字
for(int i=1;i<=L.length;i++)
a[i]=L.r[i].num[0]-'A';
for(int i=1;i<=L.length;i++){
for(int j=i+1;j<=L.length;j++){
if(a[i]>a[j]){
swap(a[i],a[j]);
Swap(i,j);
}
}
}
for(int i=1;i<=L.length;i++)
b[i]=(L.r[i].num[1]-'0')*100+(L.r[i].num[2]-'0')*10+(L.r[i].num[2]-'0');
for(int i=1;i<=L.length;i++){
for(int j=i+1;j<=L.length;j++){
if(a[i]==a[j]&&b[i]>b[j]){
swap(b[i],b[j]);
Swap(i,j);
}
}
}
printf("按照药品编号排序(基数排序)后的结果为:\n");
PrintMes();
printf(">>Enter键返回组界面\n");
system("pause");
system("cls");
}
/**按照药品单价排序(冒泡排序)*/
void BubbleSort(){
for(int i=1;i<=L.length-1;i++){
for(int j=1;j<=L.length-i;j++)
if(L.r[j].price>L.r[j+1].price)
Swap(j,j+1);
}
printf("按照药品单价排序(冒泡排序)后的药品信息为:\n");
PrintMes();
printf(">>Enter键返回主界面");
system("pause");
system("cls");
}
/**进行一次排序,返回枢轴位置*/
int Partition(int left,int right){//对顺序表进行一次排序,返回枢轴位置
L.r[0]=L.r[left];//将枢轴信息放在0号位置
int pivotkey=L.r[left].count;//记录枢轴的销售量
while(left<right){
while(left<right&&L.r[right].count>=pivotkey) right--;//右移,直到小于枢轴的销售量
L.r[left]=L.r[right];//覆盖
while(left<right&&L.r[left].count<=pivotkey) left++;//左移,直到大于枢轴的销售量
L.r[right]=L.r[left];//覆盖
}
L.r[left]=L.r[0];
return left;
}
/**对顺序表进行排序*/
void QSort(int left,int right){
if(left<right){//长度大于1
int pivotloc=Partition(left,right);//记录返回的枢轴的位置
QSort(left,pivotloc-1); //左子表排序
QSort(pivotloc+1,right);//右子表排序
}
}
/**按照销售量排序(快速排序)*/
void QuickSort(){//对L进行快速排序
QSort(1,L.length);
printf("按照销售量排序(快速排序)后的结果为:\n");
PrintMes();
printf(">>Enter键返回主界面");
system("pause");
system("cls");
}
/**筛选法调整堆*/
void HeapAdjust(int s,int m){
//s根结点,m序列长度
L.r[0]=L.r[s];//保存根结点信息
for(int i=2*s;i<=m;i*=2){//沿着销售额较大的孩子结点向下筛选
if(i<m&&L.r[i].sale<L.r[i+1].sale) i++;
if(L.r[0].sale>=L.r[i].sale) break;//根结点的销售额大于两个孩子,0号位置的信息应该在s位置上
L.r[s]=L.r[i];s=i;//否则0号位的信息应该在i,更新根结点,继续找他的左右堆,知道找到叶子结点,一次调整完毕
}
L.r[s]=L.r[0];
}
/**建立大根堆*/
void CreatHeap(){
int n=L.length;
//所有大于n/2的位置上都是叶子结点,我们从叶子最后一个非叶子结点筛选
for(int i=n/2;i>0;i--){
HeapAdjust(i,n);//不断的调整堆
//PrintMes();
}
}
/**按照销售额排序(堆排序)*/
void HeapSort(){
CreatHeap();//把无序序列建成大根堆
//打印大根堆
//PrintMes();
for(int i=L.length;i>1;i--){
//1:堆顶元素的位置,i:未排序的最后一个
Swap(1,i);//将堆顶元素与没有排序(1-i)的的最后一个记录交换
HeapAdjust(1,i-1);//除了堆顶信息,剩下的继续调整为大根堆
}
printf("按照销售额排序(堆排序)后的结果为:\n");
PrintMes();
printf(">>Enter键返回主界面");
system("pause");
system("cls");
}
/**主菜单*/
void Menu(){
printf("-------------药店的药品销售统计系统-------------\n");
printf("1.按药品编号排序(基数排序)\n");
printf("2.按照药品单价排序(冒泡排序)\n");
printf("3.按照销售量排序(快速排序)\n");
printf("4.按照销售额排序(堆排序)\n");
printf("5.退出\n");
printf("------------------------------------------------\n");
printf(">>请输入您的选择:");
int chose;
scanf("%d",&chose);
switch(chose){
case 1: {
Distribute();
Menu();
}
case 2: {
BubbleSort();
Menu();
}
case 3: {
QuickSort();
Menu();
}
case 4: {
HeapSort();
Menu();
}
case 5: {
exit(0);
}
default: {
printf("您的输入有误,请进入主界面重新输入!\n");
printf(">>Enter键重新输入!\n");
system("pause");
system("cls");
Menu();
break;
}
}
}
int main(){
InitList();
ScanMes();
Menu();
return 0;
}