6-3 Deque

这篇博客讨论了双端队列(deque)的数据结构,它是一个允许在两端进行插入和删除操作的列表。文章通过C语言实现了基于双向链表的deque,包括Push、Pop、Inject和Eject等操作,并提供了错误处理。示例代码展示了如何在空队列上执行这些操作,并给出了输入和输出样例。

6-3 Deque

分数 5

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

/*这题我忘记处理POP返回的指针了,卡了我四个小时!!!*/

#define shuiyunsheng 66666666666666

Deque CreateDeque()
{
    Deque head = (Deque)malloc(sizeof(struct DequeRecord));
    PtrToNode d = (PtrToNode)malloc(sizeof(struct Node));
    d->Next = d;
    d->Last = d;
    head->Front = d;
    head->Rear = d;
    return head;
}
int Push(ElementType X, Deque D)
{
    PtrToNode d = (PtrToNode)malloc(sizeof(struct Node));
    d->Element = X;
    if (D->Front == D->Rear)//如果为空,尾部指针需要更新
    {
        D->Rear = d;
    }
    d->Next = D->Front->Next;
    d->Last = D->Front;
    D->Front->Next->Last = d;
    D->Front->Next = d;
    return 1;
}
ElementType Pop(Deque D)
{
    if (D->Front == D->Rear)
        return ERROR;
    int n = D->Front->Next->Element;
    PtrToNode k = D->Front->Next;
    if (k == D->Rear)
    {
        D->Rear = D->Front;
    }
    k->Next->Last = D->Front;//Last 处理!!!!
    D->Front->Next = k->Next;
    free(k);
    return n;
}
int Inject(ElementType X, Deque D)
{
    PtrToNode d = (PtrToNode)malloc(sizeof(struct Node));
    d->Element = X;
    d->Next = D->Front;
    d->Last = D->Rear;
    D->Rear->Next = d;
    D->Rear = d;
    D->Front->Last = d;
    return 1;
}
ElementType Eject(Deque D)
{
    if (D->Front == D->Rear)
        return ERROR;
    int n = D->Rear->Element;
    PtrToNode k = D->Rear->Last;
    k->Next = D->Rear->Next;
    D->Front->Last = k;
    free(D->Rear);
    D->Rear = k;
    return n;
}

<think> 我们正在讨论deque(双端队列)的pop_front操作。根据引用[1]和引用[2]中提到的内容,pop_front()是用于从双端队列前端删除元素的操作。同时,引用[3]提供了deque内部结构的背景:deque由多个连续内存段组成,可以在两端高效地添加或删除元素。 由于用户要求了解pop_front的使用方法、功能和示例,我们将重点放在这些方面。 功能: pop_front()函数用于删除deque容器中的第一个元素。它不接受任何参数,也没有返回值(在C++标准库中)。调用此函数后,deque的大小(size)会减少一个元素。需要注意的是,如果deque为空,调用pop_front()会导致未定义行为(通常程序会崩溃),因此在调用前应确保deque非空。 使用方法(C++): 在C++中,使用pop_front()需要包含头文件<deque>。基本用法如下: deque_name.pop_front(); 示例: 我们可以结合引用[1]中提到的插入操作(push_front)来展示pop_front。首先创建一个deque,然后在前面插入一些元素,再使用pop_front删除前面的元素。 下面是一个完整的C++示例代码: ```cpp #include <iostream> #include <deque> using namespace std; int main() { deque<int> dq; // 使用push_front在deque前端插入元素(插入顺序为3, 2, 1) dq.push_front(3); dq.push_front(2); dq.push_front(1); // 现在deque中的元素顺序为: 1, 2, 3 // 使用pop_front删除第一个元素 dq.pop_front(); // 删除1 // 删除后,deque中的元素为: 2, 3 // 输出剩余元素 cout << "Deque after pop_front:"; for (int num : dq) { cout << &#39; &#39; << num; } cout << endl; return 0; } ``` 输出: Deque after pop_front: 2 3 注意事项: 1. 在调用pop_front()之前,应检查deque是否为空。可以使用empty()函数进行检查。 2. 与pop_front类似,pop_back()用于删除deque尾部的元素(引用[4]中展示了pop_back的使用)。 引用[4]中展示的vector的pop_back操作与deque的pop_front操作类似,都是删除元素,但vector不支持pop_front(因为vector在头部删除效率低)。 另外,引用[3]解释了deque的结构,使得在两端删除元素都是高效的操作,时间复杂度为$O(1)$。 总结: - pop_front()用于删除deque的第一个元素。 - 使用前需确保deque非空。 - 由于deque的设计,该操作非常高效。 以上内容参考了站内引用[1]、[2]、[3]、[4]。 </think> ### deque的pop_front操作详解 `pop_front()`是双端队列(deque)的核心操作之一,用于从容器**前端删除元素**。以下是详细说明和示例: --- #### **功能特性** 1. **删除元素**:移除deque的第一个元素(前端元素)。 2. **时间复杂度**:$O(1)$(得益于deque的分段连续内存结构[^3])。 3. **前置条件**:**deque必须非空**(若为空则行为未定义,通常导致崩溃)。 4. **无返回值**:直接修改容器,不返回被删除的元素(需先用`front()`获取值)。 --- #### **使用方法(C++)** ```cpp #include <deque> std::deque<T> dq; // 声明deque dq.pop_front(); // 删除前端元素 ``` #### **操作步骤** 1. 校验deque非空(避免未定义行为)。 2. 调用`pop_front()`删除第一个元素。 3. 容器大小减1,后续元素前移。 --- #### **完整示例代码** ```cpp #include <iostream> #include <deque> int main() { std::deque<int> dq = {10, 20, 30}; // 初始化: {10,20,30} std::cout << "删除前: "; for (int num : dq) std::cout << num << " "; // 输出: 10 20 30 dq.pop_front(); // 删除前端元素10 std::cout << "\n删除后: "; for (int num : dq) std::cout << num << " "; // 输出: 20 30 return 0; } ``` **输出**: ``` 删除前: 10 20 30 删除后: 20 30 ``` --- #### **注意事项** 1. **安全删除**:始终先检查容器是否为空: ```cpp if (!dq.empty()) dq.pop_front(); // 安全操作 ``` 2. **与`pop_back()`的区别**: - `pop_front()`删除前端元素(如队列头),`pop_back()`删除后端元素(如栈顶)[^1][^4]。 3. **内存管理**: deque的分段连续内存结构确保两端操作高效,无需整体移动元素[^3]。 --- #### **典型应用场景** 1. **队列模拟**:实现FIFO(先进先出)结构。 2. **滑动窗口算法**:动态移除窗口左侧过期数据。 3. **实时数据处理**:高效处理流式数据的前端过期项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值