• 《剑指offer》第六题:从尾到头打印链表


    // 面试题6:从尾到头打印链表
    // 题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。
    
    //此处注意导入顺序
    #include <stack>
    #include "List.h"
    
    void PrintListReversingly_Iteratively(ListNode* pHead)
    {
        //方法1:用栈实现, 先入后出保存后打印
        std::stack<ListNode*> nodes;
    
        ListNode* pNode = pHead;
        while (pNode != nullptr) //寻找链表尾部并保存
        {
            nodes.push(pNode);
            pNode = pNode->m_pNext;
        }
    
        while (!nodes.empty()) //打印栈
        {
            pNode = nodes.top();
            printf("%d	", pNode->m_nValue);
            nodes.pop();
        }
    }
    
    void PrintListReversingly_Recursively(ListNode* pHead)
    {
        //方法2:递归实质上也是一种栈, 访问下一节点并打印本节点值
        ListNode* pNode = pHead;
        if (pNode != nullptr) //当前节点不是尾节点
        {
            if (pNode->m_pNext != nullptr) //下一节点不是尾节点
            {
                PrintListReversingly_Recursively(pNode->m_pNext); //打印下一节点
            }
            printf("%d	", pNode->m_nValue); //打印当前节点
        }
    }
    // ====================测试代码====================
    void Test(ListNode* pHead)
    {
        PrintList(pHead);
        PrintListReversingly_Iteratively(pHead);
        printf("
    ");
        PrintListReversingly_Recursively(pHead);
    }
    
    // 1->2->3->4->5
    void Test1()
    {
        printf("
    Test1 begins.
    ");
    
        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);
    }
    
    // 只有一个结点的链表: 1
    void Test2()
    {
        printf("
    Test2 begins.
    ");
    
        ListNode* pNode1 = CreateListNode(1);
    
        Test(pNode1);
    
        DestroyList(pNode1);
    }
    
    // 空链表
    void Test3()
    {
        printf("
    Test3 begins.
    ");
    
        Test(nullptr);
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
    
        return 0;
    }
    测试代码
    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================
    
    struct ListNode
    {
        int       m_nValue;
        ListNode* m_pNext;
    };
    
    __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.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 = nullptr; //新建节点指针域为空指针
    
        return pNode;
    }
    
    //连接两个节点
    void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
    {
        if (pCurrent == nullptr) //当前节点是否存在
        {
            printf("Error to connect two nodes.
    ");
            exit(1);
        }
    
        pCurrent->m_pNext = pNext; //当前节点指针域指向下一节点
    }
    
    //打印当前节点值
    void PrintListNode(ListNode* pNode)
    {
        if (pNode == nullptr)
        {
            printf("The node is nullptr
    ");
        }
        else
        {
            printf("The key in node is %d.
    ", pNode->m_nValue);
        }
    }
    
    //从头到尾打印整个链表
    void PrintList(ListNode* pHead)
    {
        printf("PrintList starts.
    ");
    
        ListNode* pNode = pHead;
        while (pNode != nullptr)
        {
            printf("%d	", pNode->m_nValue);
            pNode = pNode->m_pNext;
        }
    
        printf("
    PrintList ends.
    ");
    }
    
    //删除整个链表
    void DestroyList(ListNode* pHead)
    {
        ListNode* pNode = pHead;
        while (pNode != nullptr)
        {
            pHead = pHead->m_pNext; //下一节点作为头节点
            delete pNode; //删除当前节点
            pNode = pHead; //新头节点
        }
    }
    
    //新建节点并添加到链表末尾
    //由于会改动头节点,因此头节点pHead为指向指针的指针,
    void AddToTail(ListNode** pHead, int value)
    {
        ListNode* pNew = new ListNode();
        pNew->m_nValue = value;
        pNew->m_pNext = nullptr;
    
        if (*pHead == nullptr)
        {
            *pHead = pNew; //如果为空链表,新插入的节点就是链表头节点
        }
        else
        {
            ListNode* pNode = *pHead;
            while (pNode->m_pNext != nullptr) //找到链表末尾
                pNode = pNode->m_pNext;
    
            pNode->m_pNext = pNew; //链表末尾节点指向新节点
        }
    }
    
    //找到并移除值为value的第一个节点
    //同样注意头指针是指向指针的指针
    void RemoveNode(ListNode** pHead, int value)
    {
        if (pHead == nullptr || *pHead == nullptr)
            return;
    
        ListNode* pToBeDeleted = nullptr; //用于保存需要删除的节点地址
        if ((*pHead)->m_nValue == value) //检查头节点
        {
            pToBeDeleted = *pHead;
            *pHead = (*pHead)->m_pNext;
        }
        else
        {
            ListNode* pNode = *pHead;
            while (pNode->m_pNext != nullptr && pNode->m_pNext->m_nValue != value) 
                pNode = pNode->m_pNext; //找到链表末尾或者找到目标值所在节点的前一节点
    
            if (pNode->m_pNext != nullptr && pNode->m_pNext->m_nValue == value)
            {
                pToBeDeleted = pNode->m_pNext; //记录下一节点为待删除节点
                pNode->m_pNext = pNode->m_pNext->m_pNext; //当前节点指向下下一节点
            }
        }
    
        if (pToBeDeleted != nullptr)
        {
            delete pToBeDeleted;
            pToBeDeleted = nullptr;
        }
    }
    List.cpp

    分析:创建了一个大小为n的栈来存放值。

    时间复杂度:O(n) = O(n+n), 空间复杂度:O(n)。

    牛客网需要返回一个vector,往vector中添加一个数据v.push_back(data)。

    /**
    *  struct ListNode {
    *        int val;
    *        struct ListNode *next;
    *        ListNode(int x) :
    *              val(x), next(NULL) {
    *        }
    *  };
    */
    class Solution {
    public:
        vector<int> printListFromTailToHead(ListNode* head) {
            
            std::stack<ListNode*> nodes;
            std::vector<int> ArrayList;
            ListNode* pNode = head;
            while (pNode != nullptr)
            {
                nodes.push(pNode);
                pNode = pNode->next;
            }
            while (!nodes.empty())
            {
                pNode = nodes.top();
                ArrayList.push_back(pNode->val);
                nodes.pop();
            }
            return ArrayList;
        }
    };
    牛客网提交代码
  • 相关阅读:
    win8平板App文件上传
    win8 APP中网页js如何触发后台的ScriptNotify方法
    lsof list open files
    python下的一个人脸识别包
    mysql hex() and unhex()
    git 补丁git formatpatch
    perl sort
    git 分支无法checkout的解决办法
    PERL 语言中的q,qw,qr,qx,qq......符号用法总结
    perl 的真假值
  • 原文地址:https://www.cnblogs.com/ZSY-blog/p/12510946.html
Copyright © 2020-2023  润新知