3-1 Deque (20 分)
A “deque” is a data structure consisting of a list of items, on which the following operations are possible:
Push(X,D): Insert item X on the front end of deque D.
Pop(D): Remove the front item from deque D and return it.
Inject(X,D): Insert item X on the rear end of deque D.
Eject(D): Remove the rear item from deque D and return it. Write routines to support the deque that take O(1) time per operation.
Format of functions:
Deque CreateDeque();
int Push( ElementType X, Deque D );
ElementType Pop( Deque D );
int Inject( ElementType X, Deque D );
ElementType Eject( Deque D );
where Deque is defined as the following:
typedef struct Node *PtrToNode;
struct Node {
ElementType Element;
PtrToNode Next, Last;
};
typedef struct DequeRecord *Deque;
struct DequeRecord {
PtrToNode Front, Rear;
};
Here the deque is implemented by a doubly linked list with a header. Front and Rear point to the two ends of the deque respectively. Front always points to the header. The deque is empty when Front and Rear both point to the same dummy header. Note: Push and Inject are supposed to return 1 if the operations can be done successfully, or 0 if fail. If the deque is empty, Pop and Eject must return ERROR which is defined by the judge program.
Sample program of judge:
#include <stdio.h>
#include <stdlib.h>
#define ElementType int
#define ERROR 1e5
typedef enum { push, pop, inject, eject, end } Operation;
typedef struct Node *PtrToNode;
struct Node {
ElementType Element;
PtrToNode Next, Last;
};
typedef struct DequeRecord *Deque;
struct DequeRecord {
PtrToNode Front, Rear;
};
Deque CreateDeque();
int Push( ElementType X, Deque D );
ElementType Pop( Deque D );
int Inject( ElementType X, Deque D );
ElementType Eject( Deque D );
Operation GetOp(); /* details omitted /
void PrintDeque( Deque D ); / details omitted */
int main()
{
ElementType X;
Deque D;
int done = 0;
D = CreateDeque();
while (!done) {
switch(GetOp()) {
case push:
scanf("%d", &X);
if (!Push(X, D)) printf("Memory is Full!\n");
break;
case pop:
X = Pop(D);
if ( X==ERROR ) printf("Deque is Empty!\n");
break;
case inject:
scanf("%d", &X);
if (!Inject(X, D)) printf("Memory is Full!\n");
break;
case eject:
X = Eject(D);
if ( X==ERROR ) printf("Deque is Empty!\n");
break;
case end:
PrintDeque(D);
done = 1;
break;
}
}
return 0;
}
/* Your function will be put here */
Sample Input:
Pop
Inject 1
Pop
Eject
Push 1
Push 2
Eject
Inject 3
End
结尾无空行
Sample Output:
Deque is Empty!
Deque is Empty!
Inside Deque: 2 3
这道题其实就是创造一个双向的队列,队列的头和尾都可以插或删,要注意的是在队头操作时,要注意没有元素和有元素的操作是不一样的,没有元素时进队还要移动队尾指针,有一个元素时出队也要移动队尾指针。但是在队尾操作时就不用单独分情况了,因为队尾永远指向最后一个元素,而队头指针一直指向的是头结点,所以无论有没有元素,都不需要移动队头了。
另外还要注意因为是双向链表。所以在插删时一定要注意Next和Last两个指针都必须改变。
#include<stdio.h>
#include<stdlib.h>
#define ElementType int
#define ERROR 1e5
typedef enum{push,pop,inject,eject,end}Operation;//还是弄一个枚举类型
typedef struct Node*PtrToNode;
struct Node{
ElementType Element;
PtrToNode Next,Last;//结点有两个指针哦
};
typedef struct DequeRecord*Deque;//头尾封装在一起的队列
struct DequeRecord{
PtrToNode Front ,Rear;
};
Deque CreateDeque();
Deque CreateDeque()//就是申请一个头尾指针结点,一个链队头结点,两个域置空,让头尾指针结点指向它
{
Deque L;
PtrToNode p;
L=(Deque)malloc(sizeof(struct DequeRecord));
p=(PtrToNode)malloc(sizeof(struct Node));
p->Next=NULL;
p->Last=NULL;
L->Front=p;
L->Rear=p;
return L;
}
int Push(ElementType X,Deque D);
int Push(ElementType X,Deque D)//一定要分情况哦
{
PtrToNode p;
p=(PtrToNode)malloc(sizeof(struct Node));
p->Element=X;
if(D->Front==D->Rear)
{
p->Next=NULL;
p->Last=D->Front;
D->Front->Next=p;
D->Rear=p;
}
else
{
p->Next=D->Front->Next;
p->Last=D->Front;
D->Front->Next=p;
p->Next->Last=p;
}
return 1;
}
ElementType Pop(Deque D);
ElementType Pop(Deque D)
{
if(D->Front==D->Rear)
return ERROR;
ElementType X;
PtrToNode p=D->Front->Next;
X=p->Element;
if(D->Front->Next==D->Rear)
{
D->Front->Next=NULL;
D->Rear=D->Front;
}
else
{
D->Front->Next=p->Next;
p->Next->Last=D->Front;
}
free(p);
return X;
}
int Inject(ElementType X,Deque D);
int Inject(ElementType X,Deque D)
{
PtrToNode p=(PtrToNode)malloc(sizeof(struct Node));
p->Element=X;
p->Last=D->Rear;
p->Next=NULL;
D->Rear->Next=p;
D->Rear=p;
return 1;
}
ElementType Eject(Deque D);
ElementType Eject(Deque D)
{
if(D->Front==D->Rear)
return ERROR;
ElementType X;
PtrToNode p=D->Rear;
X=p->Element;
p->Last->Next=NULL;
D->Rear=p->Last;
free(p);
return X;
}
Operation GetOp();
Operation GetOp()
{
const char*Ope[]={"push","pop","inject","eject","end"};
char array[10];
scanf("%s",array);
if(isupper(array[0]))
array[0]=array[0]+32;
Operation o;
for(o=push;o<=end;o++)
{
if(!strcmp(array,Ope[o]))
return o;
}
}
void PrintDeque(Deque D);
void PrintDeque(Deque D)
{
if(D->Front==D->Rear)
return 0;
else
{
PtrToNode s;
s=D->Front->Next;
printf("Inside Deque: ");
while(s)
{
printf("%d ",s->Element);
s=s->Next;
}
getchar();
}
}
int main()
{
ElementType X;
Deque D;
int done=0;
D=CreateDeque();
while(!done)
{
switch(GetOp())
{
case push:
scanf ("%d",&X);
if(!Push(X,D))printf("Memory is Full!\n");
break;
case pop:
X=Pop(D);
if(X==ERROR)printf("Deque is Empty!\n");
break;
case inject:
scanf("%d",&X);
if(!Inject(X,D))printf("Memory if Full\n");
break;
case eject:
X=Eject(D);
if(X==ERROR)printf("Deque is Empty\n");
break;
case end:
PrintDeque(D);
done=1;
break;
}
}
return 0;
}