面试题16: 反转链表
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。链表结点定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};
预备知识:
链表的基本操作如下
//创建链表结点
ListNode* CreateListNode(int value)
{
ListNode* pNode = new ListNode(); //头指针
pNode->m_nValue = value;
pNode->m_pNext = NULL;
return pNode;
}
//链接链表结点
void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
{
if(pCurrent == NULL)
{
printf("Error to connect two nodes.\n");
exit(1);
}
pCurrent->m_pNext = pNext;
}
//打印链表结点
void PrintListNode(ListNode* pNode)
{
if(pNode == NULL)
{
printf("The node is NULL\n");
}
else
{
printf("The key in node is %d.\n", pNode->m_nValue);
}
}
//遍历链表的所有结点
void PrintList(ListNode* pHead)
{
printf("PrintList starts.\n");
ListNode* pNode = pHead;
while(pNode != NULL)
{
printf("%d\t", pNode->m_nValue);
pNode = pNode->m_pNext;
}
printf("\nPrintList ends.\n");
}
//销毁链表
void DestroyList(ListNode* pHead)
{
ListNode* pNode = pHead;
while(pNode !=NULL)
{
pHead = pHead->m_pNext;
delete pNode;
pNode = pHead;
}
}
//在链表尾部添加结点
void AddToTail(ListNode** pHead, int value)
{
ListNode* pNew = new ListNode();
pNew->m_nValue = value;
pNew->m_pNext = NULL;
if(*pHead == NULL)
{
*pHead = pNew;
}
else
{
ListNode* pNode = *pHead;
while(pNode->m_pNext != NULL)
pNode = pNode->m_pNext;
pNode->m_pNext = pNew;
}
}
//移除结点
void RemoveNode(ListNode** pHead, int value)
{
if(pHead == NULL || *pHead == NULL)
return;
ListNode* pToBeDeleted = NULL;
if((*pHead)->m_nValue == value)
{
pToBeDeleted = *pHead;
*pHead = (*pHead)->m_pNext;
}
else
{
ListNode* pNode = *pHead;
while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)
pNode = pNode->m_pNext;
if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value)
{
pToBeDeleted = pNode->m_pNext;
pNode->m_pNext = pNode->m_pNext->m_pNext;
}
}
}
思路:首先面对链表这类题,要多花些时间分析和设计不要忙于写代码。首先我们需要事先准备好测试用例,如链表为空,链表只有一个结点,链表至少有2个结点,之后我们针对性的分析,如链表有3个结点应该怎么处理。通过分析我们就可以判定,要满足题目的要求,需要我们设定3个指针,分别用来指向,当前结点,前一结点,后一结点。总之,一定要多分析,不要忙于写。
算法实现:
// 面试题16.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "..\List.h"
ListNode* ReverseList(ListNode* pHead)
{
if(pHead == NULL) //头指针为NULL,链表为空
return NULL;
ListNode* pReversedHead = NULL;
ListNode* pNode = pHead; //当前节点指针
ListNode* pPrev = NULL; //前一节点指针
while(pNode != NULL)
{
ListNode* pNext = pNode->m_pNext; //后一节点指针
if(pNext == NULL) //只有一个结点的情况
pReversedHead = pNode;
//至少有两个结点的情况
pNode->m_pNext = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pReversedHead;
}
//************测试代码********
void Test1()
{
//创建结点
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
//链接结点
ConnectListNodes(pNode1,pNode2);
ConnectListNodes(pNode2,pNode3);
ConnectListNodes(pNode3,pNode4);
ConnectListNodes(pNode4,pNode5);
//打印当前链表
PrintList(pNode1);
//打印反转后的链表
PrintList(ReverseList(pNode1));
}
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
//打印当前链表
PrintList(pNode1);
//打印反转后的链表
PrintList(ReverseList(pNode1));
}
void Test3()
{
ListNode* pNode1 = NULL;
//打印当前链表
PrintList(pNode1);
//打印反转后的链表
PrintList(ReverseList(pNode1));
}
int _tmain(int argc, _TCHAR* argv[])
{
Test1();
Test2();
Test3();
return 0;
}