4-1 Deque (25分)

本文介绍了如何使用C语言实现一个双端队列(deque),支持Push、Pop、Inject和Eject操作,每个操作的时间复杂度为O(1)。deque通过双向链表实现,维护一个头节点,并详细阐述了在不同情况下节点插入和删除时的边界条件和变量更新策略。
摘要由CSDN通过智能技术生成

原题链接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语言):

细节问题:
  1. D->Front始终为链表头指针,且头结点始终为空节点。D->Rear则不固定。
  2. 插入和删除一个节点时,务必考虑3种情况,Deque内为空时,Deque内只有一个元素时,和Deque内有多个元素时。
  3. 链表变动时,需要考虑当前插入节点的->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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值