一、题目描述:
输入一个链表的头结点,从尾到头反过来打印出每个结点的值。
链表结点定义如下:
struct ListNode
{
int m_nKey;
ListNode *m_pNext;
};
二、解决思路:
单链表的特性是每个结点只有指向它的下一个结点指针;
所以我们遍历输出时只能正向遍历,而正向遍历又想获得逆向输出,我们很自然的就想到了递归。确实递归是一种解决该问题的一种思路:
void ReversePrintList(ListNode *Head)
{
if(Head != NULL)
{
ReversePrintList(Head->m_pNext);
printf("%d, ", Head->m_nKey);
}
}
递归的代码看起来很简洁,但存在一个问题:当链表非常长的时候,就会导致函数调用层级很深,从而有可能导致函数调用栈溢出,这是一个很致命的问题!
递归导致栈溢出的问题,我们通常使用栈来解决!
我们使用栈来对链表逆序输出:首先遍历一次链表将结点放入一个栈中,然后遍历栈。:
void ReversePrintListByStack(ListNode *Head)
{
stack<ListNode *> myStack;
ListNode *temp;
while(Head != NULL)
{
myStack.push(Head);
Head = Head->m_pNext;
}
while(!myStack.empty())
{
temp = myStack.top();
printf("%d, ", temp->m_nKey);
myStack.pop();
}
printf("\n\n");
}
三、源代码:
#include <iostream>
#include <stack>
using namespace std;
struct ListNode
{
int m_nKey;
ListNode *m_pNext;
};
//头插元素
void HeadInsert(ListNode **Head, int key)
{
ListNode *pNewNode = new ListNode;
if(pNewNode == NULL)
{
return;
}
pNewNode->m_nKey = key;
pNewNode->m_pNext = *Head;
*Head = pNewNode;
}
//正向输出
void PrintList(ListNode *Head)
{
while(Head != NULL)
{
printf("%d, ", Head->m_nKey);
Head = Head->m_pNext;
}
printf("\n\n");
}
//递归法逆向输出
void ReversePrintList(ListNode *Head)
{
if(Head != NULL)
{
ReversePrintList(Head->m_pNext);
printf("%d, ", Head->m_nKey);
}
}
//栈方法逆向输出
void ReversePrintListByStack(ListNode *Head)
{
stack<ListNode *> myStack;
ListNode *temp;
while(Head != NULL)
{
myStack.push(Head);
Head = Head->m_pNext;
}
while(!myStack.empty())
{
temp = myStack.top();
printf("%d, ", temp->m_nKey);
myStack.pop();
}
printf("\n\n");
}
int main(void)
{
ListNode *Head = NULL;
for(int i = 0; i < 10; i++)
{
HeadInsert(&Head, i);
}
printf("正向输出结果: \n");
PrintList(Head);
printf("递归法逆向输出结果: \n");
ReversePrintList(Head);
printf("\n\n");
printf("栈方法逆向输出结果: \n");
ReversePrintListByStack(Head);
return 0;
}
四、运行截图:
文章内容源自剑指Offer!