什么是單鏈表
在了解單鏈表之前,你知道什么是鏈表嗎?如果你不知道什么是鏈表,可以看看我的這篇博客<鏈表-LinkList>
單鏈表是鏈表的其中一種基本結構。一個最簡單的結點結構如圖所示,它是構成單鏈表的基本結點結構。在結點中數據域用來存儲數據元素,指針域用於指向下一個具有相同結構的結點。
因為只有一個指針結點,稱為單鏈表。


單鏈表中三個概念需要區分清楚:分別是頭指針,頭節點和首元節點。
頭結點、頭指針和首元結點(此段轉自@ciyeer大牛的博客)
- 頭結點:有時,在鏈表的第一個結點之前會額外增設一個結點,結點的數據域一般不存放數據(有些情況下也可以存放鏈表的長度等信息),此結點被稱為頭結點。
若頭結點的指針域為空(NULL),表明鏈表是空表。頭結點對於鏈表來說,不是必須的,在處理某些問題時,給鏈表添加頭結點會使問題變得簡單。
首元結點:鏈表中第一個元素所在的結點,它是頭結點后邊的第一個結點。
-
頭指針:永遠指向鏈表中第一個結點的位置(如果鏈表有頭結點,頭指針指向頭結點;否則,頭指針指向首元結點)。
-
頭結點和頭指針的區別:頭指針是一個指針,頭指針指向鏈表的頭結點或者首元結點;頭結點是一個實際存在的結點,它包含有數據域和指針域。兩者在程序中的直接體現就是:頭指針只聲明而沒有分配存儲空間,頭結點進行了聲明並分配了一個結點的實際物理內存。

單鏈表中可以沒有頭結點,但是不能沒有頭指針!
頭節點的引入能使鏈表對第一個元素的刪除和插入和其他元素相同,不用另外說明,使得代碼更加簡潔。
單鏈表的基本操作
單鏈表的基本操作有:增(add),刪(remove),改(set),查(find),插(insert)等。
在這里我們只講解add,remove,insert三個操作,其他實現看源碼。
單鏈表增添元素
-
聲明一個新節點node作為新的尾節點,next=null;
-
獲取原鏈表的最后一個節點,把它的next指向1步驟的新節點node
-
記錄鏈表長度的變量+1
public void add(AnyType a){
Node<AnyType> renode=new Node<>(a,null);
getNode(thesize-1).next=renode;
thesize++;
}
單鏈表刪除元素
-
獲取需要刪除的節點的上一個節點node
-
把node的next指向node的next的next
-
因為node的next節點沒有指針指向它,因此它會被系統自動清理
-
記錄鏈表長度的變量-1
public AnyType remove(int i){
Node<AnyType> prev=getNode(i-1);
AnyType a=prev.next.data;
prev.next=prev.next.next;
thesize--;
return a;
}
單鏈表插入元素
-
獲取需要插入的位置的節點;
-
聲明一個新節點node指向1步驟得到的節點;
-
獲取需要插入位置節點的上一個節點;
-
將3步驟得到的節點的next指向新節點node;
-
記錄鏈表長度的變量+1。
public void insert(int i,AnyType a){
Node<AnyType> prev=getNode(i-1);
Node<AnyType> renode=new Node<>(a,prev.next);
prev.next=renode;
thesize++;
}
源碼實現(java)
/*
結點
*/
public class Node<AnyType> {
public AnyType data;
public Node<AnyType> next;
public Node(AnyType data,Node<AnyType> next){
this.data=data;
this.next=next;
}
}
-----
public class MyLinkList<AnyType> {
//首元節點
private Node<AnyType> first;
//頭指針
private Node<AnyType> head;
//鏈表長度
int thesize;
//初始化鏈表
public boolean initlist(){
thesize=0;
first=new Node<>(null,null);
head=new Node<>(null,first);
return true;
}
//判斷鏈表是否為空
public boolean isEmpty(){
return thesize==0;
}
//獲取節點
public Node<AnyType> getNode(int i){
Node<AnyType> renode=head;
for(int j=-2;j<i;j++){
renode=renode.next;
}
return renode;
}
//在末尾添加元素
public void add(AnyType a){
Node<AnyType> renode=new Node<>(a,null);
getNode(thesize-1).next=renode;
thesize++;
}
//刪除i位置節點,並返回刪掉的數據
public AnyType remove(int i){
if(i==thesize-1){
AnyType a=getNode(thesize-1).data;
getNode(thesize-2).next=null;
return a;
}
Node<AnyType> prev=getNode(i-1);
AnyType a=prev.next.data;
prev.next=prev.next.next;
thesize--;
return a;
}
//在i位置插入新節點
public void insert(int i,AnyType a){
Node<AnyType> prev=getNode(i-1);
Node<AnyType> renode=new Node<>(a,prev.next);
prev.next=renode;
thesize++;
}
//獲取i位置節點的數據
public AnyType get(int i){
return getNode(i).data;
}
//為i位置元素重新賦值
public void set(int i,AnyType a){
getNode(i).data=a;
}
//返回鏈表節點個數
public int length(){
return thesize;
}
//清空鏈表
public void clear(){
initlist();
}
//打印鏈表
public void print(){
for(int i=0;i<thesize;i++){
System.out.println(getNode(i).data);
}
}
}