主要实现代码
/****************************************************
@Title: 数据结构实验
@Name: <实验3-4> <循环队列>
@Object:
[实验目的] 循环队列的应用。
[试验任务] 实现舞会上男女舞伴的自动匹配。
舞会上先后到达男士和女士若干人,第一轮按照
到来的先后顺序,男女搭配一组,如果有剩下的,
等下一轮首先匹配。
打印出1-3轮的匹配情况。
[实验提示]
1. 在文件 sqqueue.h 中完成循环队列的实现
2. 根据两个队列元素个数,如何计算能匹配
多少对舞伴
3. 前一轮尚未轮到的,在下一轮中先匹配,
如何处理,要完成多轮匹配。
提示:匹配后继续加入队列中。
@Files:
app0304.cpp [*]
测试循环队列的主程序
sqqueue.h [*]
循环队列的实现
dance.txt [*]
舞伴数据文件
@Usage:
请查看"TO-DO列表",根据要求完成代码
@Copyright: BTC 2004, Zhuang Bo
@Author: Zhuang Bo
@Date: 2004
@Description:
*****************************************************/
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct Person {
char name[20]; //名字
char sex; //男'M';女'F'
};
#define ElemType Person /* 队列中数据元素的类型 */
#include "sqqueue.h"
////////////////////////////////////////////
//主程序
void du();
void pipei();
SqQueue maleDancers, femaleDancers;
void main()
{
InitQueue(maleDancers);
InitQueue(femaleDancers);
//用两个队列存放男士和女士
//从文件dance.txt中读取数据
//匹配舞伴
//计算并打印出1-3轮的匹配结果
for(int round=0; round<3; round++) {
/* TODO (#1#): 计算并打印第round轮匹配结果 */
du();
pipei();
//------------------------------------------
}
system("pause"); //暂停
}
void du(){
FILE *fin=0;
if((fin=fopen("dance.txt","r"))==0) {
printf("错误: 不能打开文件 dance.txt\n");
exit(1);
}
while(!feof(fin)) {
//读出一条记录
Person p;
p.sex = fgetc(fin);
fgets(p.name, 20, fin);
//printf("%c",p.sex);
/* TODO (#1#): 根据性别将 p 加入对应的队列 */
if(p.sex=='F'){
EnQueue(femaleDancers, p);
}
else{
EnQueue(maleDancers, p);
}
//------------------------------------------
}
}
void pipei(){
Person p1,p2;
int npair; //一轮中匹配舞伴数(对)
/* TODO (#2#): 计算能够匹配多少对舞伴 */
for(npair=0;(!QueueEmpty(femaleDancers))&&(!QueueEmpty(maleDancers));npair++){
GetHead(femaleDancers, p1);
GetHead(maleDancers, p2);
printf("匹配成功,男:%s 女:%s\n",p2.name,p1.name);
DeQueue(femaleDancers, p1);
DeQueue(maleDancers, p2);
}
printf("第一匹配数%d\n",npair);
printf("匹配结束");
// npair = -------------------------------------
}
////////////////////////////////////////////
//函数的定义
/*
Name: 循环队列
Copyright: BTC 2004
Author: Zhuang Bo
Date: 2004
Description:
[Include]
ds.h
[Constants]
MAXQSIZE
[Types]
ElemType
SqQueue
[Functions]
InitQueue(&Q)
DestroyQueue(&Q)
ClearQueue(&Q)
QueueEmpty(Q)
QueueLength(Q)
GetHead(Q,&e)
EnQueue(&Q,e)
DeQueue(&Q,&e)
[For Debug]
PrintElem(ElemType e)
QueueView(Q)
*/
#ifndef SQQUEUE_H_INCLUDED
#define SQQUEUE_H_INCLUDED /* 防止重复包含 */
//////////////////////////////////////////
//包含头文件
#include <stdlib.h>
#include "ds.h" // OK, Status 等定义
//数据元素的类型(缺省使用int型)
#ifndef ElemType
#define ElemType int
#define USE_DEFAULT_ELEMTYPE /* 使用缺省类型的标志 */
#endif //ElemType
//////////////////////////////////////////
//循环队列的存储结构
#define MAXQSIZE 64 /* 循环队列的最大容量 */
typedef struct {
/* TODO (#1#): 这里完成循环队列的类型定义 */
ElemType *base;
int front;
int rear;
//....................................
} SqQueue;
//////////////////////////////////////////
//循环队列的基本操作
//构造一个空队列Q
Status InitQueue(SqQueue &Q)
{
/* TODO (#2#): 构造空队列 */
Q.base=(ElemType*)malloc(MAXQSIZE*sizeof(ElemType));
if(!Q.base){
exit(0);
}
Q.front=Q.rear=0;
return OK; //TODO: 替换这行代码,以下同
//....................................
}
//销毁队列Q
// 前提:队列Q已存在
Status DestroyQueue(SqQueue &Q)
{
/* TODO (#3#): 销毁队列 */
if(Q.base){
free(Q.base);
return OK;
}
else
return ERROR;
//....................................
}
//将队列Q清为空队列
// 前提:队列Q已存在
Status ClearQueue(SqQueue &Q)
{
/* TODO (#4#): 清空队列 */
if(Q.base){
Q.front=Q.rear;
return OK;
}
else
return ERROR;
//....................................
}
//若队列Q为空,则返回TRUE,否则FALSE
// 前提:队列Q已存在
Status QueueEmpty(SqQueue Q)
{
/* TODO (#5#): 判断队列是否为空 */
if(Q.rear==Q.front){
return TRUE;
}
return FALSE;
//....................................
}
//返回队列Q的元素个数,即队列长度
// 前提:队列Q已存在
int QueueLength(SqQueue Q)
{
/* TODO (#6#): 返回队列长度 */
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
//....................................
}
//取队列Q头元素用e返回
// 前提:队列Q存在且非空
Status GetHead(SqQueue Q, ElemType &e)
{
/* TODO (#7#): 取队头元素存入e */
if(Q.front==Q.rear){//队列为空
return ERROR;
}
e=Q.base[Q.front];
return OK;//返回操作状态(成功:OK,失败:ERROR)
//....................................
}
//插入元素e作为队列Q的新的队尾元素
// 前提:队列Q存在且未满
Status EnQueue(SqQueue &Q, ElemType e)
{
/* TODO (#8#): 元素e入队列 */
if((Q.rear+1)%MAXQSIZE==Q.front){
return ERROR;
}
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%MAXQSIZE;
return OK;//返回操作状态(成功:OK,失败:ERROR)
//....................................
}
//删除队列Q的队头元素,并用e返回
// 前提:队列Q存在且非空
Status DeQueue(SqQueue &Q, ElemType &e)
{
/* TODO (#9#): 出队列存入e */
if(Q.front==Q.rear){
return ERROR;
}
e=Q.base[Q.front];
Q.front=(Q.front+1)%MAXQSIZE;
return OK ;//返回操作状态(成功:OK,失败:ERROR)
//....................................
}
//////////////////////////////////////////
//TODO: 定义好 SqQueue 类型后使用 QueueView 函数
#include <stdio.h>
//查看队列状态(调试用)
void QueueView(SqQueue Q)
{
//extern void PrintElem(ElemType e);//打印数据用
int i=0;
if(Q.front<0||Q.front>=MAXQSIZE||Q.rear<0||Q.rear>=MAXQSIZE){
printf("队列未初始化\n");
return ;
}
printf("---Queue View---\n");
printf("front=%d , rear=%d\n", Q.front, Q.rear);
if(Q.rear>=Q.front) {
printf("..... ......\n");
for(i=Q.front; i<Q.rear; i++) {
printf("%5d\t", i);
printf("%d",Q.base[i]);
printf("\n");
}
if(i<MAXQSIZE) printf("..... ......\n");
} else {
for(i=0; i<Q.rear; i++) {
printf("%5d\t", i);
printf("%d",Q.base[i]);
printf("\n");
}
printf("..... ......\n");
for(i=Q.front; i<MAXQSIZE; i++) {
printf("%5d\t", i);
printf("%d",Q.base[i]);
printf("\n");
}
}
printf("--- view end ---\n");
}
//取消ElemType的默认定义,以免影响其它部分
#ifdef USE_DEFAULT_ELEMTYPE
#undef ElemType
#undef USE_EFAULT_ELEMTYPE
#endif
#endif //SQQUEUE_H_INCLUDED
/*
Name: 类C通用模块
Copyright: BTC 2004
Author: Zhuang Bo
Date: 2004
Description:
[Constants]
TRUE/FALSE/OK/ERROR/INFEASIBLE/OVERFLOW
[Types]
Status
[Functions]
max(a,b)
min(a,b)
read(char/int/float/double/char*)
write(char/int/float/double/char*)
*/
#ifndef _DS_H_
#define _DS_H_
// 函数结果状态代码
const int TRUE = 1;
const int FALSE = 0;
const int OK = 1;
const int ERROR = 0;
const int INFEASIBLE = -1;
const int OVERFLOW = -2;
// Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
//基本函数
#define max(a,b) (((a)<(b))?(b):(a))
#define min(a,b) (((a)<(b))?(a):(b))
#include <stdio.h>
//不用格式串的输入输出(目的是为了方便书写算法)
// 比如输入一个基本类型(char, int, float, double, char*)的
// 变量 x,可以直接用 read(x);输入,而打印则用 write(x);。
// 对于自定义类型,可以继续扩充。
inline void read(char& e) { e = getchar(); }
inline void read(int& e) { scanf("%d", &e); }
inline void read(float& e) { scanf("%f", &e); }
inline void read(double& e) { scanf("%lf", &e); }
inline void read(char *e) { gets(e); }
inline void write(char e) { printf("%c", e); }
inline void write(int e) { printf("%d", e); }
inline void write(float e) { printf("%f", e); }
inline void write(double e) { printf("%lf", e); }
inline void write(char *e) { printf("%s",e); }
#endif // _DS_H_