剑指offer面试题5

来源:互联网 发布:食品行业数据 编辑:程序博客网 时间:2024/05/29 19:31

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

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

预备知识:

链表结点定义:

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

链表的操作有:创建结点,插入结点,删除结点,遍历结点等

//创建链表结点ListNode* CreateListNode(int value){    ListNode* pNode = new ListNode(); //结构体起始指针(头指针)    pNode->m_nValue = value;    pNode->m_pNext = NULL;    return pNode;}//连接链表结点void ConnectListNodes(ListNode* pCurrent, ListNode* pNext){    if(pCurrent == NULL)    {        printf("Error to connect two nodes.\n");        exit(1);    }    pCurrent->m_pNext = pNext;}//输出链表结点void PrintListNode(ListNode* pNode){     if(pNode == NULL)    {        printf("The node is NULL\n");    }    else    {        printf("The key in node is %d.\n", pNode->m_nValue);    }}//遍历链表并打印void PrintList(ListNode* pHead){    printf("PrintList starts.\n");        ListNode* pNode = pHead;    while(pNode != NULL)    {        printf("%d\t", pNode->m_nValue);        pNode = pNode->m_pNext;    }    printf("\nPrintList ends.\n");}//销毁链表(每一个结点都要销毁)void DestroyList(ListNode* pHead){    ListNode* pNode = pHead;    while(pNode != NULL)    {        pHead = pHead->m_pNext; //一个一个结点的销毁        delete pNode;        pNode = pHead;    }}//向链表尾部添加结点void AddToTail(ListNode** pHead, int value){    ListNode* pNew = new ListNode();    pNew->m_nValue = value; //初始化    pNew->m_pNext = NULL;    if(*pHead == NULL)    {        *pHead = pNew;    }    else    {   //在结点的尾部添加        ListNode* pNode = *pHead;        while(pNode->m_pNext != NULL)            pNode = pNode->m_pNext;        pNode->m_pNext = pNew;    }}//移去结点void RemoveNode(ListNode** pHead, int value){    if(pHead == NULL || *pHead == NULL)        return;    ListNode* pToBeDeleted = NULL;    if((*pHead)->m_nValue == value) //刚好等于这个值    {        pToBeDeleted = *pHead;        *pHead = (*pHead)->m_pNext; //指针改变    }    else    {        ListNode* pNode = *pHead;        while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)            pNode = pNode->m_pNext; //遍历        if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value) //遍历找到了这个值        {            pToBeDeleted = pNode->m_pNext;            pNode->m_pNext = pNode->m_pNext->m_pNext; //指针改变        }    }    if(pToBeDeleted != NULL)    {        delete pToBeDeleted; //销毁        pToBeDeleted = NULL;    }}


思路:1. 把链表中结点的指针反过来,改变链表的反向,然后就可以从头到尾输出,但是该方法会改变原来链表的结果

            2.根据题目的要求遍历顺序是从头到尾,而输出是从尾到头,因此可以使用栈来实现这种顺序,即通过构建一个栈(后入向出)来实现,STL中有一个stack。(显栈)

            3.由于递归本质上是一个栈结构,因此可以使用递归来实现,但是当链表非常长的时候,可能导致调用栈溢出。(隐栈)

代码:

List.h

struct ListNode{    int       m_nValue;    ListNode* m_pNext;};//使用标识符:_declspec(dllimport)表明函数是从动态库中引入的 (孙鑫VC++ 712)__declspec( dllexport ) ListNode* CreateListNode(int value);__declspec( dllexport ) void ConnectListNodes(ListNode* pCurrent, ListNode* pNext);__declspec( dllexport ) void PrintListNode(ListNode* pNode);__declspec( dllexport ) void PrintList(ListNode* pHead);__declspec( dllexport ) void DestroyList(ListNode* pHead);__declspec( dllexport ) void AddToTail(ListNode** pHead, int value);__declspec( dllexport ) void RemoveNode(ListNode** pHead, int value);

List.cpp

