• 剑指offer--面试题5


    到现在为止,看过的书+代码有一定量了,并且也参加了个比赛,给自己的总体感觉:编程需要的是灵活的头脑,书里的东西只是讲个规则、思想,其实际实现可以千差万别!   潜在的规则+灵活的思维 = 程序!

    在做面试题5时,发现Utilities文件夹下的内容太好了,基本上是那些数据结构的实现:链表、二叉树、树等(缺个图),准备通过学习这些代码来深入理解各个数据结构及其接口/成员函数。

    拿该题来说,解决单链表!!!

    题目:逆序打印单链表

    一、自己写单链表类及其操作

    花了一下午时间,无语了。。。

    1、List.h

    //单链表数据结构及基本操作
    
    //最大节点数
    const int MAXLENGTH = 50;
    //节点
    struct ListNode
    {
        int m_Value;
        ListNode* m_pNext;
    };
    
    //List类
    class List
    {
    private:
        ListNode LNode;
        int MaxLength;
    public:
        //constructor and deconstructor
        List();
        virtual ~List();
        //单链表操作
        //1. 创建节点
        ListNode* CreateListNode(int value);
        //2. 创建链表或者将节点加到链尾
        void CreateFrontOrAddToTail(ListNode** pHead, int value);
        //3. 在第i个节点之前插入新的节点
        void ListInsert(ListNode* pHead, int i, int value);
        //4. 删除value=e的节点
        void RemoveListNode(ListNode** pHead,int value);
        //5. 查找第一个value=e的节点
        int FindListNode(ListNode* pHead,int value);
        //6. 销毁链表
        void DestoryList(ListNode* pHead);
        //7. 链表元素个数
        int ListLength(ListNode* pHead);
    };

    2、List.cpp

    //List.cpp
    
    #include "List.h"
    #include <iostream>
    
    List::List()
    {
        LNode.m_Value = 0;
        LNode.m_pNext = NULL;
        MaxLength = MAXLENGTH;
    }
    
    List::~List()
    {
    
    }
    
        //1. 创建节点
    ListNode* List::CreateListNode(int value)
    {
        ListNode* pNew = new ListNode;
        pNew->m_Value = value;
        pNew->m_pNext = NULL;
    }
        //2. 创建链表或者将节点加到链尾
    void List::CreateFrontOrAddToTail(ListNode** pHead, int value)
    {
        if(pHead == NULL)
            return;
        ListNode* pNew = CreateListNode(value);
        if(*pHead == NULL) //空链表
            *pHead = pNew;
        else
        {
            ListNode* pNode = *pHead;
            while(pNode->m_pNext != NULL)
                pNode = pNode->m_pNext;
            pNode->m_pNext = pNew;
        }
    
    }
        //3. 在第i个节点之前插入新的节点
    void List::ListInsert(ListNode* pHead, int i, int value)
    {
        if(pHead == NULL || i >= MaxLength)
            return;
        ListNode* pNew = CreateListNode(value);
        ListNode* pNode = *pHead;
        ListNode* preNode = *pHead;
        i--;
        while(i && pNode->m_pNext != NULL)
        {
            preNode = pNode;
            pNode = pNode->m_pNext;
            i--;
        }
        if(i == 0)
        {
            preNode->m_pNext = pNew;
            pNew->m_pNext = pNode;
        }
        else
            cout<<"Failed!"<<endl;
    }
        //4. 删除value=e的第一个节点
    bool List::RemoveListNode(ListNode** pHead,int value)
    {
        if(pHead == NULL || *pHead == NULL)
            return false;
        ListNode* pToBeDeleted = NULL;
        if((*pHead)->m_Value == value)
        {
            pToBeDeleted = *pHead;
            *pHead = (*pHead)->m_pNext;
        }
        else
        {
            ListNode* pNode = *pHead;
            while(pNode->m_pNext != NULL && pNode->m_pNext->m_Value != value)
                pNode = pNode->m_pNext;
            if(pNode->m_pNext != NULL && pNode->m_pNext->m_Value == value)
            {
                pToBeDeleted = pNode->m_pNext;
                pNode->m_pNext = pNode->m_pNext->m_pNext;
            }
        }
        if(pToBeDeleted != NULL)
        {
            delete pToBeDeleted;
            pToBeDeleted = NULL;
            return true;
        }
            return false;
    }
    
        //5. 查找第一个value=e的节点,返回其位置
    int List::FindListNode(ListNode* pHead,int value)
    {
        int i = 1;
        ListNode* pNode = pHead;
        while(pNode != NULL && pNode->m_Value != value)
        {
            i++;
            pNode = pNode->m_pNext;
        }
        if(pNode != NULL && pNode->m_Value == value)
            return i;
        else
            return 0;
    
    }
        //6. 销毁链表
    void List::DestoryList(ListNode* pHead)
    {
        ListNode* pNode = pHead;
        while(pHead != NULL)
        {
            pNode = pHead;
            pHead = pHead->m_pNext;
            delete pNode;
        }
    }
        //7. 链表元素个数
    int List::ListLength(ListNode* pHead)
    {
        ListNode* pNode = pHead;
        int i = 0;
        while(pNode != NULL)
        {
            i++;
            pNode = pNode->m_pNext;
        }
        return i;
    }

    未测试过。。。因为想继续做面试题5了,进度太慢了!!!

    二、面试题5整理:

     逆序打印单链表,首先想到的便是通过扫描链表,并同时用栈存储每个值,最后利用栈的LIFO特点打印即可。但是,鉴于自己的水平,并没有用过C++中stl里的stack,因此想了另一种方法,即将扫描链表时所得到的值存入到一个数组中,最后逆序打印即可。这种方法固然可行,但效率上必然低于栈的。所以综合以上分析,又学习了stl中的stack,具体见上一篇博客。最后,怎么也没想到可以用递归的方式求解。。。

    根据作者代码思想,做了如下改动:

    void PrintListReversingly_Iteratively(ListNode* pHead)
    {
        std::stack<int> nodes;
    
        ListNode* pNode = pHead;
        while(pNode != NULL)
        {
            nodes.push(pNode->m_nValue);
            pNode = pNode->m_pNext;
        }
        
        int value;
        while(!nodes.empty())
        {
            value = nodes.top();
            printf("%d	", value);
            nodes.pop();
        }
    }

    这里将stack的元素设置为了m_nValue的类型,仔细想想后,认为还是原代码更合理,原因如下:

    原代码中,节点地址入栈,因此栈中每个元素所占存储是固定的,在32位操作系统下,指针(地址)占4字节;但如果存储的是节点数据元素,那么每个元素所占存储很可能大于4字节;

    void PrintListReversingly_Recursively(ListNode* pHead)
    {
        if(pHead == NULL)
        {
            return;
        }
        else
        {
            PrintListReversingly_Recursively(pHead->m_pNext); 
            printf("%d	", pHead->m_nValue);
        }
    }
    清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己 -- 共勉
  • 相关阅读:
    两个单链表的第一个公共节点
    对于混沌定义中三个条件的理解
    sort()函数使用详解
    C++优先队列详解
    第一次只出现一个的字符
    丑数
    把数组排成最小的数
    从1到n整数中1的个数
    git相关知识
    文件处理(如果文件存在则追加,不存在则生成多级文件夹以及txt目录)
  • 原文地址:https://www.cnblogs.com/hello-yz/p/3240213.html
Copyright © 2020-2023  润新知