CS61B Project1-1: LinkedListDeque——复制粘贴就能运行,同时欢迎大家帮忙捉Bug

216 阅读2分钟

注意

测试启动类中,无参构造函数创建的deque和有参构造函数创建的deque测试,自己去修改。

接口

public interface Deque <T>{  
void addFirst(T item);  
void addLast(T item);  
  
boolean isEmpty();  
  
int size();  
  
void printDeque();  
  
T removeFirst();  
  
T removeLast();  
  
T get(int index);  
  
T getRecursive(int index);  
}

实现类

/**  
* 要求:  
* 1:接口方法不允许使用任何库实现  
* 2:使用泛型支持多种数据存储  
* 3:使用内嵌静态类,避免暴露使用者无需关注的细节  
* -----------------------------------------  
* 4:add相关方法,时间复杂度要求为O(1),不允许递归  
* 5:get方法,只允许使用遍历  
* 6:getRecursive方法,只允许递归  
* 7:size方法,时间复杂度要求为O(1)  
* 8:不允许在deque中保留未使用的引用类型  
* 9:实现深拷贝  
* -----------------------------------------  
* 注意: 确保有元素的时候,哨兵的前后指针均指向真正的节点  
*/  
public class LinkedListDeque<T> implements Deque<T>, Serializable{  
  
private T item;  
  
private GenericNode sentinelNode = new GenericNode();  
  
private int size = 0;  
  
public LinkedListDeque() {  
this.sentinelNode.prev = this.sentinelNode;  
this.sentinelNode.next = this.sentinelNode.prev;  
}  
  
public LinkedListDeque(T item) {  
this.sentinelNode.next = new GenericNode(item, this.sentinelNode.next, this.sentinelNode.next);  
this.sentinelNode.next.prev = this.sentinelNode;  
this.sentinelNode.next.next = this.sentinelNode;  
this.sentinelNode.prev = this.sentinelNode.next;  
this.size += 1;  
}  
  
public LinkedListDeque(LinkedListDeque<T> linkedListDeque) {  
  
LinkedListDeque<T> deepCopied = this.deepCopy(linkedListDeque);  
this.sentinelNode = deepCopied.sentinelNode;  
this.size = deepCopied.size;  
this.item = deepCopied.item;  
}  
  
private LinkedListDeque<T> deepCopy(LinkedListDeque<T> source) {  
ByteArrayOutputStream bos = null;  
ObjectOutputStream oos = null;  
  
ByteArrayInputStream bis = null;  
ObjectInputStream ois = null;  
  
LinkedListDeque<T> deepCopiedLinkedListDeque = null;  
try {  
  
//序列化  
bos = new ByteArrayOutputStream();  
oos = new ObjectOutputStream(bos);  
oos.writeObject(source);  
  
//反序列化  
bis = new ByteArrayInputStream(bos.toByteArray());  
ois = new ObjectInputStream(bis);  
deepCopiedLinkedListDeque = (LinkedListDeque<T>) ois.readObject();  
  
} catch (IOException | ClassNotFoundException e) {  
e.printStackTrace();  
} finally {  
try {  
bos.close();  
oos.close();  
bis.close();  
ois.close();  
} catch (IOException e) {  
e.printStackTrace();  
}  
}  
return deepCopiedLinkedListDeque;  
}  
  
@Override  
public void addFirst(T item) {  
this.sentinelNode.next = new GenericNode(item, this.sentinelNode.next, this.sentinelNode);  
this.sentinelNode.next.next.prev = this.sentinelNode.next;  
this.size += 1;  
}  
  
@Override  
public void addLast(T item) {  
this.sentinelNode.prev.next = new GenericNode(item, this.sentinelNode, this.sentinelNode.prev);  
this.sentinelNode.prev = this.sentinelNode.prev.next;  
this.size += 1;  
}  
  
@Override  
public boolean isEmpty() {  
return this.size == 0;  
}  
  
@Override  
public int size() {  
return this.size;  
}  
  
@Override  
public void printDeque() {  
GenericNode pointer = this.sentinelNode;  
while (pointer.next != this.sentinelNode) {  
pointer = pointer.next;  
System.out.printf(pointer.item + " ");  
}  
System.out.println();  
}  
  
@Override  
public T removeFirst() {  
if (this.size == 0) {  
return null;  
}  
  
T deletedItem = (T) this.sentinelNode.next.item;  
if (this.size > 1) {  
this.sentinelNode.next.next.prev = this.sentinelNode;  
this.sentinelNode.next = this.sentinelNode.next.next;  
} else {  
this.sentinelNode.next = this.sentinelNode;  
this.sentinelNode.prev = this.sentinelNode;  
}  
this.size -= 1;  
return deletedItem;  
}  
  
@Override  
public T removeLast() {  
if (this.size == 0) {  
return null;  
}  
T deletedItem = (T) this.sentinelNode.prev.item;  
this.sentinelNode.prev = this.sentinelNode.prev.prev;  
this.sentinelNode.prev.next = this.sentinelNode;  
this.size -= 1;  
return deletedItem;  
}  
  
@Override  
public T get(int index) {  
if (this.size == 0) {  
return null;  
}  
if (index >= this.size || index < 0) {  
System.out.println("Out of index range: " + index);  
return null;  
}  
GenericNode cursorNode = this.sentinelNode;  
  
for (int i = 0; i <= index; i++) {  
cursorNode = cursorNode.next;  
}  
  
return (T) cursorNode.item;  
}  
  
@Override  
public T getRecursive(int index) {  
if (this.size == 0) {  
return null;  
}  
  
if (index >= this.size || index < 0) {  
System.out.println("Out of index range: " + index);  
return null;  
}  
  
GenericNode cursorNode = this.sentinelNode;  
T item = this.getRecursive(index, cursorNode);  
return item;  
}  
  
private T getRecursive(int index, GenericNode cursorNode) {  
if (index < 0) {  
return (T) cursorNode.item;  
}  
return getRecursive(--index, cursorNode.next);  
  
}  
  
private static class GenericNode<T> implements Serializable{  
private T item;  
  
private GenericNode next;  
  
private GenericNode prev;  
  
public GenericNode(T item, GenericNode next, GenericNode prev) {  
this.item = item;  
this.next = next;  
this.prev = prev;  
}  
  
public GenericNode() {  
}  
}  
}

