反转链表

题目:

定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。链表结点定义如下:

struct ListNode{
	int m_nKey,
	ListNode * m_pNext;
}

思路:

为了正确地反转一个链表,需要调整链表中指针的方向。为了将复杂的过程说清楚,这里借助于下面的这张图片。

上面的图中所示的链表中,h、i和j是3个相邻的结点。假设经过若干操作,我们已经把h结点之前的指针调整完毕,这个结点的m_pNext都指向前面的一个结点。接下来我们把i的m_pNext指向h,此时结构如上图所示。

从上图注意到,由于结点i的m_pNext都指向了它的前一个结点,导致我们无法在链表中遍历到结点j。为了避免链表在i处断裂,我们需要在调整结点i的m_pNext之前,把结点j保存下来。

即在调整结点i的m_pNext指针时,除了需要知道结点i本身之外,还需要i的前一个结点h,因为我们需要把结点i的m_pNext指向结点h。同时,还需要实现保存i的一个结点j,以防止链表断开。故我们需要定义3个指针,分别指向当前遍历到的结点、它的前一个结点及后一个结点。故反转结束后,新链表的头的结点就是原来链表的尾部结点。尾部结点为m_pNext为null的结点。

代码实现:

public class ListNode {
	public int data;
	public ListNode next;
}
public ListNode reverseList(ListNode pHead){
	ListNode pReversedHead = null; //反转过后的单链表存储头结点
	ListNode pNode = pHead; //定义pNode指向pHead;
	ListNode pPrev = null; //定义存储前一个结点
	while(pNode != null){
		ListNode pNext = pNode.next; //定义pNext指向pNode的下一个结点
		if(pNext==null){ //如果pNode的下一个结点为空,则pNode即为结果
			pReversedHead = pNode;
		}
		pNode.next = pPrev; //修改pNode的指针域指向pPrev
		pPrev = pNode;       //将pNode结点复制给pPrev
		pNode = pNext;       //将pNode的下一个结点复制给pNode
	}
	return pReversedHead;
}

小结:

这道题考查我们是否真正的理解了单链表的结构,以及在反转单链表时对指针的修改。

扩展:

我们知道这个题其实是可以用递归实现使单链表变成反转链表。

代码实现:

public ListNode reverseList3(ListNode pHead){
	if(pHead==null || pHead.next == null){ //如果没有结点或者只有一个结点直接返回pHead
		return pHead;
	}
	ListNode pNext = pHead.next; //保存当前结点的下一结点
	pHead.next = null; //打断当前结点的指针域
	ListNode reverseHead = reverseList3(pNext); //递归结束时reverseHead一定是新链表的头结点
	pNext.next = pHead; //修改指针域
	return reverseHead;
}
posted @ 2018-10-09 21:55  kaleidoscopic  阅读(209)  评论(0编辑  收藏  举报