原题链接http://pta.patest.cn/pta/test/16/exam/3/question/696
4-1 Deque (25分)
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 Frontand 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 returnERROR 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
以下为答案,函数实现(C语言):
细节问题:
- D->Front始终为链表头指针,且头结点始终为空节点。D->Rear则不固定。
- 插入和删除一个节点时,务必考虑3种情况,Deque内为空时,Deque内只有一个元素时,和Deque内有多个元素时。
- 链表变动时,需要考虑当前插入节点的->Last和->Next,其前一个节点的->Next ,后一个节点的->Last,以及D->Front->Next和 D->Rear->Next与D->Rear->Last 这些变量在上述3种情况下是否需要改动。
Deque CreateDeque(){
PtrToNode Temp_Node = (PtrToNode)malloc(sizeof(struct Node));
Deque Temp_Record = (Deque)malloc(sizeof(struct DequeRecord));
// if(!Temp_Record||!Temp_Node)
// return -1;
Temp_Node->Next = NULL;
Temp_Node->Last = NULL;
Temp_Record->Front = Temp_Node;
Temp_Record->Rear = Temp_Node;
return Temp_Record;
}
int Push( ElementType X, Deque D ){
PtrToNode Temp_Node = (PtrToNode)malloc(sizeof(struct Node));
if(!Temp_Node)
return 0;
Temp_Node->Element = X;
Temp_Node->Last = D->Front;
Temp_Node->Next = D->Front->Next;
if(D->Front->Next)
D->Front->Next->Last = Temp_Node;
D->Front->Next = Temp_Node;
if(D->Front == D->Rear)
D->Rear = Temp_Node;
return 1;
}
ElementType Pop( Deque D ){
if(D->Front == D->Rear)
return ERROR;
PtrToNode Temp_Node = D->Front->Next;
if(D->Front->Next == D->Rear)
D->Rear = D->Front;
D->Front->Next = D->Front->Next->Next;
ElementType temp;
temp = Temp_Node->Element;
free(Temp_Node);
return temp;
}
int Inject( ElementType X, Deque D ){
PtrToNode Temp_Node = (PtrToNode)malloc(sizeof(struct Node));
if(!Temp_Node)
return ERROR;
Temp_Node->Element = X;
Temp_Node->Next = NULL;
D->Rear->Next = Temp_Node;
Temp_Node->Last = D->Rear;
if(D->Rear == D->Front)
D->Front->Next = Temp_Node;
D->Rear = Temp_Node;
return 1;
}
ElementType Eject( Deque D ){
if(D->Front == D->Rear)
return ERROR;
PtrToNode Temp_Node = D->Rear;
ElementType temp = D->Rear->Element;
D->Rear = D->Rear->Last;
free(Temp_Node);
return temp;
}