剑指offfer面试题5:从尾到头打印链表

题目:输入一个链表的头结点,从尾到头反过来打印每个结点的值。

单链表的实现:

1、linklist.h

#ifndef _LINKLIST_H_
#define _LINKLIST_H_

typedef int Elem_Type;

typedef struct LNode
{
    Elem_Type data;
    struct LNode* next;
}LNode,*LinkList;

void init_list(LinkList* phead);
void insert_tail(LinkList* phead,Elem_Type val);
void insert_head(LinkList* phead,Elem_Type val);
void remove_node(LinkList* phead,Elem_Type val);
void clear_list(LinkList* phead);
void destroy_list(LinkList* phead);
void show_list(LinkList* phead);
bool is_Empty(LinkList* phead);
int list_size(LinkList* phead);

#endif

2、linklist.cpp

#include "linklist.h"
#include <cassert>
#include <iostream>
#include <stack>

using namespace std;

//初始化单链表
void init_list(LinkList* phead)
{
    assert(phead != NULL);
    (*phead) = new LNode;
    (*phead)->next = NULL;
}

//尾插
void insert_tail(LinkList* phead, Elem_Type val)
{
    assert(phead != NULL);
    LNode* p = *phead;
    if (NULL == p)
    {
        return;
    }

    while (p->next != NULL)
    {
        p = p->next;
    }

    LNode* newNode = new LNode;
    newNode->data = val;
    newNode->next = NULL;
    p->next = newNode;
}

//头插
void insert_head(LinkList* phead, Elem_Type val)
{
    assert(phead != NULL);
    LNode* p = *phead;
    if (NULL == p)
    {
        return;
    }

    LNode* newNode = new LNode;
    newNode->data = val;
    newNode->next = p->next;
    p->next = newNode;
}

//删除结点
void remove_node(LinkList* phead, Elem_Type val)
{
    assert(phead != NULL);
    LNode* p = *phead;
    if (NULL == p)
    {
        return;
    }

    LNode* ppre = p;
    LNode* pcur = p->next;
    while (pcur != NULL)
    {
        if (pcur->data == val)
        {
            ppre->next = pcur->next;
            delete pcur;
            pcur = ppre->next;
        }
        else
        {
            ppre = pcur;
            pcur = ppre->next;
        }
    }
}

//清空单链表
void clear_list(LinkList* phead)
{
    assert(phead != NULL);
    LNode* p = *phead;
    if (p == NULL)
    {
        return;
    }

    LNode* ptmp = p->next;
    while (ptmp != NULL)
    {
        p = ptmp->next;
        delete ptmp;
        ptmp = p;
    }
    (*phead)->next = NULL;
}

//销毁链表
void destroy_list(LinkList* phead)
{
    assert(phead != NULL);
    LNode* p = *phead;

    LNode* ptmp;
    while (p != NULL)
    {
        ptmp = p->next;
        delete p;
        p = ptmp;
    }
    *phead = NULL;
}

//打印单链表
void show_list(LinkList* phead)
{
    assert(phead != NULL);
    LNode* p = *phead;
    if (p == NULL)
    {
        return;
    }

    while (p->next != NULL)
    {
        cout << p->next->data << " ";
        p = p->next;
    }
    cout << endl;
}

//判空
bool is_Empty(LinkList* phead)
{
    assert(phead != NULL);
    LNode* p = *phead;
    if (p == NULL)
    {
        return true;
    }
    return p->next == NULL;
}

//单链表的大小
int list_size(LinkList* phead)
{
    assert(phead != NULL);
    LNode* p = *phead;
    if (p == NULL)
    {
        return 0;
    }
    int i = 0;
    while (p->next != NULL)
    {
        ++i;
        p = p->next;
    }
    return i;
}

3、test_linklist.cpp

#include "linklist.h"
#include <iostream>

using namespace std;

int main(int argc, char* argv[])
{
    LinkList list;
    init_list(&list);
    insert_tail(&list,5);
    insert_tail(&list,10);
    insert_tail(&list,14);
    insert_head(&list,8);

    show_list(&list);
    //remove_node(&list,5);
    //show_list(&list);

    //cout << is_Empty(&list) << endl;
    //cout << list_size(&list) << endl;

//  clear_list(&list);
//  destroy_list(&list);
//  cout << list_size(&list) << endl;

    printListReversely_iteratively(list);
    printListReversely_recursively(list);
    cout << endl;

    insert_head(NULL,5);

    return 0;
}

解题思路

思路一:遍历单链表的顺序是从头到尾的顺序,可输出的顺序却是从尾到头。也就是说第一个遍历到的结点最后一个输出,而最后一个遍历到的结点是第一个输出。这就是典型的“后进先出”,可以用栈实现这种顺序。

//非递归逆序打印链表
void printListReversely_iteratively(LinkList phead)
{
    assert(phead != NULL);

    stack<LNode*> sta;
    LNode* p = phead->next;
    while (p != NULL)
    {
        sta.push(p);
        p = p->next;
    }

    while (!sta.empty())
    {
        LNode* node = sta.top();
        cout << node->data << " ";
        sta.pop();
    }
    cout << endl;
}

思路二:既然可以用栈实现,而递归在本质上就是一个栈结构,因此也可以用递归来实现。

//函数声明
void printList(LNode* p);

//递归逆序打印链表
void printListReversely_recursively(LinkList phead)
{
    assert(phead != NULL);
    printList(phead->next);
}
//逆序打印链表
void printList(LNode* p)
{
    if (p != NULL)
    {
        if (p->next != NULL)
        {
            printList(p->next);
        }
        cout << p->data << " ";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值