算法-第四版-练习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




posted @ 2017-10-22 15:50  枫竹梦  阅读(254)  评论(0编辑  收藏  举报