1. 程式人生 > >使用遞迴反轉連結串列

使用遞迴反轉連結串列

連結串列反轉:

(圖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();
	}
	
}

執行結果: