算法-第四版-练习1.3.33解答
问题
Deque。一个双向队列(或者称为deque)和栈或队列类似,但它同时支持在两端添加或删除元素。Deque能够存储一组元素并支持如下API。
/** * ----------------------------------------------------- * public class Deque<Item> implements Iterable<Item> * ----------------------------------------------------- * Deque() 创建空双向队列 * boolean isEmpty() 双向队列是否为空 * int size() 双向队列中元素的数量 * void pushLeft(Item item) 向左端添加一个新元素 * void pushRight(Item item) 向右端添加一个新元素 * Item popLeft() 从左羰删除一个元素 * Item popRight() 从右羰删除一个元素 * ----------------------------------------------------- */编写一个使用双向链表实现这份API的Deque类。以及一个使用动态数据组调整实现这份API的ResizingArrayDeque类。
解决思路
该问题解决起来并不难。使用双向链表时需要注意每个结点的双向引用,不要只添加单向的引用或者只删除单向的引用。使用动态数组时注意,何时调整数组的大小以及将数组大小调整为多大。本实现添加元素时,只有在头部或者尾部没有空间时,才进行调整,调整为队列中元素的个数的3倍,前后各留队列中元素个数的长度。在删除元素,当元素的数量小于总长度的1/6时,进行调整,将长度调整为元素个数的3倍,同样前后各留元素个数的长度。注意最小不小于3。
代码
一共三个文件,分别为Deque类,ResizingArrayDeque类和测试文件E10333类。
Deque类。
package com.furzoom.lab.algs.ch103;
import java.util.Iterator;
/**
* -----------------------------------------------------
* public class Deque<Item> implements Iterable<Item>
* -----------------------------------------------------
* Deque() 创建空双向队列
* boolean isEmpty() 双向队列是否为空
* int size() 双向队列中元素的数量
* void pushLeft(Item item) 向左端添加一个新元素
* void pushRight(Item item) 向右端添加一个新元素
* Item popLeft() 从左羰删除一个元素
* Item popRight() 从右羰删除一个元素
* -----------------------------------------------------
*/
public class Deque<Item> implements Iterable<Item> {
private Node head = null;
private Node tail = null;
private int size = 0;
private class Node {
public Item item;
public Node prev;
public Node next;
}
public boolean isEmpty() {
return head == null;
}
public int size() {
return size;
}
public void pushLeft(Item item) {
Node node = new Node();
node.item = item;
node.prev = null;
if (isEmpty()) {
head = tail = node;
node.next = null;
} else {
head.prev = node;
node.next = head;
head = node;
}
size++;
}
public void pushRight(Item item) {
Node node = new Node();
node.item = item;
node.next = null;
if (isEmpty()) {
head = tail = node;
node.prev = null;
} else {
tail.next = node;
node.prev = tail;
tail = node;
}
size++;
}
public Item popLeft() {
if (isEmpty()) {
return null;
} else {
Item e = head.item;
if (size() == 1) {
head = tail = null;
} else {
head = head.next;
head.prev.next = null;
head.prev = null;
}
size--;
return e;
}
}
public Item popRight() {
if (isEmpty()) {
return null;
} else {
Item e = tail.item;
if (size() == 1) {
head = tail = null;
} else {
tail = tail.prev;
tail.next.prev = null;
tail.next = null;
}
size--;
return e;
}
}
@Override
public Iterator<Item> iterator() {
return new Iter();
}
private class Iter implements Iterator<Item> {
private Node current = head;
@Override
public boolean hasNext() {
return current != null;
}
@Override
public Item next() {
Item e = current.item;
current = current.next;
return e;
}
}
}
ResizingArrayDeque类。
package com.furzoom.lab.algs.ch103;
import java.util.Iterator;
public class ResizingArrayDeque<Item> implements Iterable<Item> {
private int head;
private int tail;
private Item[] deque;
@SuppressWarnings("unchecked")
public ResizingArrayDeque() {
deque = (Item[])new Object[3];
head = 1;
tail = 1;
}
public boolean isEmpty() {
return head == tail;
}
public int size() {
return tail - head;
}
public void pushLeft(Item item) {
if (head == 0) {
resize(3 * size());
}
deque[--head] = item;
}
public void pushRight(Item item) {
if (tail == deque.length) {
resize(3 * size());
}
deque[tail++] = item;
}
public Item popLeft() {
if (isEmpty()) {
return null;
}
if (size() * 6 < deque.length) {
resize(size() * 3);
}
return deque[head++];
}
public Item popRight() {
if (isEmpty()) {
return null;
}
if (size() * 6 < deque.length) {
resize(size() * 3);
}
return deque[--tail];
}
@SuppressWarnings("unchecked")
private void resize(int size) {
if (size < 3) {
size = 3;
}
Item tmp[] = (Item[])new Object[size];
int j = size / 3;
for (int i = head; i < tail; i++) {
tmp[j++] = deque[i];
}
deque = tmp;
head = size / 3;
tail = j;
}
@Override
public Iterator<Item> iterator() {
return new Iter();
}
private class Iter implements Iterator<Item> {
private int current = head;
@Override
public boolean hasNext() {
return current < tail;
}
@Override
public Item next() {
Item e = deque[current++];
return e;
}
}
}
测试代码:
package com.furzoom.lab.algs.ch103;
import java.util.Iterator;
public class E10333 {
public static void main(String[] args) {
// Deque<String> deque = new Deque<String>();
ResizingArrayDeque<String> deque = new ResizingArrayDeque<String>();
deque.pushLeft("c");
deque.pushLeft("b");
deque.pushRight("d");
deque.pushRight("e");
System.out.println("deque size: " + deque.size());
Iterator<String> it = deque.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("Pop up from right: ");
while (!deque.isEmpty()) {
System.out.println(deque.popRight());
}
deque.pushLeft("c");
deque.pushLeft("b");
deque.pushRight("d");
deque.pushRight("e");
System.out.println("Pop up from left: ");
while (!deque.isEmpty()) {
System.out.println(deque.popLeft());
}
}
}
结果
deque size: 4 b c d e Pop up from right: e d c b Pop up from left: b c d e
作者:马 岩(Furzoom) (http://www.cnblogs.com/furzoom/)
版权声明:本文的版权归作者与博客园共同所有。转载时请在明显地方注明本文的详细链接,未经作者同意请不要删除此段声明,感谢您为保护知识产权做出的贡献。
版权声明:本文的版权归作者与博客园共同所有。转载时请在明显地方注明本文的详细链接,未经作者同意请不要删除此段声明,感谢您为保护知识产权做出的贡献。

浙公网安备 33010602011771号