面试题5:从尾到头打印链表
题目:输入一个链表的头结点,从尾到头反过来打印出每个节点值。
解决这个问题肯定要遍历链表。遍历的顺序是从头到尾的顺序,可输出的顺序却是从尾到头。也就是说第一个遍历到的结点最后一个输出,而最后一个遍历到得结点第一个输出。这就是典型的“后进先出”,可以用栈实现这种顺序。每经过一个结点的时候,把该结点放到一个栈中。当遍历完整个链表后,再从栈顶开始逐个输出结点的值,此时输出的结点的顺序已经反转过来了。
递归在本质上就是一个栈结构,于是很自然地想到用递归来实现。要实现反过来输出链表,每访问到一个结点的时候,先递归输出它后面的结点,再输出该结点自身,这样链表的输出结构就反过来了。
#include "stdafx.h" #include <iostream> #include <stack> using namespace std; //链表结点定义 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) { cout<<"Error to connect two nodes."<<endl; return; } pCurrent->m_pNext=pNext; } //利用栈实现链表结点逆序 void PrintListReversingly_Iteratively(ListNode* pHead) { stack<ListNode*> nodes; ListNode* pNode=pHead; while(pNode!=NULL) { nodes.push(pNode); pNode=pNode->m_pNext; } while(!nodes.empty()) { pNode=nodes.top(); cout<<pNode->m_nValue<<endl; nodes.pop(); } } //利用递归实现链表结点逆序 void PrintListReversingly_Recursively(ListNode* pHead) { if(pHead!=NULL) { if(pHead->m_pNext!=NULL) { PrintListReversingly_Recursively(pHead->m_pNext); } cout<<pHead->m_nValue<<endl; } } //1->2->3->4->5 int _tmain(int argc, _TCHAR* argv[]) { 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); PrintListReversingly_Iteratively(pNode1); PrintListReversingly_Recursively(pNode1); return 0; }
“过一个平凡无趣的人生实在太容易了,你可以不读书,不冒险,不运动,不写作,不外出,不折腾……但是,人生最后悔的事情就是:我本可以。”——陈素封。