鏈表工作原理
問題1:虛擬結點的使用,爲什麼要使用虛擬結點?
虛擬結點就是C數據結構中所說的頭結點,它的next指針指向第一個結點(當然Java中是沒有指針的);使用了虛擬結點,在刪除第一個結點時不會誤刪導致整個鏈表丟失,有利於維護鏈表。
問題2:鏈表中未使用數組,索引從何而來?
鏈表也是線性表,不論是邏輯順序和存儲順序上,表中元素都是相鄰的;所以我們可以從第一個結點開始到最後一個結點,給他指定一個索引來方便我們指定結點。
問題3:索引是如何在鏈表中進行移動的呢?
在鏈式存儲結構中,我們通過next引用將結點連接起來,這樣我們通過next引用的不斷向後傳遞,索引隨着next移動在鏈表中移動。
問題4:爲什麼使用內部類,來定義結點的數據結構?
在定義結點類時,不光使用內部類,同時利用 private 將結點類封裝在鏈表中,將底層數據封裝起來,留下接口給程序員使用,可以防止鏈表被破壞。
實現的方法
- isEmpty():判斷鏈表是否爲空
- contains(AnyType data):鏈表是否包含某個元素
- getSize():獲得鏈表中存儲元素個數
- getFirst():查詢鏈表中的第一個元素
- get(int idx):根據給定索引查詢鏈表中的元素
- getLast():查詢鏈表中的最後一個元素
- addFirst():鏈表的頭插法
- add(int idx, AnyType data):向指定索引位置插入元素
- addLast():鏈表的尾插法
- removeFirst():刪除表頭元素
- remove(int idx, AnyType data):刪除指定索引位置的元素
- removeLast():刪除表尾元素
具體代碼實現
public class MyLinkedList <AnyType>{
private Node head;
private int size;
private class Node{
AnyType data;
Node next;
public Node() {
data = null;
next = null;
}
public Node(AnyType data, Node next) {
this.data = data;
this.next = next;
}
}
public MyLinkedList() {
head = new Node();
size = 0;
}
public boolean isEmpty() {
return head.next == null;
}
public boolean contains(AnyType data) {
if(isEmpty()) {
return false;
}
Node prev = head;
while(prev.next != null) {
prev = prev.next;
if(prev.data == data)
return true;
}
return false;
}
public int getSize() {
return size;
}
public AnyType getFirst() {
Node prev = head.next;
return prev.data;
}
public AnyType get(int idx) {
if(idx > size || idx < 0) {
throw new IllegalArgumentException("不合法位置");
}
Node prev = head;
for(int i = 0; i <= idx; i++) {
prev = prev.next;
}
return prev.data;
}
public AnyType getLast() {
return get(size-1);
}
public void addFirst(AnyType data) {
Node node = new Node(data, head.next);
head.next = node;
size++;
}
public void add(int idx, AnyType data) {
if(idx > size || idx < 0) {
throw new IllegalArgumentException("不合法位置");
}
Node prev = head;
for(int i = 0; i < idx; i++) {
prev = prev.next;
}
Node node = new Node(data, prev.next);
prev.next = node;
size++;
}
public void addLast(AnyType data) {
add(size, data);
}
public void removeFirst() {
if(isEmpty())
throw new IllegalArgumentException("空表無法進行刪除操作");
head = head.next;
size--;
}
public void remove(int idx) {
if(isEmpty() || idx >= size)
throw new IllegalArgumentException("空表或者索引越界無法完成操作");
Node prev = head;
for(int i = 0; i < idx; i++) {
prev = prev.next;
}
Node outNode = prev.next;
prev.next = outNode.next;
size--;
}
public void removeLast() {
remove(size - 1);
}
public String toString() {
StringBuilder strb = new StringBuilder();
strb.append("鏈表:");
strb.append("size = "+size+"\n");
strb.append("[");
Node prev = head;
while(prev.next != null) {
prev = prev.next;
strb.append(prev.data);
if(prev.next != null)
strb.append(',');
}
strb.append("]");
return strb.toString();
}
}