主要實現代碼
/****************************************************
@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_