#include "stdafx.h"#include "list.h"#include <stdio.h>#include <stdlib.h>//创建链表结点ListNode* CreateListNode(int value){    ListNode* pNode = new ListNode(); //结构体起始指针(头指针)    pNode->m_nValue = value;    pNode->m_pNext = NULL;    return pNode;}//连接链表结点void ConnectListNodes(ListNode* pCurrent, ListNode* pNext){    if(pCurrent == NULL)    {        printf("Error to connect two nodes.\n");        exit(1);    }    pCurrent->m_pNext = pNext;}//输出链表结点void PrintListNode(ListNode* pNode){     if(pNode == NULL)    {        printf("The node is NULL\n");    }    else    {        printf("The key in node is %d.\n", pNode->m_nValue);    }}//遍历链表并打印void PrintList(ListNode* pHead){    printf("PrintList starts.\n");        ListNode* pNode = pHead;    while(pNode != NULL)    {        printf("%d\t", pNode->m_nValue);        pNode = pNode->m_pNext;    }    printf("\nPrintList ends.\n");}//销毁链表(每一个结点都要销毁)void DestroyList(ListNode* pHead){    ListNode* pNode = pHead;    while(pNode != NULL)    {        pHead = pHead->m_pNext; //一个一个结点的销毁        delete pNode;        pNode = pHead;    }}//向链表尾部添加结点void AddToTail(ListNode** pHead, int value){    ListNode* pNew = new ListNode();    pNew->m_nValue = value; //初始化    pNew->m_pNext = NULL;    if(*pHead == NULL)    {        *pHead = pNew;    }    else    {   //在结点的尾部添加        ListNode* pNode = *pHead;        while(pNode->m_pNext != NULL)            pNode = pNode->m_pNext;        pNode->m_pNext = pNew;    }}//移去结点void RemoveNode(ListNode** pHead, int value){    if(pHead == NULL || *pHead == NULL)        return;    ListNode* pToBeDeleted = NULL;    if((*pHead)->m_nValue == value) //刚好等于这个值    {        pToBeDeleted = *pHead;        *pHead = (*pHead)->m_pNext; //指针改变    }    else    {        ListNode* pNode = *pHead;        while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)            pNode = pNode->m_pNext; //遍历        if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value) //遍历找到了这个值        {            pToBeDeleted = pNode->m_pNext;            pNode->m_pNext = pNode->m_pNext->m_pNext; //指针改变        }    }    if(pToBeDeleted != NULL)    {        delete pToBeDeleted; //销毁        pToBeDeleted = NULL;    }}

main.cpp

#include "stdafx.h"#include "..\Utilities\List.h"#include <stack>  //STL: push,pop//方法1:构建一个栈(后进先出)来实现void PrintListReversingly_Iteratively(ListNode* pHead){    std::stack<ListNode*> nodes;    ListNode* pNode = pHead;      //栈顶    while(pNode != NULL)    {        nodes.push(pNode);       //先入栈        pNode = pNode->m_pNext;  //指针向上移到    }    while(!nodes.empty())    {        pNode = nodes.top();            //栈顶        printf("%d\t", pNode->m_nValue);//先输出值         nodes.pop(); //结点出栈,同时栈顶改变    }}//方法2:递归本质上是一个栈结构,因此可以使用递归来实现void PrintListReversingly_Recursively(ListNode* pHead) //层级过深,可能导致调用栈溢出{    if(pHead != NULL)    {        if (pHead->m_pNext != NULL)        {            PrintListReversingly_Recursively(pHead->m_pNext);        }         printf("%d\t", pHead->m_nValue);    }}void Test(ListNode* pHead){    PrintList(pHead);    PrintListReversingly_Iteratively(pHead); //显示栈实现    printf("\n");    PrintListReversingly_Recursively(pHead);  //隐式栈实现}// 1->2->3->4->5void Test1(){    printf("\nTest1 begins.\n");//创建单个结点    ListNode* pNode1 = CreateListNode(1);    ListNode* pNode2 = CreateListNode(2);    ListNode* pNode3 = CreateListNode(3);    ListNode* pNode4 = CreateListNode(4);    ListNode* pNode5 = CreateListNode(5);//连接链表结点    ConnectListNodes(pNode1, pNode2);    ConnectListNodes(pNode2, pNode3);    ConnectListNodes(pNode3, pNode4);    ConnectListNodes(pNode4, pNode5);    //测试Test(pNode1);//销毁栈    DestroyList(pNode1);}// 只有一个结点的链表: 1void Test2(){    printf("\nTest2 begins.\n");    ListNode* pNode1 = CreateListNode(1);    Test(pNode1);    DestroyList(pNode1);}// 空链表void Test3(){    printf("\nTest3 begins.\n");    Test(NULL);}int _tmain(int argc, _TCHAR* argv[]){    Test1();    Test2();    Test3();    return 0;}


