剑桥offer面试题:从尾到头打印链表|题目——输入一个链表的头节点,从尾到头反过来打印出每个结点的值。(打印链表的值只是一个可读操作,最好不要修改链表的结构)

题目——输入一个链表的头节点,从尾到头反过来打印出每个结点的值。(打印链表的值只是一个可读操作,最好不要修改链表的结构)

算法1——利用栈“先进后出”

分析:遍历是从头到尾访问结点中的value,而打印却是从尾到头。也就是说第一个遍历到的结点需要最后一个输出,最后一个遍历到的结点需要第一个输出,以此看来可以用到栈的特性“先进后出”。每次遍历一个结点,将其结点的value入栈,等遍历完所有结点,再将栈中的值以此出栈,那value值的顺序刚好逆序输出。

算法2——“递归”

分析:递归在本质上就是一个栈结构,从头开始每访问一个结点,先递归输出它后面的结点

注意:如果链表很长,使得递归调用层次很深,可能会导致函数调用栈溢出。基于循环的代码显式用栈鲁棒性好一点。

两个算法的代码如下:

 

#include<iostream>
#include<stack>
#include<assert.h>
using namespace std;

struct ListNode
{
    int m_value;
    ListNode* m_pNext;
};

void InitList(ListNode* pHead)
{
    assert(pHead != NULL);
    pHead->m_pNext = NULL;
}

void PrintListendtobegin1(ListNode* pHead)//算法1
{
    if (pHead == NULL)
    {
        return;
    }
    stack<ListNode*> Node;
    ListNode* ptr = pHead->m_pNext;//从第一个结点开始(不是头节点)
    while (ptr != NULL)//从第一个开始遍历并将结点逐一入栈
    {
        Node.push(ptr);
        ptr = ptr->m_pNext;
    }
    while (!Node.empty())//栈不为空时,循环获取栈顶结点,打印结点的value值后,将此节点出栈
    {
        ptr = Node.top();
        cout << ptr->m_value << " ";
        Node.pop();
    }
    cout << endl;
}

void PrintListendtobegin2(ListNode* pHead)//算法2
{
    if (pHead != NULL)
    {
        if (pHead->m_pNext != NULL)
        {
            PrintListendtobegin2(pHead->m_pNext);
        }
        cout << pHead->m_value << " ";
    }
}

int main()
{
    ListNode ListHead;//定义一个链表
    InitList(&ListHead);//初始化链表
    ListNode* p;
    ListNode* head = &ListHead;//定义一个指向链表头节点的指针,用作插入新节点
    int value;
    for (int i = 5; i > 0; --i)//头插法插入新节点
    {
        p = (ListNode*)malloc(sizeof(ListNode));
        assert(p != NULL);
        p->m_value = i;
        p->m_pNext = head->m_pNext;
        head->m_pNext = p;
    }
    //PrintListendtobegin1(&ListHead);
    ListNode* ph = (&ListHead)->m_pNext;
      PrintListendtobegin2(ph);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宠宠熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值