Deque
●queue 是一種數據結構,該數據結構允許在隊頭添加節點,然後在隊尾刪除一個項,以實現先進先出(FIFO)。
●在這個實驗中,我們將創建一個更通用的數據結構,稱爲 deque,是雙端隊列的縮寫。
●在一個 deque 中,您可以添加和刪除兩端的項(無論是其前端還是後端)。
○在本實驗室,您將完成包括添加和刪除在內的許多方法。
●此外,您必須使用通用類型,以便可以實例化 deque 來存儲任何類型的對象。
我們將使用鏈表實現一個 deque,特別是循環鏈表。
1. LLDeque EMPTY CONSTRUCTOR
●完成空的 deque 構造函數 public LLDeque()
●它創造了一個空的 deque
2. LLDeque ADD TO FRONT
●完成方法 void addFirst(T item)。
●它將一個 T 型 item 添加到 deque 的前部。
●不得使用任何循環或遞歸。
●每次操作必須持續時間,即不取決於 deque 的 size。
提示:
●我們需要創建一個新節點,並將其立即放置在哨兵旁邊
使用輸入項創建一個新節點,其上一個點指向哨兵,下一個點指向哨兵之後的舊節點
●設置哨兵後舊節點的 prev 指向新節點
●設置下一個哨兵指向新節點
●增大 size
3. LLDeque PRINT ITEMS
●完成方法 void printDeque()
●它將 deque 中的項目從頭到尾 print 出來,用空格隔開,以新行結束。
提示:
●我們需要檢查每一項並 print 出來
●項目從哨兵旁邊開始,因此設置一個指針 p 指向它
●當 p 不返回哨兵時 ○使用 Print(非 println)print p 所指節點內的 item ○添加 spacebar ○移動 p 以指向下一個節點
●使用 println 添加新行
4. LLDeque ITERATIVE GET ITEM
●迭代完成方法 T iterGet(int index)。
●它返回給定索引處的項,其中索引 0 是前端。如果不存在此類項,則返回 null。
●它必須使用循環,而不是遞歸。
●不得使 deque 突變。
提示:
●如果 deque 爲空,或者索引無效(負數、大於或等於),則返回 null
●創建一個從哨兵的下一個開始的節點指針 p
●使用 for/while 移動指向 index-th 節點的指針
●返回 p 所指節點內的 item
5. LLDeque ADD TO BACK
●完成方法 void addLast(T item)。
●它在 deque 後面添加了一個 T 類型的 item。
●它不能使用任何循環或遞歸。
●每次操作必須持續時間,即不取決於 deque 的大小。
6. LLDeque DELETE FRONT
●完成方法 T delFirst()。
●刪除並返回 deque 前面的項,如果不存在,則返回空。
●不得使用任何循環或遞歸。
●每次操作必須持續一段時間,即不取決於 deque 的大小。
7. LLDeque DELETE BACK
●完成方法 T delLast()。
●刪除並返回 deque 後面的項,如果不存在,則返回空。
●不得使用任何循環或遞歸。
●每次操作必須持續時間,即不取決於 deque 的大小。
8. LLDeque RECURSIVE GET ITEM
●遞歸地完成方法 T recGet(int index)。
●它返回給定索引處的項,其中索引 0 是前端。如果不存在此類項,則返回 null。
●不得使用循環。
●不得使 deque 突變。
上代碼:
public class LLDeque<T> {
private class Node {
Node prev;
T item;
Node next;
Node(Node p, T i, Node n) {
prev = p;
item = i;
next = n;
}
}
private Node sentinel;
private int size;
/**
* @return the number of items in the deque.
*/
public int size() {
return size;
}
/**
* @return true if deque is empty, false otherwise.
*/
public boolean isEmpty() {
return size == 0;
}
/*
***************************
* DO NOT MODIFY CODE ABOVE
***************************
*/
// EXERCISE 8.1 EMPTY CONSTRUCTOR
/**
* Creates an empty deque.
*/
public LLDeque() {
this.size = 0;
Node head = new Node(null, null, null);
head.prev = head;
head.next = head;
this.sentinel = head.next;
}
// EXERCISE 8.2 ADD TO FRONT
/**
* Adds an item of type T to the front of the deque.
* @param item is a type T object added to the deque.
*/
public void addFirst(T item) {
Node newNode = new Node(null, item, null);
newNode.prev = this.sentinel;
newNode.next = this.sentinel.next;
this.sentinel.prev = newNode.next;
this.sentinel.next = newNode;
this.size += 1;
}
// EXERCISE 8.3 PRINT ITEMS
/**
* Prints the items in the deque from first to last,
* separated by a space, ended with a new line.
*/
public void printDeque() {
Node p = this.sentinel.next;
while(p!=this.sentinel) {
System.out.print(p.item);
if(p.next!=this.sentinel) System.out.print(" ");
p = p.next;
}
System.out.print("\n");
}
// EXERCISE 8.4 ITERATIVE GET ITEM
/**
* Gets the item at the given index.
* If no such item exists, returns null.
* Does not mutate the deque.
* @param index is an index where 0 is the front.
* @return the ith item of the deque, null if it does not exist.
*/
public T iterGet(int index) {
if(this.sentinel==null||this.size<=0||index<0||index>=this.size) return null;
Node p = this.sentinel.next;
for(int i=0;i<=index;i++) {
if(index==i) return p.item;
p = p.next;
}
return null;
}
// ASSIGNMENT 8.1 ADD TO BACK
/**
* Adds an item of type T to the back of the deque.
* @param item is a type T object added to the deque.
*/
public void addLast(T item) {
Node newNode = new Node(null, item, null);
newNode.prev = this.sentinel.prev;
this.sentinel.prev.next = newNode;
this.sentinel.prev = newNode;
newNode.next = this.sentinel;
this.size += 1;
}
// ASSIGNMENT 8.2 DELETE FRONT
/**
* Deletes and returns the item at the front of the deque.
* If no such item exists, returns null.
* @return the first item of the deque, null if it does not exist.
*/
public T delFirst() {
if(this.sentinel==null||this.size<=0) {
return null;
}
T target = this.sentinel.next.item;
Node f1rst = this.sentinel.next;
Node next = this.sentinel.next.next;
next.prev = this.sentinel;
this.sentinel.next = next;
f1rst.next = null;
f1rst.prev = null;
this.size -= 1;
return target;
}
// ASSIGNMENT 8.3 DELETE BACK
/**
* Deletes and returns the item at the back of the deque.
* If no such item exists, returns null.
* @return the last item of the deque, null if it does not exist.
*/
public T delLast() {
if(this.sentinel==null||this.size<=0) {
return null;
}
Node last2Node = this.sentinel.prev.prev;
Node targetNode = this.sentinel.prev;
T target = targetNode.item;
last2Node.next = this.sentinel;
this.sentinel.prev = last2Node;
targetNode.next = null;
targetNode.prev = null;
return target;
}
// ASSIGNMENT 8.4 RECURSIVE GET ITEM
/**
* Gets the item at the given index.
* If no such item exists, returns null.
* Does not mutate the deque.
* @param index is an index where 0 is the front.
* @return the ith item of the deque, null if it does not exist.
*/
public T recGet(int index) {
return recHelper(index, 0, this.sentinel.next);
}
private T recHelper(int index,int now,Node n) {
if(this.sentinel==null||this.size<=0||index<0||index>=this.size) return null;
if(now==index) return n.item;
return recHelper(index, now+1, n.next);
}
public static void main(String[] args) {
LLDeque<String> deque = new LLDeque<>();
deque.addFirst("b");
deque.addFirst("a");
deque.printDeque();
}
}