一、隊列: 先進先出(FIFO),例如超市的收銀臺、排隊買票的顧客。在Java中,它和List的區別在於,List能夠在任意位置添加和刪除元素,而Queue只有兩個操做:java
二、棧: 下壓棧,後進先出(LIFO),例如你辦公桌上的一疊信件,新信件來時將它們放在最上面(push方法),當閱讀時從上到下取件(pop方法)。node
三、雙棧算術表達式求值:
例如計算(1+((2+3)*(4*5)))
的值:用兩個棧,一個保存運算符(運算符棧),一個保存數字(操做數棧)。算法
從左到右逐個將實體送入棧處理:
一、遇到數字時,將數字壓入操做數棧,遇到運算法時,壓入運算符棧;
二、遇到左括號時忽略;
三、遇到右括號,彈出一個運算符,彈出所需數量的數字,並將運算符和數字的運算結果壓入操做數棧。數組
雙棧算術表達式求值算法(爲了代碼簡潔未考慮異常):數據結構
import java.util.Stack; public class EvaluateTest { public static void main(String[] args) { // 須要計算的表達式 String str = "(1+((2+3)*(4*5)))".trim(); // 運算符棧和操做數棧 Stack<String> ops = new Stack<>(); Stack<Double> vals = new Stack<>(); for(int i=0;i < str.length();i++) { String s = String.valueOf(str.charAt(i)); if(s.equals("(")){ // 左括號時忽略 }else if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/") || s.equals("sqrt")){ // 運算符時壓運算符棧 ops.push(s); }else if(s.equals(")")){ // 右括號時,將兩個棧都pop,再計算、壓棧 String op = ops.pop(); Double v = vals.pop(); if(op.equals("+")){ v = vals.pop() + v; }else if(op.equals("-")){ v = vals.pop() - v; }if(op.equals("*")){ v = vals.pop() * v; }if(op.equals("/")){ v = vals.pop() / v; }if(op.equals("sqrt")){ v = Math.sqrt(v); } vals.push(v); }else{ // 最後是數字時,轉爲double壓入操做數棧 vals.push(Double.valueOf(s)); } } System.out.println("最終運算結果:" + vals.pop()); } }
四、鏈表
鏈表是一種遞歸的數據結構,它能夠爲空(null),能夠是指向一個節點(node)的引用。該節點包含一個元素(數據域,儲存節點含有的信息)和一個指向另外一條鏈表或節點的引用(引用域)。lua
鏈表的特色:3d
- 插入和刪除元素方便;
- 查找數據時效率低,訪問某個位置的數據要從第一個節點開始訪問,根據第一個節點保存的下一個節點的地址找到第二個節點,以此類推;
能夠看完下面的流程再來理解它的特色。這裏主要介紹單向鏈表:code
// 一個節點 public class Node { public Object item; public Node next; }
僞代碼構造一條鏈表:
對象
建立好鏈表後,在表頭插入一個節點很容易,以下圖,若是在表頭插入字符串"not",先將first保存在oldfirst中,而後將一個新節點賦給first,並將它的item元素設爲not,next設爲oldfirst。
blog
在表頭刪除一個節點,將first指向first.next便可。曾經的第一個節點對象變成了一個孤兒,Java的內存管理最終將回收它所佔用的內存:
請注意:當鏈表中只有一個節點時,它既是首節點又是尾節點,另外注意鏈表爲空的狀況。
那麼在表尾插入節點能夠表示爲:
之前鏈表操做只須要幾行賦值代碼,所需時間和鏈表的長度無關。但若是須要刪除表尾節點,就要遍歷整條鏈表並找出指向last節點的節點,這樣所需的時間和鏈表的長度成正比。
要想實現任意插入和刪除操做,可使用雙向鏈表,這裏不做介紹。
五、遍歷鏈表 咱們知道遍歷數組能夠用for(int i = 0; i < N; i++){...}
;那麼遍歷鏈表也有一個對應方式:
for (Node x = first; x != null; x = x.next) { // 處理 x.item }
六、堆棧的鏈表實現
直接上代碼:
import java.util.Iterator; import java.util.NoSuchElementException; public class Stack<Item> implements Iterable<Item> { private Node<Item> first; // 棧頂(最近添加的元素) private int n; // 元素數量 private static class Node<Item> { private Item item; private Node<Item> next;// 定義了節點的嵌套類 } /** * Initializes an empty stack. */ public Stack() { first = null; n = 0; } /** * 當first==null或者n==0時,棧是空的 */ public boolean isEmpty() { return first == null; } public int size() { return n; } /** * 向棧頂添加元素 */ public void push(Item item) { Node<Item> oldfirst = first; first = new Node<Item>(); first.item = item; first.next = oldfirst; n++; } /** * 從棧頂刪除元素 */ public Item pop() { if (isEmpty()) throw new NoSuchElementException("Stack underflow"); Item item = first.item; first = first.next; n--; return item; } /** * 只取值,不刪除 */ public Item peek() { if (isEmpty()) throw new NoSuchElementException("Stack underflow"); return first.item; } /** * 按照LIFO的順序,返回一個迭代器能夠迭代此類 */ public Iterator<Item> iterator() { return new LinkedIterator(first); } private class LinkedIterator implements Iterator<Item> { private Node<Item> current; public LinkedIterator(Node<Item> first) { current = first; } public boolean hasNext() { return current != null; } public void remove() { throw new UnsupportedOperationException(); } public Item next() { if (!hasNext()) throw new NoSuchElementException(); Item item = current.item; current = current.next; return item; } } }
七、隊列的鏈表實現
Queue的實現使用的數據結構和Stack類相同,都是鏈表,但它實現了不一樣的添加和刪除算法,這也是FIFO和LIFO的區別所在。
import java.util.Iterator; import java.util.NoSuchElementException; public class Queue<Item> implements Iterable<Item> { private Node<Item> first; // 指向最先添加的節點的引用 private Node<Item> last; // 隊尾,最近添加 private int n; private static class Node<Item> { private Item item; private Node<Item> next; } public Queue() { first = null; last = null; n = 0; } public boolean isEmpty() { return first == null; } public int size() { return n; } /** * 向表尾添加元素 */ public void enqueue(Item item) { Node<Item> oldlast = last; last = new Node<Item>(); last.item = item; last.next = null; if (isEmpty()){ first = last; }else{ oldlast.next = last; } n++; } /** * 從表頭刪除元素 */ public Item dequeue() { if (isEmpty()) throw new NoSuchElementException("Queue underflow"); Item item = first.item; first = first.next; n--; if (isEmpty()) last = null; return item; } /** * 從表頭獲取元素,不刪除 */ public Item peek() { if (isEmpty()) throw new NoSuchElementException("Queue underflow"); return first.item; } public Iterator<Item> iterator() { return new LinkedIterator(first); } private class LinkedIterator implements Iterator<Item> { private Node<Item> current; public LinkedIterator(Node<Item> first) { current = first; } public boolean hasNext() { return current != null; } public void remove() { throw new UnsupportedOperationException(); } public Item next() { if (!hasNext()) throw new NoSuchElementException(); Item item = current.item; current = current.next; return item; } } }
相關文獻:
Bags, Queues, and Stacks