双端队列链式实现完整代码

看看思想,,,代码都是调试通过的。

#ifndef  _TWO_QUEUE_H_
#define  _TWO_QUEUE_H_

typedef int ElemType;

typedef  struct _two_queue
{
 ElemType a;
 struct _two_queue *prev;
 struct _two_queue *next;
}tq;


typedef  struct _node
{
 tq *first_head;
 tq *first_tail;
 tq *last_head;
 tq *last_tail;
}pnode;

typedef  enum _status
{
 first,last
}status;

//初始化空队列:
void init_queue(pnode *p);

//销毁队列:
void destroy_queue(pnode *p);

//判断是否为空队列:
bool is_empty(pnode *p);

//获得队头元素:
void get_head(pnode *p,ElemType *e,status sign);

//入队:
void push_queue(pnode *p,ElemType e,status sign);

//出队:
void pop_queue(pnode *p,ElemType *e,status sign);
#endif


/*双端队列函数基本操作实现如下*/

#include"two_queue.h"
#include<stdio.h>
#include<stdlib.h>

//初始化空队列:
void init_queue(pnode *p)
{
 if(p == NULL)
 {
  printf("error\n");
  exit(1);
 }
 else
 {
  p->first_head = NULL;
  p->first_tail = NULL;
  p->last_head = NULL;
  p->last_tail = NULL;
 }
}

//判断是否为空队列:
bool is_empty(pnode *p)
{
 return p->first_head == NULL;
}

//入队:
void push_queue(pnode *p,ElemType e,status sign)
{
 tq *tmp = (tq *)malloc(sizeof(tq)*1);
 tmp->a  = e;
 tmp->next = NULL;
 if(is_empty(p))
 {
  p->first_head = tmp;
  p->first_tail = tmp;
  p->last_head = tmp;
  p->last_tail = tmp;
 }
 else
 {
  if(sign == first)
  {
    tmp->next = p->first_head;
     p->first_head ->prev = tmp;
        p->first_tail = tmp;
     p->first_head = tmp;
  }
  else
  {
     tmp->prev = p->last_head;
     p->last_head->next = tmp;
        p->last_tail = tmp;
     p->last_head = tmp;
  }
 }

}

//出队:
void pop_queue(pnode *p,ElemType *e,status sign)
{
 if(is_empty(p))
 {
  printf("error\n");
  exit(1);
 }
 else
 {
  if(sign == first)
  {
     *e = p->first_head->a;
        p->first_head = p->first_head->next;
  }
  else
  {
     *e = p->last_head ->a;
        p->last_head = p->last_head->prev;
  }
 }
}

//销毁队列:
void destroy_queue(pnode *p)
{
 tq *s = p->first_head;
 if(is_empty(p))
 {
  printf("error\n");
  exit(1);
 }
 else
 {
  while(s)
  {
   p->first_head = p->first_head->next;
   free(s);
   s = p->first_head;
  }
  p->first_head = NULL;
  p->first_tail = NULL;
  p->last_head  = NULL;
  p->last_tail = NULL;
  printf("the queue is destroyed successfully\n ");
 }
}

//获得队头元素:
void get_head(pnode *p,ElemType *e,status sign)
{
 if(is_empty(p))
 {
  printf("the queue is NULL,no top number\n");
  exit(1);
 }
 else
 {
  if(sign == first)
  {
    *e = p->first_head->a;
  }
  else
  {
   *e = p->last_head->a;
  }
 }
}



//主函数

#include<stdio.h>
#include"two_queue.h"

int main()
{
 int n = 10;
 int x = -99;
 int k = 100;
 int y;
 int t;
 pnode m;
 init_queue(&m);
 push_queue(&m,n,first);
 push_queue(&m,k,last);
 push_queue(&m,x,first);
 //get_head(&m,&t,first);
 //printf("%d\n",t);
 //get_head(&m,&y,last);
 //printf("%d\n",y);
 pop_queue(&m,&y,first);
 //pop_queue(&m,&t,first);
 printf("%d\n",y);
 //printf("%d\n",t);
 destroy_queue(&m);
 get_head(&m,&t,first);
 printf("%d\n",t);
 return 0;
}






