使用遞迴反轉連結串列
阿新 • • 發佈:2019-02-04
連結串列反轉:
(圖1)
把問題規模減小,並且減小的量為1
(圖2)
假設我們的程式能夠正常的反轉:則反轉後為
(圖3)
反轉後,1元素並沒有任何操作,所以反轉1的next仍然指向2,
(圖4)
假設2開頭的連結串列已經反轉成功,接下來只要將2的next指向1,
(圖5)
而1的next指向null即可。
(圖6)
看似複雜的問題,把如此多的指標反過來指,其實只要將兩個節點反過來即可。
程式碼如下:
package com.sise.recursion; import java.util.ArrayList; import java.util.Arrays; public class LinkedListReverser { /* * 反轉一個連結串列 * head為待反轉連結串列的頭結點 * @return 反轉後的連結串列頭結點,當然該連結串列也是以null結尾 */ public Node reverseLinkedList(Node head) { /* *特殊處理 */ // //空連結串列,sise==0 // if(head==null){ // return null; // } // //只有一個結點的時候,size==1 // if(head.getNext()==null){ // return head; // } //把上兩個特殊情況合起來 if(head==null||head.getNext()==null){ return head; } //假設函式能夠反轉連結串列,返回頭結點 //---------------此處head有可能是null,head。getNext()有可能是null----------- Node newHead=reverseLinkedList(head.getNext()); //此時如圖4狀態,1的getNext就是第二個結點2, //把第二結點2的next指向head則實現把2的指標指向1,如圖5 //------------此處的getNext()有可能是null------ head.getNext().setNext(head); head.setNext(null);//最後指向null,如圖6 return newHead; } public static void main(String[] args) { LinkedListCreator creator=new LinkedListCreator(); LinkedListReverser reverser=new LinkedListReverser(); ArrayList arrayList=new ArrayList<>(); Node.printLinkedList( reverser.reverseLinkedList(creator.createLinkedList(arrayList)) ); Node.printLinkedList( reverser.reverseLinkedList(creator.createLinkedList(Arrays.asList(1))) ); Node.printLinkedList( reverser.reverseLinkedList(creator.createLinkedList(Arrays.asList(1,2,3,4,5))) ); } }
package com.sise.recursion; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class LinkedListCreator { /* * 建立一個連結串列 * @return 連結串列的頭結點,返回連結串列的最後一個結點的getNext()==null. */ public Node createLinkedList(List<Integer> data){ //假設傳入空的List if(data.isEmpty()){ return null; } //取出傳入資料的第一個結點 Node firstNode=new Node(data.get(0)); //取走一個元素後,從第二個元素建立一個連結串列, //因為返回的是Node,所以用Node來接收 //假設傳入來的List有一個元素,則走到這裡時sublist傳入的兩個引數相等 //但是sublist函式的定義可以看到fromIndex==toIndex時,返回null /* * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is */ //與我們期望返回值一致 // Node headOfSublistNode= // createLinkedList(data.subList(1, data.size())); // //第一個結點的next指向規模縮小的連結串列返回來的頭結點 // firstNode.setNext(headOfSublistNode); //上面兩行程式碼清理成如下程式碼 firstNode.setNext(createLinkedList(data.subList(1, data.size()))); return firstNode; } public static void main(String[] args) { LinkedListCreator creator=new LinkedListCreator(); ArrayList arrayList=new ArrayList<>(); Node.printLinkedList( creator.createLinkedList(arrayList) ); Node.printLinkedList( creator.createLinkedList(Arrays.asList(1)) ); Node.printLinkedList( creator.createLinkedList(Arrays.asList(1,2,3,4,5)) ); } }
package com.sise.recursion; public class Node { private final int value;//使用者定義之後就不能修改 private Node next; public Node(int value){ this.value=value; this.next=null;//這樣建立出來的結點都是單點Node } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } public int getValue() { return value; } //列印函式 public static void printLinkedList(Node head) { while(head!=null){ System.out.print(head.getValue());; System.out.print(" "); head=head.getNext(); } System.out.println(); } }
執行結果: