关闭

颠倒一个链表的顺序

标签: 算法设计链表Java面试题
1035人阅读 评论(0) 收藏 举报
分类:

对于颠倒一个链表的顺序这里我们介绍两种可行的方法: 递归的和非递归的.


我们先说说递归的方法:

(1)如果一个链表为空链表,那么他的逆序还是为空,也就是这个链表本身了.

(2)如果一个链表中只有一个节点,那么他的逆序就是这个链表本身.

(3)如果一个链表的长度大于一,那么我们做如下递归.

把当前链表的除了头节点(head)之外的剩余节点组成的链表逆序,也就是递归调用,并得到剩余链表逆序后的头结点(ph),

此时将head的下一个节点的的next指向head, 并将head的next指针置空.然后返回ph.


说起来比较抽象,画图模拟一下吧:

(1).(2)点很简单,我们只说(3):


我们调用函数reverse(head), 将整个链表的头部传进去.然后head不为空,且head.next不为空,那么递归调用,reverse(head.next),此时链表长度减一.程序一直递归,直至当前传入的链表长度为1时,程序返回该子链表本身,其实就只有一个节点,也就是原链表的最后一个节点,此时程序返回ph(就是唯一的那个节点)到上一次调用处,此时程序处在倒数第二层调用.情况如下

图中的ph就是最后一次递归返回的节点,head为倒数第二次递归时链表的头结点.此时如何完成节点顺序的倒置呢,如下:


该过程分为两步: 

第一步先是将head的后一个节点的next指向当前头结点.

第二部再是将head的next置为空,去掉head.next和ph之间的关系.

此时的链表变为:


然后倒数第二层递归执行完成,将ph返回给倒数第三层.情形如下:


图中框起来部分就是倒数第二层递归时已经完成逆序的部分,当前递归中应该处理此时的head与ph之间的关系

此时依然完成上面已经提到过的那两步:


此时绿线部分便是在此次循环过程中完成的工作,一次类推.直至将整个链表逆序.


程序源码:

public Node reverse(Node head){
	if (head == null){
		return head;
	}
	if (head.next == null){
		return head;
	}
	Node ph = reverse(head.next);
	head.next.next = head;
	head.next = null;
	return ph;
}


下面我们来说说非递归的方法:

非递归过程比较简单,此处仅给出实现代码:

public Node reverse1(Node head){
	if (head == null){
		return null;
	}
	Node p = head;
	Node previous = null;
	while (p.next != null){
		p.next = previous;
		previous = p;
		p = previous.next;
	}
	p.next = previous;
	return p;
}

整个过程中使用previous保存已经处理过的上一个节点,总是将当前节点的next指向上一个节点.而上一个节点恰恰就是原链表中当前节点的下一个节点,以此来实现链表的颠倒.

注意事项为头结点的上一个节点为空,因此previous应该初始化为空,还有一点就是原链表的尾会成为新链表的头,而原链表的尾部的next为空,因此需要单独处理,也就是在推出循环后,将p.next指向previous.

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:10184次
    • 积分:203
    • 等级:
    • 排名:千里之外
    • 原创:7篇
    • 转载:0篇
    • 译文:4篇
    • 评论:4条
    最新评论