public class ArrayStack<Item> implements MyStack<Item> {// 棧元素數組,只能通過轉型來創建泛型數組private Item[] a = (Item[]) new Object[1];// 元素數量private int N = 0;@Overridepublic MyStack<Item> push(Item item) {check();a[N++] = item;return this;}@Overridepublic Item pop() throws Exception {if (isEmpty()) {throw new Exception("stack is empty");}Item item = a[--N];check();// 避免對象游離a[N] = null;return item;}private void check() {if (N >= a.length) {resize(2 * a.length);} else if (N > 0 && N <= a.length / 4) {resize(a.length / 2);}}/*** 調整數組大小,使得棧具有伸縮性*/private void resize(int size) {Item[] tmp = (Item[]) new Object[size];for (int i = 0; i < N; i++) {tmp[i] = a[i];}a = tmp;}@Overridepublic boolean isEmpty() {return N == 0;}@Overridepublic int size() {return N;}@Overridepublic Iterator<Item> iterator() {// 返回逆序遍歷的迭代器return new Iterator<Item>() {private int i = N;@Overridepublic boolean hasNext() {return i > 0;}@Overridepublic Item next() {return a[--i];}};}
}
數組實現,通過N 來統計最后一個是啥子。然后既可以進行add和remove了
2. 鏈表實現 需要使用鏈表的頭插法來實現,因為頭插法中最后壓入棧的元素在鏈表的開頭,它的 next 指針指向前一個壓入棧的元素,在彈出元素時就可以通過 next 指針遍歷到前一個壓入棧的元素從而讓這個元素成為新的棧頂元素。 ** 新加入的元素成為第一個節點first**
public class ListStack<Item> implements MyStack<Item> {private Node top = null;private int N = 0;private class Node {Item item;Node next;}@Overridepublic MyStack<Item> push(Item item) {Node newTop = new Node();newTop.item = item;newTop.next = top;top = newTop;N++;return this;}@Overridepublic Item pop() throws Exception {if (isEmpty()) {throw new Exception("stack is empty");}Item item = top.item;top = top.next;N--;return item;}@Overridepublic boolean isEmpty() {return N == 0;}@Overridepublic int size() {return N;}@Overridepublic Iterator<Item> iterator() {return new Iterator<Item>() {private Node cur = top;@Overridepublic boolean hasNext() {return cur != null;}@Overridepublic Item next() {Item item = cur.item;cur = cur.next;return item;}};}
}
隊列
下面是隊列的鏈表實現,需要維護 first 和 last 節點指針,分別指向隊首和隊尾。
這里需要考慮 first 和 last 指針哪個作為鏈表的開頭。因為出隊列操作需要讓隊首元素的下一個元素成為隊首,所以需要容易獲取下一個元素,而鏈表的頭部節點的 next 指針指向下一個元素,因此可以讓 first 指針鏈表的開頭。 因為隊列是先進先出,進去的在后面,出來的是從前面出來的。所以說需要兩個指針
public interface MyQueue<Item> extends Iterable<Item> {int size();boolean isEmpty();MyQueue<Item> add(Item item);Item remove() throws Exception;
}
public class ListQueue<Item> implements MyQueue<Item> {private Node first;private Node last;int N = 0;private class Node {Item item;Node next;}@Overridepublic boolean isEmpty() {return N == 0;}@Overridepublic int size() {return N;}@Overridepublic MyQueue<Item> add(Item item) {Node newNode = new Node();newNode.item = item;newNode.next = null;if (isEmpty()) {last = newNode;first = newNode;} else {last.next = newNode;last = newNode;}N++;return this;}@Overridepublic Item remove() throws Exception {if (isEmpty()) {throw new Exception("queue is empty");}Node node = first;first = first.next;N--;if (isEmpty()) {last = null;}return node.item;}@Overridepublic Iterator<Item> iterator() {return new Iterator<Item>() {Node cur = first;@Overridepublic boolean hasNext() {return cur != null;}@Overridepublic Item next() {Item item = cur.item;cur = cur.next;return item;}};}
}