测试启动类

public class TestLinkedListDeque {  
public static void main(String[] args) {  
System.out.println("\nStart testing !\n");  
LinkedListDeque<String> linkedListDeque = testAddFirst();  
testAddLast(linkedListDeque);  
testSize(linkedListDeque);  
testPrintDeque(linkedListDeque);  
/*int size = linkedListDeque.size();  
for (int i = 0; i < size; i++) {  
System.out.println(linkedListDeque.isEmpty());  
if (linkedListDeque.size() == 0) {  
break;  
}  
testRemoveFirst(linkedListDeque);  
testRemoveLast(linkedListDeque);  
  
}  
testRemoveLast(linkedListDeque);*/  
  
testGet(linkedListDeque,8);  
  
//assert = Element-2  
testGet(linkedListDeque,3);  
  
//assert = tail-4  
testGet(linkedListDeque,7);  
  
testGet(linkedListDeque,1);  
testGet(linkedListDeque,9);  
linkedListDeque.printDeque();  
  
testGet(linkedListDeque,-1);  
testGet(linkedListDeque,0);  
testGet(linkedListDeque,10);  
testMixingAddFirstLast();  
  
  
  
//  
System.out.println("Recursively get test: ");  
//assert = Element-2  
testGetRecursive(linkedListDeque,3);  
  
//assert = tail-4  
testGetRecursive(linkedListDeque,7);  
  
//assert = E4  
testGetRecursive(linkedListDeque,1);  
testGetRecursive(linkedListDeque,9);  
  
// assert = t2  
testGetRecursive(linkedListDeque,5);  
linkedListDeque.printDeque();  
  
testGetRecursive(linkedListDeque,-2);  
testGetRecursive(linkedListDeque,0);  
testGetRecursive(linkedListDeque,11);  
  
LinkedListDeque<String> deepCopied = testDeepCopy(linkedListDeque);  
  
deepCopied.removeLast();  
deepCopied.addFirst("deep-copied");  
deepCopied.addLast("deep-copied-tail");  
  
System.out.println("Testing deep copy : ");  
deepCopied.printDeque();  
linkedListDeque.printDeque();  
  
System.out.println(Objects.equals(deepCopied.get(1), linkedListDeque.get(1)));  
  
  
}  
  
private static LinkedListDeque<String> testAddFirst() {  
LinkedListDeque<String> stringLinkedListDeque = new LinkedListDeque<>(/*"Element-1"*/);  
stringLinkedListDeque.addFirst("Element-2");  
stringLinkedListDeque.addFirst("Element-3");  
stringLinkedListDeque.addFirst("Element-4");  
stringLinkedListDeque.addFirst("Element-5");  
System.out.println("Complete testing addFirst!");  
return stringLinkedListDeque;  
}  
  
private static <T> void testSize(LinkedListDeque<T> linkedListDeque) {  
System.out.println("LinkedListDeque size : "+ linkedListDeque.size());  
}  
  
private static void testAddLast(LinkedListDeque<String> linkedListDeque) {  
linkedListDeque.addLast("tail-1");  
linkedListDeque.addLast("tail-2");  
linkedListDeque.addLast("tail-3");  
linkedListDeque.addLast("tail-4");  
System.out.println("Complete testing addLast!");  
}  
  
private static void testMixingAddFirstLast() {  
LinkedListDeque<String> stringLinkedListDeque = new LinkedListDeque<>(/*"Element-1"*/);  
stringLinkedListDeque.addLast("tail-5");  
stringLinkedListDeque.addFirst("Element-2");  
stringLinkedListDeque.addFirst("Element-3");  
stringLinkedListDeque.addLast("tail-2");  
stringLinkedListDeque.addLast("tail-3");  
stringLinkedListDeque.addFirst("Element-4");  
stringLinkedListDeque.addFirst("Element-5");  
stringLinkedListDeque.addLast("tail-6");  
  
//Expected: e5 e4 e3 e2 e1 t5 t2 t3 t6  
stringLinkedListDeque.printDeque();  
}  
private static <T> void testPrintDeque(LinkedListDeque<T> linkedListDeque) {  
linkedListDeque.printDeque();  
}  
  
private static <T> void testRemoveFirst(LinkedListDeque<T> linkedListDeque) {  
System.out.println("Removed: " + linkedListDeque.removeFirst());  
linkedListDeque.printDeque();  
}  
  
private static <T> void testRemoveLast(LinkedListDeque<T> linkedListDeque) {  
System.out.println("Removed: " + linkedListDeque.removeLast());  
linkedListDeque.printDeque();  
}  
  
private static <T> void testGet(LinkedListDeque<T> linkedListDeque,int index) {  
System.out.println(linkedListDeque.get(index));  
}  
  
private static <T> void testGetRecursive(LinkedListDeque<T> linkedListDeque,int index) {  
System.out.println(linkedListDeque.getRecursive(index));  
}  
  
private static <T> LinkedListDeque<T> testDeepCopy(LinkedListDeque<T> linkedListDeque) {  
return new LinkedListDeque<>(linkedListDeque);  
}  
}