从尾到头打印单链表
题目:输入一个链表的头结点,从尾到头反过来打印出每个节点的值
根据题目,我们知道这是一个带有头结点的单链表对吧,那么我们首先就可以定义一个结构体用来描述这个节点:
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x)
:val(x), next(NULL)
{}
};
下面我呢介绍两种方法解决这个问题
1、递归方法
我们知道,正常来说,有头结点的话,我们直接从头结点遍历去打印就行了,但是呢我们现在是需要逆序打印,所以我们一定需要先到尾节点再打印。
其次,我们知道如果这是一个双向链表,带有prev这个指向前一个节点的指针,那么也可以根据头结点很方便的去打印,直接从头结点开始不断指向前一个节点就好了。
但是,我们现在没有prev这个指针,如果要逆序打印就必须先到最后的尾节点。所以,我们可以用递归的方式去走到最后一个节点,然后再去打印。
下面呢我们通过代码来解释:
void PrintListFromTailToHead_R(ListNode* head)
{
if (head)
{
if (head->next)
PrintListFromTailToHead_R(head->next);
cout << head->val << " ";
}
}
首先,我们判断头结点是否为空,如果为空,那么可以直接退出了,毕竟这个链表就是空的。
如果链表不为空,那么我们呢就需要去判断从头结点开始的下一个节点是否为空,如果不为空,那么就递归走下去,如果为空了,那么就打印,并且往后退,直到退出递归。
下面呢我用图片仔细演示一下递归的过程:
2、利用栈的方法
这一种不利用递归的方式其实很多人都很熟悉,那就是去利用栈的特性。栈是先进后出的特性,所以你只需要不断地往栈里面压入数据,那么第一个进去的数据肯定是最后一个出栈,那么就可以模拟实现递归的效果了。在所有数据都压入栈之后,我们再去选择打印,当栈不为空时,打印栈顶的数据,然后把栈顶元素删掉,这样就可以调到下一个元素了。
代码:
void PrintListFromTailToHead_Stack(ListNode* head)
{
stack<int> s;
ListNode* cur = head;
while (cur)
{
s.push(cur->val);
cur = cur->next;
}
while (!s.empty())
{
cout << s.top() << " ";
s.pop();
}
}
注:在VS2013编译器下实现的代码