《剑指Offer》面试题:从尾到头打印链表

本文介绍了一种从尾到头打印链表的方法,包括使用递归和迭代两种实现方式,以及如何向链表尾部添加新节点。

题目

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

法一

思路:将链表的指针全部反向,然后输出即可

/*
题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值 
思路:将链表的指针全部反向,然后输出即可 
*/

#include<stdio.h>
#include<string.h>
#include <stdlib.h> 
typedef int  ElementType;
struct ListNode{
    ElementType mValue;
    ListNode *mpNext;
};
//输入一个链表的头结点,反向链表 
//@param  pHead  :头结点的指针 
ListNode* reverseList(ListNode *pHead){
    if(pHead==NULL) {
        return NULL;

    }
    ListNode *cur=pHead; 
    ListNode *pre=NULL;
    ListNode *next;
    while(cur->mpNext!=NULL){
        next=cur->mpNext;//先把当前结点下一个节点保存起来,作为下一次循环的位置 
        cur->mpNext=pre;
        pre=cur;
        cur=next; 
    } 
    cur->mpNext=pre;//将最后一个节点反向链接 
    pHead=cur; //将最后一个节点变为头结点 

    return pHead;
}
void printList(ListNode* pHead){
    if(pHead==NULL){
        return ;
    }
    ListNode *curNode=pHead;
    while(curNode->mpNext!=NULL){

        printf("%d",curNode->mValue);
        curNode=curNode->mpNext;
    }
    printf("%d",curNode->mValue);//输出最后一个节点的信息 
    printf("\n");


}
ListNode* createList()  
{  
    ElementType value;  
    ListNode* pHead = NULL;  
    ListNode* pCur = NULL;  
    do  
    {  
        scanf("%d",&value);  
        if(value != -1)  
        {  
            ListNode *pNew = (ListNode*)malloc(sizeof( ListNode));  
            if(pNew == NULL)  
                exit(EXIT_FAILURE);  
            pNew->mValue = value;  
            pNew->mpNext = NULL;  

            if(pHead == NULL)  
            {  
                pHead = pNew;  
                pCur = pHead;  
            }  
            else  
            {  
                pCur->mpNext = pNew;  
                pCur = pCur->mpNext;  
            }  
        }  
    }while(value != -1);  

    return pHead;  
}  
int main(void){
    //先构造结点数为N的链表
    ListNode *pHead;
    ElemType value;

    pHead=createList();
    //输出正序列表的信息 
    printList(pHead); 
    pHead=reverseList(pHead);
    //输入一个链表的头结点,从尾到头反过来打印出每个结点的值 
    printList(pHead); //反向输出 

    return 0;
}

法二

思路:递归直接输出

实现代码如下:

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

typedef int ElemType;  

 struct Node  
{  
    ElemType mValue;  
    struct Node *mpNext;  
};  

/* 
递归从尾到头打印单链表 
*/  
void PrintListReverse(Node* pHead)  
{  
    if(pHead == NULL)  
        return;  
    if(pHead->mpNext != NULL)  
        PrintListReverse(pHead->mpNext);  
    printf("%d\n",pHead->mValue);  
}  

Node* CreateList()  
{  
    ElemType val;  
    Node* pHead = NULL;  
    Node* pCur = NULL;  
    do  
    {  
        scanf("%d",&val);  
        if(val != -1)  
        {  
            Node* pNew = (Node*)malloc(sizeof(Node));  
            if(pNew == NULL)  
                exit(EXIT_FAILURE);  
            pNew->mValue = val;  
            pNew->mpNext = NULL;  

            if(pHead == NULL)  
            {  
                pHead = pNew;  
                pCur = pHead;  
            }  
            else  
            {  
                pCur->mpNext = pNew;  
                pCur = pCur->mpNext;  
            }  
        }  
    }while(val != -1);  

    return pHead;  
}  

void DestroyList(Node* pHead)  
{  
    if(pHead == NULL)  
        return;  
    Node* p = NULL;  
    while(pHead != NULL)  
    {  
        p = pHead->mpNext;  
        free(pHead);  
        pHead = p;  
    }  
}  
int main()  
{  
    Node* pHead = CreateList();  
    PrintListReverse(pHead);  
    DestroyList(pHead);  
    return 0;  
} 

上面两种方法都可以实现从尾都头打印链表。

最后提供向链表尾部添加新的结点的代码如下

//向链表尾部添加新的结点
ListNode* addNodeToTailInList(ListNode *pHead,int value){
    //根据value构造一个新的结点 
    //ListNode *pNew=new ListNode();
    ListNode *pNew;
    pNew=(ListNode *)malloc(sizeof(struct ListNode));
    pNew->mValue=value;
    pNew->mpNext=NULL; 
    //如果pHead 为空,则新结点就为头结点 
    if(pHead==NULL){
        pHead=pNew;

    }
    ListNode  *temp=pHead;
    while(temp->mpNext!=NULL){
        temp=temp->mpNext;
    } 

    temp->mpNext=pNew;
    return pHead;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值