使用递归反转链表

链表反转:

使用递归反转链表_第1张图片

(图1)

把问题规模减小,并且减小的量为1

使用递归反转链表_第2张图片

(图2)

假设我们的程序能够正常的反转:则反转后为

使用递归反转链表_第3张图片

(图3)

反转后,1元素并没有任何操作,所以反转1的next仍然指向2,

使用递归反转链表_第4张图片

(图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 data){
		//假设传入空的List
		if(data.isEmpty()){
			return null;
		}
		
		//取出传入数据的第一个结点
		Node firstNode=new Node(data.get(0));
		//取走一个元素后,从第二个元素创建一个链表,
		//因为返回的是Node,所以用Node来接收
		//假设传入来的List有一个元素,则走到这里时sublist传入的两个参数相等
		//但是sublist函数的定义可以看到fromIndex==toIndex时,返回null
		/*
		 *  fromIndex and toIndex 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();
	}
	
}

运行结果:

使用递归反转链表_第5张图片

你可能感兴趣的:(编码技巧)