java 双端队列应用实例_双端队列,java语言描述并带类库分析.

双端队列

双端队列其实就是两边都可以进出,不再局限于先进先出。

双端队列的接口

public interface DequeInterface { // 名字与java自身类库稍有不同,功能类似

public void addToFront(T newEntry);

public void addToBack(T newEntry);

public T removeFront();

public T removeBack();

public T getFront();

public T getBack();

public boolean isEmpty();

public void clear();

public int size();

}

我们选择使用双向链表实现双端队列。为了简单起见,我先使用LinkedList来实现这个接口以便读者了解各个方法,然后逐渐转化成自己手写的Deque.,LinkedList既是双向链表.

实现接口的类

import java.util.LinkedList;

/**

* Description:

*

* @ClassName: 双向链表/LinkedList实现双端队列。

* @author 过道

* @date 2018年8月14日 上午9:10:57

*/

public class LinkedDeque implements DequeInterface {

private LinkedList list;

public LinkedDeque() {

// 初始化链表

list = new LinkedList();

}

@Override

public void addToFront(T newEntry) {

// 从队列的头部近入

list.addFirst(newEntry);

}

@Override

public void addToBack(T newEntry) {

// 从队列的尾部近入

list.addLast(newEntry);

}

@Override

public T removeFront() {

// 移除首位元素

return list.removeFirst();

}

@Override

public T removeBack() {

// 移除尾部元素

return list.removeLast();

}

@Override

public T getFront() {

// 类似于peek(),将首位元素返回,不进行操作。

return list.getFirst();

}

@Override

public T getBack() {

// 得到尾部元素,不进行操作

return list.getLast();

}

@Override

public boolean isEmpty() {

// 容量,可以选择size==0,也可以直接调用siEmpty

return list.isEmpty();

}

@Override

public void clear() {

// 清空即可

list.clear();

}

@Override

public int size() {

return list.size();

}

}

接下来的任务就很清楚了,自定义一个双向链表,替换掉LinkedList。

定义Node类

class Node {

T data;

Node prev;//指向前一节点

Node next;//指向后一节点

public Node(T data, Node prev, Node next) {

this.data = data;

this.prev = prev;

this.next = next;

}

public Node(T data) {

this(data, null, null);

}

}

其实,现在问题就是如何实现双向链表,用自己的双向链表替换掉LinkedList即可.

用到的各个字段,构造器

// 使用一个值保存头结点,一个保存尾结点。 没有必要使用循环链表,因为判断起来比较麻烦。

private Node first;

private Node last;

int size;

public LinkedDeque() {

// 初始化链表

// list = new LinkedList();

// 初始化属性

first = null;

last = null;

size = 0; // 虽然有默认初始化,此处仍需初始化,养成一个好的编码习惯

}

各种方法实现

@Override

public void addToFront(T newEntry) {

// 从队列的头部近入

Node newNode = new Node(newEntry);

if (isEmpty()) {

// 尾结点也是头结点 头结点也是尾结点

last = newNode;

} else {

// 新节点与首节点建立双向链接

first.prev = newNode;

newNode.next = first;

}

first = newNode;

size++;

// list.addFirst(newEntry);

}

@Override

public void addToBack(T newEntry) {

// 从队列的尾部近入

Node newNode = new Node(newEntry);

if (isEmpty()) {

// 尾结点也是头结点 头结点也是尾结点

first = newNode;

} else {

// 新节点与尾节点建立双向链接

newNode.prev = last;

last.next = newNode;

}

last = newNode;

size++;

// 从队列的尾部近入

// list.addLast(newEntry);

}

@Override

public T removeFront() {

// 移除首位元素

// return list.removeFirst();

if (isEmpty()) {

// 抛出异常

}

Node front = first;

// 首节点后移

first = first.next;

if (first == null) {

last = null;

} else {

// 断开双向链接

first.prev = null;

front.next = null;

}

size--;

return front.data;

}

@Override

public T removeBack() {

if (isEmpty()) {

// 抛出异常

}

Node back = last;

last = last.prev;

if (last == null) {

first = null;

} else {

// 断开双向链接

last.next = null;

back.prev = null;

}

size--;

return back.data;

// 移除尾部元素

// return list.removeLast();

}

@Override

public T getFront() {

// 类似于peek(),将首位元素返回,不进行操作。

// return list.getFirst();

if (isEmpty()) {

// 抛出异常

}

return first.data;

}

@Override

public T getBack() {

// 得到尾部元素,不进行操作

// return list.getLast();

if (isEmpty()) {

// 抛出异常

}

return last.data;

}

@Override

public boolean isEmpty() {

// 容量,可以选择size==0,也可以直接调用siEmpty

// return list.isEmpty();

// 当first 和 back 都为空时,双向链表为空

return (first == null) && (last == null);

}

@Override

public void clear() {

// 双向链表实现,必须考虑两个对象相互引用的情况,如果出现,那么GC就不会清理这个内存,从而导致内存泄漏。

// 所以我们需要遍历链表并将其置为null

for (Node x = first; x != null && x != last;) {

Node next = x.next;

x.data = null;

x.next = null;

x.prev = null;

x = next;

}

first = last = null;

size = 0;

// 清空即可

// list.clear();

}

@Override

public int size() {

return size;

// return list.size();

}

所有源码

package unit10.queue;

import java.util.LinkedList;

/**

* Description:

*

* @ClassName: 双向链表实现双端队列。

* @author 过道

* @date 2018年8月14日 上午9:10:57

*/

public class LinkedDeque implements DequeInterface {

// private LinkedList list;

// 使用一个值保存头结点,一个保存尾结点。 没有必要使用循环链表,因为判断起来比较麻烦。

private Node first;

private Node last;

int size;

public LinkedDeque() {

// 初始化链表

// list = new LinkedList();

// 初始化属性

first = null;

last = null;

size = 0; // 虽然有默认初始化,此处仍需初始化,养成一个好的编码习惯

}

@Override

public void addToFront(T newEntry) {

// 从队列的头部近入

Node newNode = new Node(newEntry);

if (isEmpty()) {

// 尾结点也是头结点 头结点也是尾结点

last = newNode;

} else {

// 新节点与首节点建立双向链接

first.prev = newNode;

newNode.next = first;

}

first = newNode;

size++;

// list.addFirst(newEntry);

}

@Override

public void addToBack(T newEntry) {

// 从队列的尾部近入

Node newNode = new Node(newEntry);

if (isEmpty()) {

// 尾结点也是头结点 头结点也是尾结点

first = newNode;

} else {

// 新节点与尾节点建立双向链接

newNode.prev = last;

last.next = newNode;

}

last = newNode;

size++;

// 从队列的尾部近入

// list.addLast(newEntry);

}

@Override

public T removeFront() {

// 移除首位元素

// return list.removeFirst();

if (isEmpty()) {

// 抛出异常

}

Node front = first;

// 首节点后移

first = first.next;

if (first == null) {

last = null;

} else {

// 断开双向链接

first.prev = null;

front.next = null;

}

size--;

return front.data;

}

@Override

public T removeBack() {

if (isEmpty()) {

// 抛出异常

}

Node back = last;

last = last.prev;

if (last == null) {

first = null;

} else {

// 断开双向链接

last.next = null;

back.prev = null;

}

size--;

return back.data;

// 移除尾部元素

// return list.removeLast();

}

@Override

public T getFront() {

// 类似于peek(),将首位元素返回,不进行操作。

// return list.getFirst();

if (isEmpty()) {

// 抛出异常

}

return first.data;

}

@Override

public T getBack() {

// 得到尾部元素,不进行操作

// return list.getLast();

if (isEmpty()) {

// 抛出异常

}

return last.data;

}

@Override

public boolean isEmpty() {

// 容量,可以选择size==0,也可以直接调用siEmpty

// return list.isEmpty();

// 当first 和 back 都为空时,双向链表为空

return (first == null) && (last == null);

}

@Override

public void clear() {

// 双向链表实现,必须考虑两个对象相互引用的情况,如果出现,那么GC就不会清理这个内存,从而导致内存泄漏。

// 所以我们需要遍历链表并将其置为null

for (Node x = first; x != null && x != last;) {

Node next = x.next;

x.data = null;

x.next = null;

x.prev = null;

x = next;

}

first = last = null;

size = 0;

// 清空即可

// list.clear();

}

@Override

public int size() {

return size;

// return list.size();

}

class Node {

T data;

Node prev;

Node next;

public Node(T data, Node prev, Node next) {

this.data = data;

this.prev = prev;

this.next = next;

}

public Node(T data) {

this(data, null, null);

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值