赞
踩
双端队列(Double-ended queue,简称Deque)是一种数据结构,允许在队列的两端进行插入和删除操作。它可以被看作是一个允许元素插入和删除的线性表,但与普通队列不同,双端队列支持在队列的头部和尾部进行插入和删除操作,因此具有更加灵活的使用方式。
双端队列的特点包括:
前端插入和删除: 可以在双端队列的前端执行插入和删除操作。这使得双端队列可以像栈一样用于一些问题,比如实现逆序计算或其他需要后进先出(LIFO)操作的场景。
后端插入和删除: 同样可以在双端队列的后端执行插入和删除操作。这使得双端队列保持了队列的性质,即先进先出(FIFO)。
双端队列常见的操作包括:
双端队列在很多算法和数据结构问题中都有广泛的应用,因为它的灵活性使得它可以同时满足栈和队列的需求。在编程中,许多编程语言提供了标准库中的双端队列实现,以方便开发者使用。
下面分别是用链表和数组实现双端队列:
先定义一个接口:
- public interface Deque<E>
- {
- /**
- * 从头部插入
- * @param e 要插入的元素
- * @return 是否插入成功
- */
- boolean offerFirst(E e);
- /**
- * 从尾部插入
- * @param e 要插入的元素
- * @return 是否插入成功
- */
- boolean offerLast(E e);
- /**
- * 从头部删除
- * @return 被删除的元素
- */
- E pollFirst();
- /**
- * 从尾部删除
- * @return 被删除的元素
- */
- E pollLast();
- /**
- * 从头部查看
- * @return 被查看的元素
- */
- E peekFirst();
- /**
- * 从尾部查看
- * @return 被查看的元素
- */
- E peekLast();
- /**
- * 队列是否为空
- * @return 是否为空
- */
- boolean isEmpty();
- /**
- * 队列是否已满
- * @return 是否已满
- */
- boolean isFull();
- }
链表实现:
-
-
- public class LinkedListDeque<E> implements Deque<E>, Iterable<E>
- {
- /**
- * 双向链表节点类
- * @param <E> 节点存储的元素类型
- */
- static class Node<E>
- {
- Node<E> prev;//前驱,表示当前节点的前一个节点
- E value;//值
- Node<E> next;//后继,当前节点的后一个节点
- Node(final Node<E> prev,final E value,final Node<E> next)
- {
- this.prev = prev;
- this.value = value;
- this.next = next;
- }
- }
- int capacity = Integer.MAX_VALUE;//容量
- int size;//当前元素个数
- Node<E> sentinel = new Node<>(null,null,null);//哨兵节点
-
- /**
- * 构造函数
- * @param capacity 容量
- */
- public LinkedListDeque(final int capacity)
- {
- this.capacity = capacity;
- sentinel.prev = sentinel;
- sentinel.next = sentinel;
- }
- /**
- * 构造函数
- */
- public LinkedListDeque()
- {
- sentinel.prev = sentinel;
- sentinel.next = sentinel;
- }
-
- /**
- * 迭代器
- * @return 迭代器
- */
- @Override
- public Iterator<E> iterator()
- {
- return new Iterator<E>() {
- Node<E> p = sentinel.next;//当前节点
- /**
- * 是否有下一个元素
- * @return 是否有下一个元素,p不等于哨兵节点时有下一个元素
- */
- @Override
- public boolean hasNext()
- {
- return p != sentinel;
- }
-
- /**
- * 获取当前元素的值,并将p指向下一个元素
- * @return 当前元素的值
- */
-
- @Override
- public E next()
- {
- E value = p.value;
- p = p.next;
- return value;
- }
- };
- }
-
- /**
- * 从头部插入
- * @param e 要插入的元素
- * @return 是否插入成功
- */
- @Override
- public boolean offerFirst(final E e)
- {
- if (isFull())
- {
- return false;
- }
- Node<E> a = sentinel;
- Node<E> b = sentinel.next;
- Node<E> added = new Node<>(a,e,b);
- a.next = added;
- b.prev = added;
- size ++;
- return true;
- }
-
- /**
- * 从尾部插入
- * @param e 要插入的元素
- * @return 是否插入成功
- */
- @Override
- public boolean offerLast(final E e)
- {
- if (isFull())
- {
- return false;
- }
- Node<E> a = sentinel.prev;
- Node<E> b = sentinel;
- Node<E> added = new Node<>(a,e,b);
- a.next = added;
- b.prev = added;
- size ++;
- return true;
- }
-
- /**
- * 从头部删除
- * @return 被删除的元素
- */
- @Override
- public E pollFirst()
- {
- if (isEmpty())
- {
- return null;
- }
- Node<E> a = sentinel;
- Node<E> removed = sentinel.next;
- Node<E> b = removed.next;
- a.next = b;
- b.prev = a;
- size --;
- return removed.value;
- }
-
- /**
- * 从尾部删除
- * @return 被删除的元素
- */
- @Override
- public E pollLast()
- {
- if (isEmpty())
- {
- return null;
- }
- Node<E> removed = sentinel.prev;
- Node<E> a = removed.prev;
- Node<E> b = sentinel;
- a.next = b;
- b.prev = a;
- size --;
- return removed.value;
- }
-
- /**
- * 从头部查看
- * @return 被查看的元素
- */
- @Override
- public E peekFirst()
- {
- if (isEmpty())
- {
- return null;
- }
- return sentinel.next.value;
- }
-
- /**
- * 从尾部查看
- * @return 被查看的元素
- */
- @Override
- public E peekLast()
- {
- if (isEmpty())
- {
- return null;
- }
- return sentinel.prev.value;
- }
-
- /**
- * 队列是否为空
- * @return 是否为空
- */
- @Override
- public boolean isEmpty()
- {
- return size == 0;
- }
-
- /**
- * 队列是否已满
- * @return 是否已满
- */
- @Override
- public boolean isFull()
- {
- return size == capacity;
- }
-
-
- /**
- * 重写toString方法
- */
-
- @Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append("[");
- int i = 0;
- for (E e : this)
- {
- i ++;
- if (i == size)
- {
- sb.append(e);
- }
- else
- {
- sb.append(e);
- sb.append(",");
- }
- }
- sb.append("]");
- return sb.toString();
- }
- }
数组实现:
-
-
- public class ArrayDeque1<E> implements Iterable<E>, Deque<E>
- {
- /**
- * 用于给数组下标加1,如果到达数组末尾则返回0
- * @param i 当前下标
- * @param length 数组长度
- * return i+1 下标加1
- */
- static int inc(int i,int length)
- {
- if (i + 1 >= length)
- {
- return 0;
- }
- return i + 1;
- }
-
- /**
- * 用于给数组下标减1,如果到达数组头部则返回数组末尾下标
- * @param i 当前下标
- * @param length 数组长度
- * return i-1 下标减1
- */
- static int dec(int i,int length)
- {
- if (i - 1 < 0)
- {
- return length - 1;
- }
- return i - 1;
- }
-
- E[] array;//数组
- int head;//头指针,代表该队列的第一个元素
- int tail;//尾指针,始终置空,不存储元素,只是用来标记下一次尾部插入时,元素插入的位置
-
- /**
- * 构造函数
- * @param capacity 容量
- */
- public ArrayDeque1(int capacity)
- {
- array = (E[]) new Object[capacity + 1];
- }
-
- /**
- * 实现迭代器
- */
- @Override
- public Iterator<E> iterator()
- {
- return new Iterator<E>() {
- int p = head;//当前指针
- /**
- * 是否有下一个元素
- * @return 是否有下一个元素,p不等于尾指针时有下一个元素
- */
- @Override
- public boolean hasNext() {
- return p != tail;
- }
-
- /**
- * 获取当前元素的值,并将p指向下一个元素
- * @return 当前元素的值
- */
- @Override
- public E next() {
- E value = array[p];
- p = inc(p,array.length);
- return value;
- }
- };
- }
-
- /**
- * 从头部插入
- * @param e 要插入的元素
- * @return 是否插入成功
- */
- @Override
- public boolean offerFirst(E e)
- {
- if (isFull())
- {
- return false;
- }
- head = dec(head,array.length);//头指针向前一步
- array[head] = e;//在当前头指针处插入元素
- return true;
- }
-
- /**
- * 从尾部插入
- * @param e 要插入的元素
- * @return 是否插入成功
- */
- @Override
- public boolean offerLast(E e)
- {
- if (isFull())
- {
- return false;
- }
- array[tail] = e;//在当前尾指针处插入元素
- tail = inc(tail,array.length);//尾指针向后一步
- return true;
- }
-
- /**
- * 从头部删除
- * @return 被删除的元素
- */
- @Override
- public E pollFirst()
- {
- if (isEmpty())
- {
- return null;
- }
- E e = array[head];
- array[head] = null;//清理内存,help GC
- head = inc(head,array.length);
- return e;
- }
-
- @Override
- public E pollLast()
- {
- if (isEmpty())
- {
- return null;
- }
- tail = dec(tail,array.length);
- E e = array[tail];
- array[tail] = null;//help GC
- return e;
- }
-
- /**
- * 从头部查看
- * @return 被查看的元素
- */
- @Override
- public E peekFirst()
- {
- if (isEmpty())
- {
- return null;
- }
- return array[head];
- }
-
- /**
- * 从尾部查看
- * @return 被查看的元素
- */
- @Override
- public E peekLast()
- {
- if (isEmpty())
- {
- return null;
- }
- return array[dec(tail,array.length)];
- }
-
- /**
- * 队列是否为空
- * @return 是否为空
- */
- @Override
- public boolean isEmpty()
- {
- return head == tail;
- }
-
- /**
- * 队列是否已满,两种情况:
- * 1.如果尾指针在头指针后面,则当尾指针减头指针等于数组长度减1时,队列已满
- * 2.如果尾指针在头指针前面,则当头指针减尾指针等于1时,也就是头指针紧挨着尾指针,队列已满
- * @return 是否已满
- */
- @Override
- public boolean isFull()
- {
- if (tail > head)
- {
- return tail - head == array.length - 1;
- }
- else if (tail < head)
- {
- return head - tail == 1;
- }
- else
- {
- return false;
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。