注意
测试启动类中,无参构造函数创建的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);
}
}