6-1 jmu-ds-舞伴问题 (15 分)
假设在周末舞会上,男士和女士们分别进入舞厅,各自排成一队。跳舞开始,依次从男队和女队队头各出一人配成舞伴,若两队初始人数不同,则较长那一队未配对者等待下一轮舞曲。现要求写一算法模拟上述舞伴配对问题。 你需要用队列操作实现上述算法。请完成下面5个函数的操作。
函数接口定义:
int QueueLen(SqQueue Q);//队列长度
int EnQueue(SqQueue &Q, Person e);//加入队列
int QueueEmpty(SqQueue &Q);//队列是否为空
int DeQueue(SqQueue &Q, Person &e);//出队列
void DancePartner(Person dancer[], int num); //配对舞伴
Q:队列
e:参加舞会的人
dancer:全部舞者
num:参加舞会的人数
输入说明
先输入参加舞会人数,再分别输入参加舞会人的姓名和性别
输出说明
先输出配对的男女舞伴,若队伍有剩人,则输出剩下人性别及剩下人数目。
裁判测试程序样例:
#include
#define MAXQSIZE 100//队列可能达到的最大长度
#define OK 1
#define ERROR 0
#define OVERFLOW -2
using namespace std;
typedef struct {
char name[20]; //姓名
char sex; //性别,'F’表示女性,'M’表示男性
} Person;
//- - - - - 队列的顺序存储结构- - - - -
typedef struct {
Person data[MAXQSIZE];
int front; //头指针
int rear; //尾指针
} Queue;
typedef Queue SqQueue;
SqQueue Mdancers, Fdancers; //分别存放男士和女士入队者队列
int InitQueue(SqQueue &Q);
void DestroyQueue(SqQueue &q);
int QueueLen(SqQueue Q);//队列长度
int EnQueue(SqQueue &Q, Person e);//加入队列
int QueueEmpty(SqQueue &Q);//队列是否为空
int DeQueue(SqQueue &Q, Person &e);//出队列
void DancePartner(Person dancer[], int num); //配对舞伴
int main(){
int i;
int n;
Person dancer[MAXQSIZE];
cin>>n;
for(i=0;i
InitQueue(Mdancers); //男士队列初始化
InitQueue(Fdancers); //女士队列初始化
cout << “The dancing partners are:” << endl;
DancePartner(dancer, n);
if (!QueueEmpty(Fdancers)) {
cout << “F:”<
cout << “M:”<
DestroyQueue(Fdancers);
DestroyQueue(Mdancers);
return 0;
}
int InitQueue(SqQueue &Q) {//构造一个空队列Q
Q = new Queue; //为队列分配一个最大容量为MAXSIZE的数组空间
if (!Q->data)
exit( OVERFLOW); //存储分配失败
Q->front = Q->rear = 0; //头指针和尾指针置为零,队列为空
return OK;
}
void DestroyQueue(SqQueue &q)
{
delete q;
}
/
输入样例:
6
张1 F
林1 F
王2 M
李1 F
薛2 M
翁1 F
输出样例:
The dancing partners are:
张1 王2
林1 薛2
F:2
作者: linli
单位: 集美大学
时间限制: 400 ms
内存限制: 64 MB
代码如下
int QueueLen(SqQueue Q)//队列长度
{
return (Q->rear -Q->front);
}
int EnQueue(SqQueue &Q, Person e)//加入队列
{
Q->data[Q->rear]=e;
Q->rear = (Q->rear+1)%MAXQSIZE;
return true;
}
int QueueEmpty(SqQueue &Q)//队列是否为空
{
return Q->front == Q->rear;
}
int DeQueue(SqQueue &Q, Person &e)//出队列
{
e = Q->data[Q->front];
Q->front =(Q->front+1)%MAXQSIZE;
return true;
}
void DancePartner(Person dancer[], int num) //配对舞伴
{
Person p,q;
for(int i = 0;i < num;i++){
if(dancer[i].sex == 'M'){
EnQueue(Mdancers,dancer[i]);
}
else {
EnQueue(Fdancers,dancer[i]);
}
}
while(!QueueEmpty(Mdancers) && !QueueEmpty(Fdancers)){
DeQueue(Fdancers,p);
DeQueue(Mdancers,q);
cout<
6-2 小孩报数(顺序循环队列版) (15 分)
有若干个小孩围成一圈,现从指定的第1个开始报数,报到第 w个时,该小孩出列,然后从下一个小孩开始报数,仍是报到w个出列,如此重复下去,直到所有的小孩都出列(总人数不足w个时将循环报数),求小孩出列的顺序。 算法要求:使用顺序循环队列来存储所有小孩,报数时小孩出队,未数到w时,接着入队;数到w时,输出小孩的名字,该小孩不再入队,如此直到所有小孩出队,队列为空时停止报数。 请写出顺序循环队列的所有基本操作。 说明 :参与报数游戏的小孩人数不能超过10人。
数据结构与操作函数接口定义:
typedef char ElemType;
typedef struct // 顺序循环队列结点定义
{
ElemType *name[MaxSize]; //小孩姓名
int front,rear; //队首和队尾指针
} SqQueue;
void InitQueue(SqQueue *&q); //初始化队列;
void DestroyQueue(SqQueue *&q); //销毁队列;
bool QueueEmpty(SqQueue *q); //判定队列为空时返回true; 否则返回false;
bool enQueue(SqQueue *&q,ElemType *e); // e 入队;成功入队返回true; 否则返回false;
bool deQueue(SqQueue *&q,ElemType *&e); //出队,返回出队元素e,且成功出队返回true,否则返回false;
裁判测试程序样例:
#include
#include
#include
#define MaxSize 11
#define N 10
int main()
{
ElemType *e;
int n,i;
SqQueue *q;
InitQueue(q);
scanf("%d",&n);
while(1)
{
char *name=(char *)malloc(sizeof(char)*N);
scanf("%s",name);
if( (strcmp("-1",name)==0)||!enQueue(q,name))
break;
}
i=n-1;
while(!QueueEmpty(q))
{
deQueue(q,e);
if(i–>0)
enQueue(q,e);
else
{
printf("%s\n",e);
i=n-1;
free(e);
}
}
DestroyQueue(q);
}
/* 请在这里填写答案 */
输入样例:
第一行:报数w;
第二行:输入若干小孩姓名,以空格符间隔,以字符串“-1”结束输入。 在这里给出一组输入。例如:
3
Jenny Mike Lily Tom Yoyo -1
输出样例:
在这里给出相应的输出。例如:
Lily
Jenny
Yoyo
Mike
Tom
代码如下
void InitQueue(SqQueue *&q) //初始化队列;
{
q = new SqQueue; //为队列分配一个最大容量为MAXSIZE的数组空间
q->front = q->rear = 0; //头指针和尾指针置为零,队列为空
}
void DestroyQueue(SqQueue *&q) //销毁队列;
{
delete q;
}
bool QueueEmpty(SqQueue *q) //判定队列为空时返回true; 否则返回false;
{
if(q->front == q->rear)
return true;
else
return false;
}
bool enQueue(SqQueue *&q,ElemType *e) // e 入队;成功入队返回true; 否则返回false;
{
if(q->front == (q->rear+1)%MaxSize)
return false;
q->name[q->rear]=e;
q->rear = (q->rear+1)%MaxSize;
return true;
}
bool deQueue(SqQueue *&q,ElemType *&e) //出队,返回出队元素e,且成功出队返回true,否则返回false;
{
if(q->front == q->rear)
return false;
e = q->name[q->front];
q->front =(q->front+1)%MaxSize;
return true;
}
6-3 另类循环队列 (20 分)
如果用一个循环数组表示队列,并且只设队列头指针Front,不设尾指针Rear,而是另设Count记录队列中元素个数。请编写算法实现队列的入队和出队操作。
函数接口定义:
bool AddQ( Queue Q, ElementType X );
ElementType DeleteQ( Queue Q );
其中Queue结构定义如下:
typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
ElementType Data; / 存储元素的数组 /
Position Front; / 队列的头指针 /
int Count; / 队列中元素个数 /
int MaxSize; / 队列最大容量 */
};
typedef PtrToQNode Queue;
注意:如果队列已满,AddQ函数必须输出“Queue Full”并且返回false;如果队列是空的,则DeleteQ函数必须输出“Queue Empty”,并且返回ERROR。
裁判测试程序样例:
#include
#include
#define ERROR -1
typedef int ElementType;
typedef enum { addq, delq, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
ElementType Data; / 存储元素的数组 /
Position Front; / 队列的头、尾指针 /
int Count; / 队列中元素个数 /
int MaxSize; / 队列最大容量 */
};
typedef PtrToQNode Queue;
Queue CreateQueue( int MaxSize )
{
Queue Q = (Queue)malloc(sizeof(struct QNode));
Q->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
Q->Front = 0;
Q->Count = 0;
Q->MaxSize = MaxSize;
return Q;
}
bool AddQ( Queue Q, ElementType X );
ElementType DeleteQ( Queue Q );
Operation GetOp(); /* 裁判实现,细节不表 */
int main()
{
ElementType X;
Queue Q;
int N, done = 0;
scanf("%d", &N);
Q = CreateQueue(N);
while ( !done ) {
switch( GetOp() ) {
case addq:
scanf("%d", &X);
AddQ(Q, X);
break;
case delq:
X = DeleteQ(Q);
if ( X!=ERROR ) printf("%d is out\n", X);
break;
case end:
while (Q->Count) printf("%d ", DeleteQ(Q));
done = 1;
break;
}
}
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
4
Del
Add 5
Add 4
Add 3
Del
Del
Add 2
Add 1
Add 0
Add 10
End
输出样例:
Queue Empty
5 is out
4 is out
Queue Full
3 2 1 0
代码如下
bool AddQ( Queue Q, ElementType X )
{
if(Q->Count == Q->MaxSize){
printf("Queue Full\n");
return false;
}
Q->Count++;
Q->Data[(Q->Front+Q->Count)%Q->MaxSize]=X;
return true;
}
ElementType DeleteQ( Queue Q )
{
ElementType e;
if(Q->Count == 0){
printf("Queue Empty\n");
return ERROR;
}
Q->Count-- ;
Q->Front = ( Q->Front+1) %Q->MaxSize;
e = Q->Data[Q->Front];
return e;
}
6-4 双端队列 (25 分)
双端队列(deque,即double-ended queue的缩写)是一种具有队列和栈性质的数据结构,即可以(也只能)在线性表的两端进行插入和删除。若以顺序存储方式实现双端队列,请编写例程实现下列操作:
Push(X,D):将元素X插入到双端队列D的头;
Pop(D):删除双端队列D的头元素,并返回;
Inject(X,D):将元素X插入到双端队列D的尾部;
Eject(D):删除双端队列D的尾部元素,并返回。
函数接口定义:
bool Push( ElementType X, Deque D );
ElementType Pop( Deque D );
bool Inject( ElementType X, Deque D );
ElementType Eject( Deque D );
其中Deque结构定义如下:
typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
ElementType Data; / 存储元素的数组 /
Position Front, Rear; / 队列的头、尾指针 /
int MaxSize; / 队列最大容量 */
};
typedef PtrToQNode Deque;
注意:Push和Inject应该在正常执行完操作后返回true,或者在出现非正常情况时返回false。当Front和Rear相等时队列为空,Pop和Eject必须返回由裁判程序定义的ERROR。
裁判测试程序样例:
#include
#include
#define ERROR -1
typedef int ElementType;
typedef enum { push, pop, inject, eject, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
ElementType Data; / 存储元素的数组 /
Position Front, Rear; / 队列的头、尾指针 /
int MaxSize; / 队列最大容量 */
};
typedef PtrToQNode Deque;
Deque CreateDeque( int MaxSize )
{ /* 注意:为区分空队列和满队列,需要多开辟一个空间 */
Deque D = (Deque)malloc(sizeof(struct QNode));
MaxSize++;
D->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
D->Front = D->Rear = 0;
D->MaxSize = MaxSize;
return D;
}
bool Push( ElementType X, Deque D );
ElementType Pop( Deque D );
bool Inject( ElementType X, Deque D );
ElementType Eject( Deque D );
Operation GetOp(); /* 裁判实现,细节不表 /
void PrintDeque( Deque D ); / 裁判实现,细节不表 */
int main()
{
ElementType X;
Deque D;
int N, done = 0;
scanf("%d", &N);
D = CreateDeque(N);
while (!done) {
switch(GetOp()) {
case push:
scanf("%d", &X);
if (!Push(X, D)) printf("Deque is Full!\n");
break;
case pop:
X = Pop(D);
if ( X==ERROR ) printf("Deque is Empty!\n");
else printf("%d is out\n", X);
break;
case inject:
scanf("%d", &X);
if (!Inject(X, D)) printf("Deque is Full!\n");
break;
case eject:
X = Eject(D);
if ( X==ERROR ) printf("Deque is Empty!\n");
else printf("%d is out\n", X);
break;
case end:
PrintDeque(D);
done = 1;
break;
}
}
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
3
Pop
Inject 1
Pop
Eject
Push 2
Push 3
Eject
Inject 4
Inject 5
Inject 6
Push 7
Pop
End
输出样例:
Deque is Empty!
1 is out
Deque is Empty!
2 is out
Deque is Full!
Deque is Full!
3 is out
Inside Deque: 4 5
作者: DS课程组
单位: 浙江大学
时间限制: 400 ms
内存限制: 64 MB
代码如下
bool Push( ElementType X, Deque D )
{
if(D->Front == (D->Rear+1)%D->MaxSize)
return false;
D->Front = (D->Front-1+D->MaxSize)%D->MaxSize;
D->Data[D->Front] = X;
return true;
}
ElementType Pop( Deque D )
{
if(D->Front == D->Rear)
return ERROR;
ElementType t = D->Data[D->Front];
D->Front = (D->Front+1)%D->MaxSize;
return t;
}
bool Inject( ElementType X, Deque D )
{
if(D->Front == (D->Rear+1)%D->MaxSize)
return false;
D->Data[D->Rear] = X;
D ->Rear = (D->Rear+1)%D->MaxSize;
return true;
}
ElementType Eject( Deque D )
{
if(D->Front == D->Rear)
return ERROR;
D->Rear = (D->Rear-1+D->MaxSize)%D->MaxSize;
return D->Data[D->Rear];
}
7-1 堆栈模拟队列 (25 分)
设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q。
所谓用堆栈模拟队列,实际上就是通过调用堆栈的下列操作函数:
int IsFull(Stack S):判断堆栈S是否已满,返回1或0;
int IsEmpty (Stack S ):判断堆栈S是否为空,返回1或0;
void Push(Stack S, ElementType item ):将元素item压入堆栈S;
ElementType Pop(Stack S ):删除并返回S的栈顶元素。
实现队列的操作,即入队void AddQ(ElementType item)和出队ElementType DeleteQ()。
输入格式:
输入首先给出两个正整数N1和N2,表示堆栈S1和S2的最大容量。随后给出一系列的队列操作:A item表示将item入列(这里假设item为整型数字);D表示出队操作;T表示输入结束。
输出格式:
对输入中的每个D操作,输出相应出队的数字,或者错误信息ERROR:Empty。如果入队操作无法执行,也需要输出ERROR:Full。每个输出占1行。
输入样例:
3 2
A 1 A 2 A 3 A 4 A 5 D A 6 D A 7 D A 8 D D D D T
输出样例:
ERROR:Full
1
ERROR:Full
2
3
4
7
8
ERROR:Empty
代码如下
#include
#include
#include
typedef enum { addq, delq, end } Operation;
Operation GetOp() {
char a[11];
scanf("%s", a);
if (!strcmp("A", a)) return addq;
if (!strcmp("D", a)) return delq;
return end;
}
int main()
{
int s1[100],s2[100];
int m,n,done =0;
scanf("%d%d", &m,&n);
if(m>n){
m=n;
}
int X;
int cont =0 ,cont2 =0;
while (!done) {
switch(GetOp()) {
case addq:
scanf("%d", &X);
if (cont == m && cont2) printf("ERROR:Full\n");
else if(cont == m){
while(cont){
s2[cont2++] = s1[--cont];
}
s1[cont++] = X;
}
else
s1[cont++] = X;
break;
case delq:
if (!cont&&!cont2) printf("ERROR:Empty\n");
else{
if(!cont2){
while(cont)
s2[cont2++] = s1[--cont];
}
printf("%d\n",s2[--cont2]);
}
break;
case end:
done = 1;
break;
}
}
return 0;
}
7-2 银行业务队列简单模拟 (25 分)
设某银行有A、B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 —— 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客。给定到达银行的顾客序列,请按业务完成的顺序输出顾客序列。假定不考虑顾客先后到达的时间间隔,并且当不同窗口同时处理完2个顾客时,A窗口顾客优先输出。
输入格式:
输入为一行正整数,其中第1个数字N(≤1000)为顾客总数,后面跟着N位顾客的编号。编号为奇数的顾客需要到A窗口办理业务,为偶数的顾客则去B窗口。数字间以空格分隔。
输出格式:
按业务处理完成的顺序输出顾客的编号。数字间以空格分隔,但最后一个编号后不能有多余的空格。
输入样例:
8 2 1 3 9 4 11 13 15
输出样例:
1 3 2 9 11 4 13 15
代码如下
#include
#include
int main()
{
int A[1100],B[1100];
int n;
scanf("%d",&n);
int m = n;
int X;
int afront = 0 ,bfront =0,arear =0,brear =0;
while(n--){
scanf("%d",&X);
if(X%2==0)
B[brear++] = X;
else
A[arear++] =X;
}
int k =0;
while(afront < arear || bfront < brear){
if(afront < arear){
printf("%d",A[afront++]);
if(k < m-1){
printf(" ");
k++;
}
}
if(afront < arear){
printf("%d",A[afront++]);
if(k < m-1){
printf(" ");
k++;
}
}
if(bfront < brear){
printf("%d",B[bfront++]);
if(k < m-1){
printf(" ");
k++;
}
}
}
return 0;
}
7-3 列车调度 (25 分)
火车站的列车调度铁轨的结构如下图所示。
两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?
输入格式:
输入第一行给出一个整数N (2 ≤ N ≤10
5
),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。
输出格式:
在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。
输入样例:
9
8 4 2 5 3 9 1 6 7
输出样例:
4
代码如下
在这里插入代码片