Java 数据结构之Deque(双向队列)

一个线性 collection,支持在两端插入和移除元素。名称 deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。大多数Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。

此接口定义在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(nullfalse,具体取决于操作)。插入操作的后一种形式是专为使用有容量限制的 Deque 实现设计的;在大多数实现中,插入操作不能失败。

下表总结了上述 12 种方法:

 第一个元素(头部)最后一个元素(尾部)
 抛出异常特殊值抛出异常特殊值
插入addFirst(e)offerFirst(e)addLast(e)offerLast(e)
移除removeFirst()pollFirst()removeLast()pollLast()
检查getFirst()peekFirst()getLast()peekLast()

此接口扩展了 Queue 接口。在将双端队列用作队列时,将得到 FIFO(先进先出)行为。将元素添加到双端队列的末尾,从双端队列的开头移除元素。从Queue 接口继承的方法完全等效于 Deque 方法,如下表所示:

Queue 方法等效 Deque 方法
add(e)addLast(e)
offer(e)offerLast(e)
remove()removeFirst()
poll()pollFirst()
element()getFirst()
peek()peekFirst()

双端队列也可用作 LIFO(后进先出)堆栈。应优先使用此接口而不是遗留 Stack 类。在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。堆栈方法完全等效于Deque 方法,如下表所示:

堆栈方法等效 Deque 方法
push(e)addFirst(e)
pop()removeFirst()
peek()peekFirst()

注意,在将双端队列用作队列或堆栈时,peek 方法同样正常工作;无论哪种情况下,都从双端队列的开头抽取元素。

此接口提供了两种移除内部元素的方法:removeFirstOccurrence removeLastOccurrence

List 接口不同,此接口不支持通过索引访问元素。

虽然 Deque 实现没有严格要求禁止插入 null 元素,但建议最好这样做。建议任何事实上允许 null 元素的 Deque 实现用户最好 要利用插入 null 的功能。这是因为各种方法会将null 用作特殊的返回值来指示双端队列为空。

Deque 实现通常不定义基于元素的 equalshashCode 方法,而是从 Object 类继承基于身份的equalshashCode 方法。 


示例代码

package com.yulore.ex;

import java.util.ArrayDeque;
import java.util.Deque;

public class DequeTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Deque<Integer> mDeque = new ArrayDeque<Integer>();
		
		for(int i=0;i<5;i++){
			mDeque.offer(i);
		}
		
		System.out.println(mDeque.peek());
		
		System.out.println("***********集合方式遍历**********"); 
		
		//集合方式遍历,元素不会被移除 
        for (Integer x : mDeque) { 
                System.out.println(x); 
        } 
        
        System.out.println("**********遍历队列*************"); 
        
        //队列方式遍历,元素逐个被移除 
        while (mDeque.peek() != null) { 
                System.out.println(mDeque.poll()); 
        } 
        
        System.out.println("***********进栈操作************"); 
        
        mDeque.push(10);
        mDeque.push(15);
        mDeque.push(24);
        print(mDeque);
        
        System.out.println("*********出栈操作*************"); 
        
        System.out.println(mDeque.pop());
	}
	
	public static void print(Deque<Integer> queue){
		//集合方式遍历,元素不会被移除 
        for (Integer x : queue) { 
                System.out.println(x); 
        } 
	}
}






/* * 基于双向链表实现双端队列结构 */ 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
Java中,Deque(Double Ended Queue)是一种双端队列数据结构,可以在队列的两端进行插入和删除操作。Deque接口继承自Queue接口,并提供了更多的方法来支持双端操作。 要使用Deque,需要导入`java.util.Deque`包。以下是一些Deque接口中常用的方法: - `addFirst(element)`:将元素添加到双端队列的开头。 - `addLast(element)`:将元素添加到双端队列的末尾。 - `offerFirst(element)`:将元素添加到双端队列的开头,并返回是否成功。 - `offerLast(element)`:将元素添加到双端队列的末尾,并返回是否成功。 - `removeFirst()`:从双端队列的开头删除并返回第一个元素。 - `removeLast()`:从双端队列的末尾删除并返回最后一个元素。 - `pollFirst()`:从双端队列的开头删除并返回第一个元素,如果队列为空则返回null。 - `pollLast()`:从双端队列的末尾删除并返回最后一个元素,如果队列为空则返回null。 - `getFirst()`:获取双端队列的第一个元素,但不删除它。 - `getLast()`:获取双端队列的最后一个元素,但不删除它。 下面是一个使用Deque接口的示例: ```java import java.util.Deque; import java.util.LinkedList; public class DequeExample { public static void main(String[] args) { Deque<String> deque = new LinkedList<>(); // 在双端队列的开头和末尾插入元素 deque.addFirst("Hello"); deque.addLast("World"); // 获取并删除双端队列的第一个元素 String firstElement = deque.removeFirst(); System.out.println(firstElement); // 输出:Hello // 获取双端队列的最后一个元素 String lastElement = deque.getLast(); System.out.println(lastElement); // 输出:World } } ``` 在上述示例中,我们使用了LinkedList类实现了Deque接口。通过调用不同的方法,我们可以在双端队列的开头和末尾进行插入和删除操作。需要注意的是,LinkedList还可以作为普通队列或堆栈使用。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值