標籤:color 方向 改名 next item tor 概念 集合 解決
總結:本小節講述了鏈表的概念,以及用鏈表實現Stack、Queue和Bag的過程和優缺點。
重點:
1. 定義:鏈表是一種遞迴的資料結構,它或者為空白(null),或者是指向一個結點(node)的引用,該結點含有一個泛性的元素和一個指向另一條鏈表的引用。
2. 我們首先用一個嵌套類來定義結點的抽象資料類型:
private class Node { Item item; Node next;}
它們實現的不是抽象資料類型,因為我們會直接使用其執行個體變數。
3. 所需的時間和鏈表的長度無關的三種操作:
· 在表頭插入結點;
· 從表頭刪除結點;
· 在表尾插入結點。
這是重點,一定要理解!
4. 實現任意插入和刪除操作的標準解決方案是使用雙向鏈表,其中每個結點都含有兩個連結,分別指向不同的方向。
5. 棧的實現(原因:3):
當使用push()壓入一個元素時,我們會按照1.3.3.3節所討論的代碼將該元素添加在表頭;
當使用pop()刪除一個元素時,我們會按照1.3.3.4節討論的代碼將該元素從表頭刪除。
public class Stack<Item> { private Node first; // 棧頂(最近添加的元素) private int N; // 元素數量 private class Node { // 定義了結點的嵌套類 Item item; Node next; } public boolean isEmpty() { return first == null; } public int size() { return N; } public void push(Item item) { // 向棧頂添加元素 Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; N++; } public Item pop() { // 從棧頂刪除元素 Item item = first.item; first = first.next; N--; return item; }}
鏈表的方向:棧頂 -> 棧底
6. 隊列的實現(原因:3):
要將一個元素入列(enqueue()),我們就將它添加到表尾(在鏈表為空白時需要將first和last都指向新結點);
要將一個元素出列(dequeue()),我們就刪除表頭的結點(當鏈表為空白時需要更新last的值)。
public class Queue<Item> { private Node first; // 指向最早添加的結點的連結 private Node last; // 指向最近添加的結點的連結 private int N; // 隊列中的元素數量 private class Node { // 定義了結點的嵌套類 Item item; Node next; } public boolean isEmpty() { return first == null; // 或: N == 0. } public int size() { return N; } public void enqueue(Item item) { // 向表尾添加元素 Node oldlast = last; last = new Node(); last.item = item; last.next = null; if (isEmpty()) first = last; else oldlast.next = last; N++; } public Item dequeue() { // 從表頭刪除元素 Item item = first.item; first = first.next; if (isEmpty()) last = null; N--; return item; }}
鏈表的方向:隊頭 -> 隊尾
7. 鏈表的使用達到了我們的最優設計目標:
· 它可以處理任意類型的資料;
· 所需的空間總是和集合的大小成正比;
· 操作所需的時間總是和集合的大小無關。
8. 程式設計語言曆史上的一塊裡程碑就是McCathy在20世紀50年代發明的LISP語言,而鏈表則是這種語言群組織程式和資料的主要結構。
9. 背包的實現:
只需要將Stack中的push()改名為add(),並去掉pop()的實現即可。
import java.util.Iterator;public class Bag<Item> implements Iterable<Item> { private Node first; // 鏈表的首結點 private int N; private class Node { Item item; Node next; } public boolean isEmpty() { return first == null; } public int size() { return N; } public void add(Item item) { // 和Stack的push()方法完全相同 Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; N++; } public Iterator<Item> iterator() { return new ListIterator(); } private class ListIterator implements Iterator<Item> { private Node current = first; public boolean hasNext() { return current != null; } public void remove() {} public Item next() { Item item = current.item; current = current.next; return item; } }}
*hasNext()方法會檢測current是否為null。
演算法(第4版)-1.3.3 鏈表