`
gaofen100
  • 浏览: 1189929 次
文章分类
社区版块
存档分类
最新评论

链表反转

 
阅读更多

from : http://hi.baidu.com/fumble/blog/item/b56e5d60029638dc8db10dc4.html

题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。链表结点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
分析:这是一道广为流传的微软面试题。由于这道题能够很好的反应出程序员思维是否严密,在微软之后已经有很多公司在面试时采用了这道题。
为了正确地反转一个链表,需要调整指针的指向。与指针操作相关代码总是容易出错的,因此最好在动手写程序之前作 全面的分析。在面试的时候不急于动手而是一开始做仔细的分析和设计,将会给面试官留下很好的印象,因为在实际的软件开发中,设计的时间总是比写代码的时间 长。与其很快地写出一段漏洞百出的代码,远不如用较多的时间写出一段健壮的代码。
为了将调整指针这个复杂的过程分析清楚,我们可以借助图形来直观地分析。假设下图中 l m n 是三个相邻的结点:
a ß b ßß l m à n à
假设经过若干操作,我们已经把结点 l之前的指针调整完毕,这些结点的 m_pNext 指针都指向前面一个结点。现在我们遍历到结点 m。当然,我们需要把调整结点的 m_pNext 指针让它指向结点 l。但注意一旦调整了指针的指向,链表就断开了,如下图所示:
a ß b ßl ß m n à
因为已经没有指针指向结点 n,我们没有办法再遍历到结点 n 了。因此为了避免链表断开,我们需要在调整 m m_pNext 之前要把 n 保存下来。
接下来我们试着找到反转后链表的头结点。不难分析出反转后链表的头结点是原始链表的尾位结点。什么结点是尾结点?就是 m_pNext 为空指针的结点。
基于上述分析,我们不难写出如下代码:
///////////////////////////////////////////////////////////////////////
// Reverse a list iteratively
// Input: pHead - the head of the original list
// Output: the head of the reversed head
///////////////////////////////////////////////////////////////////////
ListNode* ReverseIteratively(ListNode* pHead)
{
ListNode* pReversedHead = NULL;
ListNode* pNode = pHead;
ListNode* pPrev = NULL;
while (pNode != NULL)
{
// get the next node, and save it at pNext
ListNode* pNext = pNode->m_pNext;
// if the next node is null, the currect is the end of original
// list, and it's the head of the reversed list
if (pNext == NULL)
pReversedHead = pNode;

// reverse the linkage between nodes
pNode->m_pNext = pPrev;

// move forward on the the list
pPrev = pNode;
pNode = pNext;
}

return pReversedHead;
}
扩展:本题也可以递归实现。感兴趣的读者请自己编写递归代码。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics