面试题5:从尾到头打印链表
题目:输入一个链表的头结点,从尾到头反过来打印出每个节点的值。
分析
这道题有如下几种解决方案:
- 将链表逆置,然后顺次打印
- 递归方案
- 迭代方案
如果逆置链表的话,会改变链表原先的结构。我们可以在面试时询问面试过是否可以改变链表,如果是肯定的回答,就可以采用这种办法。否则只能采用后面的方法。
逆置链表也很简单,只需要从第二个节点开始,顺次摘取一个节点头插就可以。
代码如下
list* PrintListInReversedOrder(list* head)
{
if(head==NULL || head->next==NULL)
return head;
list* tmp=NULL;
list* cur=head->next;
head->next=NULL;
while(cur!=NULL)
{
tmp=cur->next;
cur->next=head;
head=cur;
cur=tmp;
}
cur=head;
while(cur!=NULL)
{
cout << cur->data << " ";
cur=cur->next;
}
cout << endl;
return head;
}
递归方案很简单,如果当前函数参数所指向的节点是尾节点,则打印之。否则先打印它的下一个节点即可。
代码如下
void PrintListInReversedOrder(list* head)
{
if(head==NULL)
return;
PrintListInReversedOrder(head->next);
cout << head->data << " ";
}
但如果链表太长,采用递归的话可能会导致 Stack OverFlow,所以更好的办法是用循环来控制。而递归在本质上就是一个栈结构(系统栈),所以我们可以用自定义的栈(数据结构栈)来模拟递归的行为以实现这种效果
代码如下
#include<stack>
void PrintListInReversedOrder(list* head){
//此处不用判断head是否为空,并非忘记
stack<list*> s;
list* cur=head;
while(cur!=NULL)
{
s.push(cur);
cur=cur->next;
}
while(!s.empty())
{
cout << s.top()->data << " ";
s.pop();
}
}
以上
如果你有任何想法或是可以改进的地方,欢迎和我交流!
完整代码及测试用例在github上:[点我前往]()