一.揹包
揹包是一種不支持從中刪除元素的集合數據類型,目的是幫助用例收集元素並迭代所有收集到的元素,也可以檢查揹包是否為空,或者獲取揹包中元素的數量。揹包裡面的元素的順序不確定。
要理解揹包的概念,可以想象一個喜歡收集彈珠球的人。他將所有的彈珠球都放在一個揹包裡,一次一個,並且會不時在所有的彈珠球中尋找某一顆;
1.用鏈表實現
<code>import edu.princeton.cs.algs4.StdIn;import edu.princeton.cs.algs4.StdOut;import java.util.Iterator;import java.util.NoSuchElementException;public class Bag<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 bag. */ public Bag() { first = null; n = 0; } public boolean isEmpty() { return first == null; } public int size() { return n; } public void add(Item item) { Node<item> oldfirst = first; first = new Node<item>(); first.item = item; first.next = oldfirst; n++; } public Iterator<item> iterator() { return new ListIterator(first); } private class ListIterator implements Iterator<item> { private Node<item> current; public ListIterator(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; } } public static void main(String[] args) { Bag<string> bag = new Bag<string>(); while (!StdIn.isEmpty()) { String item = StdIn.readString(); bag.add(item); } StdOut.println("size of bag = " + bag.size()); for (String s : bag) { StdOut.println(s); } }}/<string>/<string>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<code>
二.隊列
隊列的特性:
- 在隊尾插入元素,在隊首刪除元素。
- FIFO(先進先出),就向排隊取票一樣。
1.用鏈表實現
<code>package structure;import edu.princeton.cs.algs4.StdIn;import edu.princeton.cs.algs4.StdOut;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 Item peek() { if (isEmpty()) throw new NoSuchElementException("Queue underflow"); return first.item; } //增加元素 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; // to avoid loitering return item; } public String toString() { StringBuilder s = new StringBuilder(); for (Item item : this) { s.append(item); s.append(' '); } return s.toString(); } public Iterator<item> iterator() { return new ListIterator(first); } private class ListIterator implements Iterator<item> { private Node<item> current; public ListIterator(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; } } public static void main(String[] args) { Queue<string> queue = new Queue<string>(); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) queue.enqueue(item); else if (!queue.isEmpty()) StdOut.print(queue.dequeue() + " "); } StdOut.println("(" + queue.size() + " left on queue)"); }}/<string>/<string>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<code>
三.棧
(1)棧是一種線性結構,棧中的元素遵循先入後出的原則,最先進入的元素所在位置叫做棧底,最後放入的元素所在位置叫做棧頂。
這種結構類似於盛放羽毛球的圓筒,一端封閉,另一端開口,先放入的羽毛球位於筒的底部(即棧底),後放入的羽毛球位於筒的入口(即棧頂)。
(2)棧也是一種抽象的邏輯結構,依賴於物理結構(如數組、鏈表)而存在。既可以使用數組實現,也可以使用鏈表實現。
(3)出棧、入棧的時間複雜都是O(1)。
1.用數組實現
<code>import edu.princeton.cs.algs4.StdIn;import edu.princeton.cs.algs4.StdOut;import java.util.Iterator;import java.util.NoSuchElementException;public class ResizingArrayStack<item> implements Iterable<item> { private Item[] a; private int n; public ResizingArrayStack() { a = (Item[]) new Object[2]; n = 0; } public boolean isEmpty() { return n == 0; } public int size() { return n; } //重置數組大小 private void resize(int capacity) { assert capacity >= n; // textbook implementation Item[] temp = (Item[]) new Object[capacity]; for (int i = 0; i < n; i++) { temp[i] = a[i]; } a = temp; // alternative implementation // a = java.util.Arrays.copyOf(a, capacity); } public void push(Item item) { if (n == a.length) resize(2*a.length); a[n++] = item; } public Item pop() { if (isEmpty()) throw new NoSuchElementException("Stack underflow"); Item item = a[n-1]; a[n-1] = null; n--; if (n > 0 && n == a.length/4) resize(a.length/2); return item; } // 返回棧頂部數據,但不移除 public Item peek() { if (isEmpty()) throw new NoSuchElementException("Stack underflow"); return a[n-1]; } public Iterator<item> iterator() { return new ReverseArrayIterator(); } private class ReverseArrayIterator implements Iterator<item> { private int i; public ReverseArrayIterator() { i = n-1; } public boolean hasNext() { return i >= 0; } public void remove() { throw new UnsupportedOperationException(); } public Item next() { if (!hasNext()) throw new NoSuchElementException(); return a[i--]; } } public static void main(String[] args) { ResizingArrayStack<string> stack = new ResizingArrayStack<string>(); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) stack.push(item); else if (!stack.isEmpty()) StdOut.print(stack.pop() + " "); } StdOut.println("(" + stack.size() + " left on stack)"); }}/<string>/<string>/<item>/<item>/<item>/<item>/<code>
2.用鏈表實現
<code>import edu.princeton.cs.algs4.StdIn;import edu.princeton.cs.algs4.StdOut;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; } public Stack() { 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; // save item to return first = first.next; // delete first node n--; return item; // return the saved item } //返回棧頂部數據,但不移除 public Item peek() { if (isEmpty()) throw new NoSuchElementException("Stack underflow"); return first.item; } public String toString() { StringBuilder s = new StringBuilder(); for (Item item : this) { s.append(item); s.append(' '); } return s.toString(); } public Iterator<item> iterator() { return new ListIterator(first); } private class ListIterator implements Iterator<item> { private Node<item> current; public ListIterator(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; } } public static void main(String[] args) { Stack<string> stack = new Stack<string>(); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) stack.push(item); else if (!stack.isEmpty()) StdOut.print(stack.pop() + " "); } StdOut.println("(" + stack.size() + " left on stack)"); }}/<string>/<string>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<item>/<code>
閱讀更多 sandag 的文章