面试题【3】链表的逆序打印

题干:

输入链表的头结点,逆序打印出链表的值。

因为每个人 对头结点的理解不一,这里 我分两种情况来写。

第一种,头结点中的数据域不存放数据的;
第二种,头结点中的数据域存放数据的。
上面两种方法,都不会对链表的结构进行改变,本人之前在 菜鸟学习历程【12】链表 讲解过 将链表 结构 改变成 逆序的情况。

如若,有讲述不正确的 地方,还希望得到指正。

(1) 头结点中的数据域不存放数据的
这里写图片描述

这里,你使用 头插 或者 尾插 都无所谓,我个人使用的是 头插法,关键在于 如何 高效 的 从后往前 进行打印?

首先,我们需要遍历到 最后一个结点 ,从最后一个结点 开始打印,再返回上一级 进行打印。。。这样的操作 与 后序递归 很相似,我们也可以使用 后序递归 来完成这个题目,当然 你能想到 使用 栈 也未尝不是一个好方法。

附上代码:

#include <stdio.h>
#include <stdlib.h>

struct LinkNode
{
    int data;
    struct LinkNode *next;
};

typedef struct LinkNode List;
typedef List *LinkList;

void Insert(LinkList &Head)
{

    for (int i = 0; i < 10; i++)
    {
        LinkList tmp = (LinkList)malloc(sizeof(List));
        if (tmp == NULL)
            printf("分配地址失败\n");
        tmp->next = NULL;

        if (Head->next == NULL)
        {
            tmp->data = i;
            Head->next = tmp;
        }
        else
        {
            tmp->data = i;
            tmp->next = Head->next;
            Head->next = tmp;
        }
    }
}

// 由于 这种情况下 头结点 不存放数据;因此,打印时 不该打印头结点 的值
// 因此,先将 Head 指向 下一个结点 ,再调用 递归
void ReversePrint(LinkList Head)
{
    if (Head != NULL && Head->next != NULL)
    {
        Head = Head->next;
        ReversePrint(Head);
        printf("%d\n", Head->data); 
    }
}

void print(LinkList Head)
{
    LinkList tmp = Head->next;
    while (tmp != NULL)
    {
        printf("%d\n", tmp->data);
        tmp = tmp->next;
    }
}

// 这个释放内存的函数 如有争议,可以直接留言 
void myfree(LinkList &Head)
{   
    while (Head != NULL)
    {
        LinkList tmp = Head;
        Head = Head->next;
        free(tmp);
        tmp = NULL;
    }
}

int main()
{
    LinkList Head = (LinkList)malloc(sizeof(List));
    if (Head == NULL)
        printf("分配地址失败\n");
    Head->next = NULL;

    Insert(Head);

    print(Head);

    printf("逆序打印\n");

    ReversePrint(Head);
    myfree(Head);

    return 0;
}

(2)头结点中的数据域存放数据的
这里写图片描述

#include <stdio.h>
#include <stdlib.h>

struct LinkNode
{
    int data;
    struct LinkNode *next;
};

typedef struct LinkNode List;
typedef List *LinkList;

void Insert(LinkList &Head)
{

    for (int i = 1; i < 10; i++)
    {
        LinkList tmp = (LinkList)malloc(sizeof(List));
        if (tmp == NULL)
            printf("分配地址失败\n");
        tmp->next = NULL;

        if (Head->next == NULL)
        {
            tmp->data = i;
            Head->next = tmp;
        }
        else
        {
            tmp->data = i;
            tmp->next = Head->next;
            Head->next = tmp;
        }
    }
}

void ReversePrint(LinkList Head)
{
    if (Head != NULL)
    {
        if (Head->next != NULL)
        {
            ReversePrint(Head->next);
        }
        printf("%d\n", Head->data);
    }
}


void print(LinkList Head)
{
    LinkList tmp = Head;
    while (tmp != NULL)
    {
        printf("%d\n", tmp->data);
        tmp = tmp->next;
    }
}

void myfree(LinkList &Head)
{
    while (Head != NULL)
    {
        LinkList tmp = Head;
        Head = Head->next;
        free(tmp);
        tmp = NULL;
    }
}

int main()
{
    LinkList Head = (LinkList)malloc(sizeof(List));
    if (Head == NULL)
        printf("分配地址失败\n");
    Head->data = 0;
    Head->next = NULL;

    Insert(Head);

    print(Head);

    ReversePrint(Head);

    myfree(Head);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值