1、單鏈表和數組的區別
數組:數組的存儲空間是連續的,需要事先申請空間確定大小,通過下標查找數據,所以查找速度快,但是增加和刪除速度慢
鏈表:離散存儲,不需要事先確定大小,通過頭指針加遍歷查找數據,查找數據慢,但是增加和刪除速度快
【舉例】
把內存空間看成一個教室,同學代表數據
【數組】
- 申請空間
int[] seat = new int[5]表示我從教室(內存空間)申請第一排座位(數組),座位按1,2,3.....的順序標記,seat[1]表示坐在第一個位置的同學(數據),同學只能坐第一排。

-
存儲數據
-
來了第一個同學(
1)他坐在了第1個位置(int[0] = 1), -
來了第二個同學(
4) 他屁事多,他要做第6個位置(int[5] = 4),此時老師罵人了,那里不讓做(數組越界異常),無奈,第二個同學選擇了第4個位置(int[3] = 4) -
接下來五個同學都坐滿了
-
-
查找
查找數據就不用說了吧,對號入座,老師很快就可以按座位號(下標)叫第幾個同學回答問題
- 刪除
這個就有點麻煩了,第二個同學不認真,老師叫他滾出去,這時候座位號應該減少一個,那么第三個同學就要往左移一格(int[1] = int[2]),后面依次往左移一格,最后int[4]空出來了,所以應該把最后一個座位還給教室(歸還給內存),所以說這個還是比較麻煩的(ps:我是按照c語言思想講這里的,只學過Java的同學可能難以接受)需要移動座位,很麻煩

【鏈表】
-
申請空間
鏈表不需要事先申請空間
-
添加數據(這里講的是有頭節點的鏈表,方便寫代碼)
-
老師先讓班長(頭節點)找好位置(可用內存),老師只知道班長的座位號(地址),這時候班長找好了位置,告訴了老師,老師對班長說:吩咐下去,叫每一個同學記好在他們后一個進教室的同學的座位(地址)
-
第一個同學M進來,按照自己的心情找了個空座位(可用內存),班長(頭節點)記錄了他的座位
-
第二同學N進來,也按照自己的心情找了個空座位(可用內存),第一個同學記錄了第二個同學的座位
......以此類推
-
-
查找數據(每個同學只知道他們下一個進來的同學)
-
老師對班長(頭節點)說:點名,第3個進來的同學回答問題
-
班長說:我后面進來的是同學M,找到了M
-
M說:我后面進來的是同學N,找到了N
-
N說:我后面進來的同學是X,找到了第三個進來的同學X
-
老師說:就是你了,同學X回答問題
-
-
刪除數據
- 第2個進教室的同學調皮搗蛋,老師讓他滾出去
- 重復查找數據步驟,班長——>M——>N(找到第二進來的同學)
- 讓N滾動,此時,在M后進入的同學就是X了,只要記住座位號就可以了
- 不要移動座位,很方便

-
插入數據
- 同學N改過自新了,重新申請做在第二個位置
- 重復查找步驟,班長——>M(找到第一個進來的同學)
- M記住他的下一個同學是N
- N記住他的下一個同學是X
- 不要移動座位,很方便

2、代碼實現
數據結構這種東西,太玄學了,我當初學的c語言版本,學了好久就是不明白,突然有一天就腦袋就開竅了,估計是菩薩保佑
現在來用java代碼實現
1、定義鏈表
public class SingleLinkedList<T>{
//記錄鏈表長度
private int size;
//頭節點,不存數據,方便實現增刪代碼的
private Node head;
/**
* 成員內部類,節點類,相當於例子中的同學和座位號的集合題
* 我覺得這個類不應該暴露給外部
*/
private class Node{
private Node next;
private T t;
Node(Node next,T t){
this.next = next;
this.t = t;
}
Node(T t){
this(null,t);
}
Node(){
Node next = null;
t = null;
}
}
//鏈表構造方法
public SingleLinkedList(){
//初始化頭節點,不存數據,方便實現增刪代碼的
this.head = new Node();
this.size = 0;
}
/**
* 此處省略了方法,單獨拿出來給大家講解
* .........
*/
}
2、獲取長度
//獲取長度
public int getSize(){
return size;
}
3、添加節點
//添加節點
public void add(T t){
Node newNode = new Node(t);
Node temp = this.head;
while(temp.next != null){
temp = temp.next;
}
temp.next = newNode;
size++;
}
4、插入節點
//插入節點,先判斷節點是否合法
public void insert(T t,int index){
if(index <= 0 || index > this.size){
throw new RuntimeException("index參數不合法");
}
Node newNode = new Node(t);
Node temp = this.head;
//要明白到底循環幾次
for (int i = 1; i < index; i++) {
temp = temp.next;
}
//注意順序
newNode.next = temp.next;
temp.next = newNode;
size++;
}
5、取節點數據
//取節點數據
public T getValue(int index){
if(index <= 0 || index > this.size){
throw new RuntimeException("index參數不合法");
}
Node temp = this.head;
//要明白到底循環幾次
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp.t;
}
6、刪除節點
//刪除節點
public void delete(int index){
if(index <= 0 || index > this.size){
throw new RuntimeException("index參數不合法");
}
Node temp = this.head;
//要明白到底循環幾次
for (int i = 1; i < index; i++) {
temp = temp.next;
}
temp.next = temp.next.next;
//java垃圾回收機制gc自動回收內存
size--;
}
7、遍歷
//遍歷
public void showData(){
Node temp = this.head;
//要明白到底循環幾次
for (int i = 0; i < this.size; i++) {
temp = temp.next;
System.out.print("["+temp.t+"]-->");
}
}
【總結】
個人代碼水平有限,僅作參考
