在面试中,被问到有关链表的问题是很多的。如题,本文就是其中一个。
一共有三种思路:循环与递归,还有一种是头插:
循环的思想是用三个节点指针来进行反转,如图:
有了思路之后,代码如下:
struct ListNode {
int _value;
struct ListNode *_next;
}
//
ListNode* reverseList(ListNode* pHead) {
ListNode *first = pHead->next;
ListNode *current = pHead;
ListNode *last = NULL;
//迭代反转
while ( current != NULL ){
current ->next = last;
last = current;
current = first;
if ( first != NULL ){//最后一个节点时first为NULL
first = first->next;
}
}
return last;
}
你可以调整一下判断的位置,这样可以更简洁;
第二个思路:
要反转当前节点,则后面节点须已经反转,故而可用递归,代码如下:
ListNode* ReverseList(ListNode* pHead) {
if (NULL == pHead)
return NULL;
return reverse(pHead, NULL);
}
ListNode *reverse(ListNode *pHead, ListNode *prev){
if (pHead == NULL)
return prev;
ListNode *Next = pHead->next;
pHead->next = prev;
return reverse(Next, pHead);
}
第三个思路:头插法
每次循环取出原链表的一个节点,对新链表进行头插
ListNode* reverseList(ListNode* pHead) {
ListNode *nhead = NULL;
ListNode *Next = NULL;
ListNode *cur = NULL;
while (pHead){
cur = pHead;
pHead = pHead->next;
cur->next = Next;
nhead = cur;
Next = cur;
}
return nhead;
}
除了上述的办,你也可以借助数据结构来帮助你,比如栈,不过这似乎走远了。。