資料結構(五)——線性結構之連結串列Linked List
一.連結串列
典型的連結串列結構,連結串列中每個結點都應該包括如下內容:
- 資料部分,儲存的是該結點的實際資料;
- 地址部分,儲存的是下一個結點的地址。
由於採用了引用來指示下一個資料的地址。因此在連結串列結構中,邏輯上相鄰的結點在記憶體中不一定相鄰,邏輯相鄰關係通過地址部分的引用變數來實現。
(1)連結串列優點:
連結串列最大的好處是結點之間不要求連續存放,因此在儲存大量資料的同時,不需要分配一塊連續的儲存空間。
使用者可以用new函式動態分配結點的儲存空間,當刪除某個結點時,給該結點賦值null,釋放其佔用的記憶體空間。
(2)連結串列缺點:
浪費儲存空間。對於每個結點資料,都要額外儲存一個引用變數。
(3)連結串列訪問方式:
從表頭逐個查詢,即通過head頭引用找到第一個結點,再從第一個結點找到第二個結點....這樣逐個比較一直找到需要的結點為止。而不能像順序表一樣隨機訪問。
二.單鏈表
1.單鏈表定義
單向連結串列(又名單鏈表、線性連結串列)是連結串列的一種,其特點是連結串列的連結方向是單向的(每個結點中只包含一個引用),對連結串列的訪問要通過從頭部開始,依序往下讀取。
2.單鏈表的操作
單鏈表的主要操作有以下幾個:
(1)在連結串列結尾追加結點;
(2)獲取下一個結點;
(3)獲取最後一個結點;
(4)判斷當前結點是否為最後結點;
(5)刪除下一個結點;
(6)展示連結串列的所有結點;
(7)插入一個結點作為當前結點的下一個結點。
package cn.kimtian.linkedlist; /** * 這是連結串列的一個結點 * * @author kimtian */ public class Node { /** * 結點內容(存任何型別都可以) */ private int data; /** * 下一個結點 */ Node next; /** * 建立結點的時候,給一個value * * @param data */ public Node(int data) { this.data = data; } /** * 為結點追加結點(在連結串列的結尾) * * @param node */ public Node appendNode(Node node) { //開始是當前結點 Node currentNode = this; //迴圈向後找 while (true) { //取出下一個節點,賦值給當前結點 Node nextNode = currentNode.next; //結束標記,如果下一個結點為null,當前結點已經是最後一個結點了 if (nextNode == null) { break; } currentNode = nextNode; } //把需要追加的結點追加到找到的當前結點的下一個結點 currentNode.next = node; //將自身返回出去 return this; } /** * 獲取結點的下一個結點 */ public Node nodeNext() { return this.next; } public int getData() { return this.data; } /** * 獲取結點的最終結點 */ public Node nodeFinal() { //開始是當前結點 Node currentNode = this; //迴圈向後找 while (true) { //取出下一個節點,賦值給當前結點 Node nextNode = currentNode.next; //結束標記,如果下一個結點為null,當前結點已經是最後一個結點了 if (nextNode == null) { break; } currentNode = nextNode; } //將自身返回出去 return currentNode; } /** * 判斷當前結點是否為最後結點 */ public boolean isLast() { return this.next == null; } /** * 刪除下一個結點 */ public void removeNext() { //取出下下一個結點 Node newNext = next.next; //把下下一個結點設定為當前結點的下一個結點 this.next = newNext; } /** * 插入一個結點作為當前結點的下一個結點(在連結串列中間) * * @param node 插入的結點 */ public void addNode(Node node) { //取出下一個結點作為下下一個結點 Node nextNode = next; //把新結點插入為當前結點的下一個結點 this.next = node; //把下下一個結點設定為新結點的下一個結點 node.next = nextNode; } /** * 顯示所有結點資訊 */ public void showNodes() { Node currentNode = this; while (true) { System.out.print(currentNode.data + " "); //取出下一個結點 currentNode = currentNode.next; //如果是最後一個結點 if (currentNode == null) { break; } } System.out.println(); } }
三.迴圈連結串列
1.單向迴圈連結串列定義:
操作和單鏈表基本一致。(在單鏈表中,將終端結點的引用域null改為指向表頭結點或開始結點即可構成單迴圈連結串列。)
只是它的最後一個結點指向頭結點,形成一個環。因此,從迴圈連結串列中的任何一個結點出發都能找到任何其他結點。
2.單向迴圈連結串列的操作:
(1)插入結點;
(2)刪除結點。
package cn.kimtian.linkedlist;
/**
* 迴圈連結串列
*
* @author kimtian
*/
public class LoopNode {
/**
* 結點內容(存任何型別都可以)
*/
private int data;
/**
* 下一個結點
*/
LoopNode next = this;
/**
* 建立結點的時候,給一個value
*
* @param data
*/
public LoopNode(int data) {
this.data = data;
}
/**
* 獲取結點的下一個結點
*/
public LoopNode nodeNext() {
return this.next;
}
public int getData() {
return this.data;
}
/**
* 刪除下一個結點
*/
public void removeNext() {
//取出下下一個結點
LoopNode newNext = next.next;
//把下下一個結點設定為當前結點的下一個結點
this.next = newNext;
}
/**
* 插入一個結點作為當前結點的下一個結點(在連結串列中間)
*
* @param node 插入的結點
*/
public void addNode(LoopNode node) {
//取出下一個結點作為下下一個結點
LoopNode nextNode = next;
//把新結點插入為當前結點的下一個結點
this.next = node;
//把下下一個結點設定為新結點的下一個結點
node.next = nextNode;
}
}
3.雙向迴圈連結串列定義
若每個結點包含兩個引用,一個指向下一個結點,另一個指向上一個結點,這就是雙向連結串列。
4.雙向連結串列操作
(1)增加一個結點;
(2)獲取上一個結點;
(3)獲取下一個結點;
package cn.kimtian.linkedlist;
/**
* 這是一個雙向連結串列
*
* @author kimtian
*/
public class DoubleNode {
/**
* 結點內容(存任何型別都可以)
*/
private int data;
public int getData() {
return data;
}
/**
* 上一個結點
*/
DoubleNode preDoubleNode = this;
/**
* 下一個結點
*/
DoubleNode nextDoubleNode = this;
/**
* 建立結點的時候,給一個value
*
* @param data
*/
public DoubleNode(int data) {
this.data = data;
}
/**
* 增加一個結點
*
* @param doubleNode 結點
*/
public void addDoubleNode(DoubleNode doubleNode) {
//取出下一個結點作為下下一個結點
DoubleNode nextNode = nextDoubleNode;
//把新結點插入為當前結點的下一個結點
this.nextDoubleNode = doubleNode;
//把當前結點作為新結點的前一個結點
doubleNode.preDoubleNode = this;
//把下下一個結點設定為新結點的下一個結點
doubleNode.nextDoubleNode = nextNode;
//把下下一個結點的上一個結點設定為新結點
nextNode.preDoubleNode = doubleNode;
}
/**
* 獲取下一個結點的方法
*/
public DoubleNode getNext() {
return this.nextDoubleNode;
}
/**
* 獲取上一個結點的方法
*/
public DoubleNode getPre() {
return this.preDoubleNode;
}
}
5.多重鏈的迴圈連結串列:
如果將表中的結點鏈在多個環上,將構成多重鏈的迴圈連結串列。