作者 陈越
单位 浙江大学
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
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
C程序如下:
// 创建一个空的双端队列
Deque CreateDeque(){ // 分配内存给DequeRecord结构体 Deque p = (Deque)malloc(sizeof(struct DequeRecord)); // 如果内存分配失败,此处应该添加错误处理代码 // 分配内存给队列的第一个(也是唯一的)节点 PtrToNode q = (PtrToNode)malloc(sizeof(struct Node)); // 初始化节点,使其指向自己(空队列的情况) q->Next = q->Last = NULL; // 设置Deque的前端和后端都指向这个节点 p->Front = q; p->Rear = q; // 返回新创建的Deque return p;
} // 在双端队列的前端添加一个元素
int Push( ElementType X, Deque D ){ // 分配内存给新节点 PtrToNode q = (PtrToNode)malloc(sizeof(struct Node)); q->Element = X; // 如果队列为空(只有一个哨兵节点) if(D->Front == D->Rear){ // 新节点的Next和Last都设置为NULL(因为它是第一个元素) q->Next = NULL; // 前一个节点(也就是D->Front)的Next指向新节点 q->Last = D->Front; D->Front->Next = q; // 更新Rear指向新节点 D->Rear = q; } else{ // 如果队列不为空,将新节点插入到Front之后 q->Next = D->Front->Next; // 前一个节点(也就是D->Front->Next的前一个节点)的Last指向新节点 D->Front->Next->Last = q; // 更新Front的Next指向新节点 D->Front->Next = q; // 新节点的Last指向Front->Next(也就是原来的第一个元素) q->Last = D->Front->Next; } // 总是成功返回1 return 1;
} // 从双端队列的前端移除一个元素
ElementType Pop( Deque D ){ // 如果队列为空,返回错误值 if(D->Front == D->Rear){ return ERROR; } // 获取第一个节点(也就是要移除的节点) PtrToNode p = D->Front->Next; // 保存要返回的元素 ElementType m = p->Element; // 更新Front的Next指向下一个节点 D->Front->Next = p->Next; // 如果队列中只剩下一个节点(也就是哨兵节点),则更新Last指向NULL if(D->Front->Next == NULL) { D->Rear = D->Front; } else { // 否则,更新新的第一个节点的Last指向Front D->Front->Next->Last = D->Front; } // 释放移除的节点的内存 free(p); // 返回移除的元素 return m;
} // 在双端队列的后端添加一个元素
int Inject( ElementType X, Deque D ){ // 分配内存给新节点 PtrToNode p = (PtrToNode)malloc(sizeof(struct Node)); p->Element = X; // 新节点的Last指向原Rear节点 p->Last = D->Rear; // 原Rear节点的Next指向新节点 D->Rear->Next = p; // 更新Rear指向新节点 D->Rear = p; // 总是成功返回1 return 1;
} // 从双端队列的后端移除一个元素
ElementType Eject( Deque D ){ // 如果队列为空,返回错误值 if(D->Front == D->Rear){ return ERROR; } // 获取最后一个节点(也就是要移除的节点) ElementType m = D->Rear->Element; PtrToNode p = D->Rear; // 更新原Rear的前一个节点的Next指向NULL(因为Rear是最后一个节点) D->Rear->Last->Next = NULL; // 更新Rear指向原Rear的前一个节点 D->Rear = D->Rear->Last; // 释放移除的节点的内存 free(p); // 返回移除的元素 return m;
}