/********************7月15日********************************/

// 面试题5.cpp : 定义控制台应用程序的入口点。////面试题5:从尾到头打印链表#include "stdafx.h"#include <stack>struct ListNode{intm_nKey;ListNode*m_pNext;};/********链表的基本操作*************///创建结点ListNode* CreateListNode(int value){ListNode* pNode = new ListNode();pNode->m_nKey = value;pNode->m_pNext= NULL;return pNode;}//链接结点void ConnectListNode(ListNode* pNode1, ListNode* pNode2){if(pNode1 == NULL)return;pNode1->m_pNext = pNode2;}//遍历链表 void PrintListNode(ListNode* pHead){if(pHead == NULL)return;ListNode* pNode = pHead;while(pNode != NULL){printf("%d ", pNode->m_nKey);pNode = pNode->m_pNext;}printf("\n");}//销毁链表void DestroyListNode(ListNode* pHead){ListNode* pNode = pHead;while(pNode != NULL){pNode = pNode->m_pNext;delete pHead;pHead = pNode;}}/************面试题5的功能****/void PrintListReversingly_Iteratively(ListNode* pHead){std::stack<ListNode*> nodes;ListNode* pNode = pHead;while(pNode != NULL){nodes.push(pNode); //结点入栈pNode = pNode->m_pNext;}while(!nodes.empty()){pNode = nodes.top();  //栈顶元素printf("%d ", pNode->m_nKey);nodes.pop();          //出栈}printf("\n");}void PrintListReversingly_Recursively(ListNode* pHead){if(pHead != NULL){if(pHead->m_pNext != NULL)PrintListReversingly_Recursively(pHead->m_pNext);printf("%d ", pHead->m_nKey);}}/***********测试链表基本功能*****************/void Test1(){//创建链表结点ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);//连接链表结点ConnectListNode(pNode1,pNode2);ConnectListNode(pNode2,pNode3);ConnectListNode(pNode3,pNode4);ConnectListNode(pNode4,pNode5);ConnectListNode(pNode5,pNode6);//打印链表PrintListNode(pNode1);//销毁链表DestroyListNode(pNode1);}void Test2(){//创建链表结点ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);//连接链表结点ConnectListNode(pNode1,pNode2);ConnectListNode(pNode2,pNode3);ConnectListNode(pNode3,pNode4);ConnectListNode(pNode4,pNode5);ConnectListNode(pNode5,pNode6);//打印链表PrintListReversingly_Iteratively(pNode1);//销毁链表DestroyListNode(pNode1);}void Test3(){//创建链表结点ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);//连接链表结点ConnectListNode(pNode1,pNode2);ConnectListNode(pNode2,pNode3);ConnectListNode(pNode3,pNode4);ConnectListNode(pNode4,pNode5);ConnectListNode(pNode5,pNode6);//打印链表PrintListReversingly_Recursively(pNode1);printf("\n");//销毁链表DestroyListNode(pNode1);}void Test4(){//创建链表结点ListNode* pNode1 = CreateListNode(1);//打印链表//PrintListReversingly_Iteratively(pNode1);PrintListNode(pNode1);//销毁链表DestroyListNode(pNode1);}int _tmain(int argc, _TCHAR* argv[]){Test1();Test2();Test3();Test4();return 0;}



0 0
原创粉丝点击