這個文章好的很,尊重原著轉自原貼
(一)單鏈表的結點結構:
data域:儲存資料元素資訊的域稱為資料域;
next域:儲存直接後繼位置的域稱為指標域,它是存放結點的直接後繼的地址(位置)的指標域(鏈域)。
data域+ next域:組成資料ai的儲存映射,稱為結點;
注意: ①鏈表通過每個結點的鏈域將線性表的n個結點按其邏輯順序連結在一起的。
②每個結點只有一個鏈域的鏈表稱為單鏈表(Single Linked List)。
所謂的鏈表就好像火車車廂一樣,從火車頭開始,每一節車廂之後都連著後一節車廂。
要實現單鏈表格儲存體,首先是建立一結點類,其Java代碼如下:
class Node { private int Data;// 資料域 private Node Next;// 指標域 public Node(int Data) { // super(); this.Data = Data; } public int getData() { return Data; } public void setData(int Data) { this.Data = Data; } public Node getNext() { return Next; } public void setNext(Node Next) { this.Next = Next; } }
(二)實現反轉的方法:
(1)遞迴反轉法:在反轉當前節點之前先反轉後續節點。這樣從頭結點開始,層層深入直到尾結點才開始反轉指標域的指向。簡單的說就是從尾結點開始,逆向反轉各個結點的指標域指向,其過程圖如下所示:
head:是前一結點的指標域(PS:前一結點的指標域指向當前結點)
head.getNext():是當前結點的指標域(PS:當前結點的指標域指向下一結點)
reHead:是反轉後新鏈表的頭結點(即原來單鏈表的尾結點)
java代碼如下:
package javatest1; public class javatest1 { public static void main(String[] args) { Node head = new Node(0); Node node1 = new Node(1); Node node2 = new Node(2); Node node3 = new Node(3); head.setNext(node1); node1.setNext(node2); node2.setNext(node3); // 列印反轉前的鏈表 Node h = head; while (null != h) { System.out.print(h.getData() + " "); h = h.getNext(); } // 調用反轉方法 head = Reverse1(head); System.out.println("\n**************************"); // 列印反轉後的結果 while (null != head) { System.out.print(head.getData() + " "); head = head.getNext(); } } /** * 遞迴,在反轉當前節點之前先反轉後續節點 */ public static Node Reverse1(Node head) { // head看作是前一結點,head.getNext()是當前結點,reHead是反轉後新鏈表的頭結點 if (head == null || head.getNext() == null) { return head;// 若為空白鏈或者當前結點在尾結點,則直接還回 } Node reHead = Reverse1(head.getNext());// 先反轉後續節點head.getNext() head.getNext().setNext(head);// 將當前結點的指標域指向前一結點 head.setNext(null);// 前一結點的指標域令為null; return reHead;// 反轉後新鏈表的頭結點 } } class Node { private int Data;// 資料域 private Node Next;// 指標域 public Node(int Data) { // super(); this.Data = Data; } public int getData() { return Data; } public void setData(int Data) { this.Data = Data; } public Node getNext() { return Next; } public void setNext(Node Next) { this.Next = Next; } }
(2)遍曆反轉法: 遞迴反轉法是從後往前逆序反轉指標域的指向,而遍曆反轉法是從前往後反轉各個結點的指標域的指向。 基本思路是:將當前節點cur的下一個節點 cur.getNext()緩衝到temp後,然後更改當前節點指標指向上一結點pre。也就是說在反轉當前結點指標指向前,先把當前結點的指標域用tmp臨時儲存,以便下一次使用,其過程可表示如下:
pre:上一結點
cur: 當前結點
tmp: 臨時結點,用於儲存當前結點的指標域(即下一結點)
Java代碼實現:
package javatest1; public class JavaTest1 { public static void main(String[] args) { Node head = new Node(0); Node node1 = new Node(1); Node node2 = new Node(2); Node node3 = new Node(3); head.setNext(node1); node1.setNext(node2); node2.setNext(node3); // 列印反轉前的鏈表 Node h = head; while (null != h) { System.out.print(h.getData() + " "); h = h.getNext(); } // 調用反轉方法 // head = reverse1(head); head = reverse2(head); System.out.println("\n**************************"); // 列印反轉後的結果 while (null != head) { System.out.print(head.getData() + " "); head = head.getNext(); } } /** * 遍曆,將當前節點的下一個節點緩衝後更改當前節點指標 */ public static Node reverse2(Node head) { if (head == null) return head; Node pre = head;// 上一結點 Node cur = head.getNext();// 當前結點 Node tmp;// 臨時結點,用於儲存當前結點的指標域(即下一結點) while (cur != null) {// 當前結點為null,說明位於尾結點 tmp = cur.getNext(); cur.setNext(pre);// 反轉指標域的指向 // 指標往下移動 pre = cur; cur = tmp; } // 最後將原鏈表的前端節點的指標域置為null,還回新鏈表的頭結點,即原鏈表的尾結點 head.setNext(null); return pre; } } class Node { private int Data;// 資料域 private Node Next;// 指標域 public Node(int Data) { // super(); this.Data = Data; } public int getData() { return Data; } public void setData(int Data) { this.Data = Data; } public Node getNext() { return Next; } public void setNext(Node Next) { this.Next = Next; } }