/* * 基于双向链表实现双端队列结构 */ package dsa; public class Deque_DLNode implements Deque { protected DLNode header;//指向头节点(哨兵) protected DLNode trailer;//指向尾节点(哨兵) protected int size;//队列中元素的数目 //构造函数 public Deque_DLNode() { header = new DLNode(); trailer = new DLNode(); header.setNext(trailer); trailer.setPrev(header); size = 0; } //返回队列中元素数目 public int getSize() { return size; } //判断队列是否为空 public boolean isEmpty() { return (0 == size) ? true : false; } //取首元素(但不删除) public Object first() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return header.getNext().getElem(); } //取末元素(但不删除) public Object last() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return trailer.getPrev().getElem(); } //在队列前端插入新节点 public void insertFirst(Object obj) { DLNode second = header.getNext(); DLNode first = new DLNode(obj, header, second); second.setPrev(first); header.setNext(first); size++; } //在队列后端插入新节点 public void insertLast(Object obj) { DLNode second = trailer.getPrev(); DLNode first = new DLNode(obj, second, trailer); second.setNext(first); trailer.setPrev(first); size++; } //删除首节点 public Object removeFirst() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = header.getNext(); DLNode second = first.getNext(); Object obj = first.getElem(); header.setNext(second); second.setPrev(header); size--; return(obj); } //删除末节点 public Object removeLast() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = trailer.getPrev(); DLNode second = first.getPrev(); Object obj = first.getElem(); trailer.setPrev(second); second.setNext(trailer); size--; return(obj); } //遍历 public void Traversal() { DLNode p = header.getNext(); while (p != trailer) { System.out.print(p.getElem()+" "); p = p.getNex
<think>好的,用户想了解双端队列的概念、定义和使用方法。首先,我需要回忆双端队列的基本定义,确保准确无误。根据引用[1]和[2],双端队列是一种允许在两端进行插入和删除操作的数据结构,结合了队列和栈的特性。接下来需要解释它的逻辑结构和操作,比如入队、出队的方法,以及顺序存储和链式存储的不同实现方式,这部分可以参考引用[3]和[5]。 用户可能对双端队列的应用场景不太清楚,需要结合实际例子说明,比如滑动窗口或撤销操作,如引用[2]提到的。同时,要注意区分双端队列与普通队列、栈的区别,强调其双向操作的灵活性。 另外,用户提供的引用中有代码示例,比如接口定义,可以引用[5]中的Java代码来说明双端队列的方法,比如offerFirst、pollLast等。同时,需要指出实现时的注意事项,比如循环数组的使用和指针管理,这部分引用[3]提到顺序存储的三种方法,可能需要简要说明。 还要确保回答结构清晰,分点讲解定义、特点、实现方式和应用场景,最后生成相关问题时要覆盖基本概念、实现细节、应用及比较,帮助用户深入理解。检查是否有遗漏的信息,比如双端队列的优缺点,引用[2]提到的高效处理双向数据流,这也是需要强调的。 最后,确保所有数学公式和代码块格式正确,使用中文回答,并自然添加引用标识。这样用户能系统地掌握双端队列的相关知识,并解决可能的问题。</think>### 双端队列的概念及用法解析 #### 一、双端队列的定义 **双端队列(Deque,Double-Ended Queue)** 是一种允许从队列的**前端(front)和尾端(rear)** 同时进行插入和删除操作的线性数据结构。它结合了队列(先进先出)和栈(后进先出)的特性,支持以下操作: - 两端插入元素:`offerFirst(e)`、`offerLast(e)` - 两端删除元素:`pollFirst()`、`pollLast()` - 查看两端元素:`peekFirst()`、`peekLast()` - 判空与判满:`isEmpty()`、`isFull()`[^5] #### 二、双端队列的核心特点 1. **双向操作**:相比普通队列仅支持尾部插入和头部删除,双端队列的操作更加灵活。 2. **混合特性**: - 若仅使用一端的插入和删除操作,则表现为栈; - 若固定一端插入、另一端删除,则表现为队列[^2]。 3. **实现方式**: - **顺序存储**:通过循环数组实现,需处理队满条件(如空间置换法、队长法、标志法)[^3]。 - **链式存储**:通过双向链表实现,天然支持两端操作,无需预先分配固定空间。 #### 三、双端队列的应用场景 1. **滑动窗口算法**:如求数组滑动窗口的最大值,需高效维护窗口两端元素。 2. **撤销操作**:支持用户从操作历史的两端撤销或重做(如文本编辑)。 3. **多线程任务调度**:允许任务从队列两端加入或取出,平衡负载。 4. **回文检测**:通过两端同时弹出字符进行比较。 #### 四、代码示例(链式存储实现) ```java // 双向链表节点定义 class Node<E> { E value; Node<E> prev; Node<E> next; } // 双端队列接口实现(简化版) public class LinkedDeque<E> implements Deque<E> { private Node<E> head; private Node<E> tail; public boolean offerFirst(E e) { Node<E> newNode = new Node<>(e); if (isEmpty()) { head = tail = newNode; } else { newNode.next = head; head.prev = newNode; head = newNode; } return true; } public E pollLast() { if (isEmpty()) return null; E value = tail.value; tail = tail.prev; if (tail != null) tail.next = null; else head = null; // 队列已空 return value; } // 其他方法类似... } ``` #### 五、与普通队列的对比 | 特性 | 普通队列 | 双端队列 | |--------------------|------------------|----------------------| | 插入位置 | 仅尾部 | 头尾均可 | | 删除位置 | 仅头部 | 头尾均可 | | 时间复杂度(插入/删除) | $O(1)$ | $O(1)$ | | 典型应用 | 任务调度、BFS | 滑动窗口、撤销操作 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值