单链表 删除倒数第m个元素的实现

#include<iostream>
#include<iomanip>
using namespace std;

struct Node
{
    public:
        Node():val(0),next(NULL){}
        Node(int v):val(v),next(NULL){}
        int val;
        Node* next;
};

class NodeManager
{
    public:
        NodeManager(){pHead = NULL;};

        //尾插法插入一个元素
        void push_back(int val)
        {
            //第一个元素涉及head指针指向,所以单独处理
            if (pHead == NULL)
            {
                pHead = new Node(val);
            }
            else//非第一个元素找到队尾插入此元素
            {
                Node* pNewNode = new Node(val);
                Node* pCurrent = pHead;
                while(pCurrent->next)
                {
                    pCurrent = pCurrent->next;
                }

                pCurrent->next = pNewNode;

            }
        }

        virtual ~NodeManager()
        {
            Node* pCurrent = pHead;

            while(pCurrent)
            {
                pHead = pCurrent->next;

                cout << "delet address: " << hex << pCurrent << endl;
                delete pCurrent;
                pCurrent = pHead;
            }
        }

        void showList()
        {
            Node* pCurrent = pHead;
            while(pCurrent)
            {
                cout<< "val = " << pCurrent->val << "  myAddress = 0x" << hex << pCurrent << "    nextAddress = 0x" << hex << pCurrent->next << dec << endl;
                pCurrent = pCurrent->next;
            }
        }

        int getListNumber() //获取链表节点长度
        {
            int nTotalNum = 0;
            Node* pCurrent = pHead;
            while(pCurrent)
            {
                pCurrent = pCurrent->next;
                ++nTotalNum;
            }
            return nTotalNum;
        }

        Node* removeNthFromEnd(int n)  //用普通方法进行删除倒数第n个元素的处理
        {
            //计数倒数第n个是整数第几个
            int nTotalNum = getListNumber();
            int nObjNum = nTotalNum -n +1;
            cout << "nObjNum = " << nObjNum << endl;

            //删除第一个元素特别, 要动head指针的位置 ,所以特别拎出来处理
            if (nObjNum == 1)
            {
                Node* pObj = pHead;
                pHead = pObj->next;
                delete pObj; pObj = NULL;
                return pHead;
            }

            //找到第n-1个元素。第n个元素是待删除元素。 n-1元素执行n+1元素,然后删掉第n个元素
            Node* pCurrent = pHead; //最终指向第n-1个元素
            int nCurNum = 1;

            while(nCurNum != nObjNum - 1)
            {
               pCurrent = pCurrent->next;
               ++nCurNum;
            }

            Node* pObj = pCurrent->next; //第n个元素

            pCurrent->next = pObj->next;
            delete pObj; pObj = NULL;

            return pHead;
        }

/* 声明两个节点指针,快指针先向前移动 N 步,然后快慢节点指针一起向前移动,直到快指针遍历完毕,此时慢节点指针会指向倒数第 N+1 个节点元素。
 注意,如果快指针向前移动 N 步已经为空,则说明我们要删除第1个元素。*/

        Node* removeNthFromEnd2(int n)   //只循环一遍删除一个倒数第n个元素
        {
            Node* pFast = pHead;
            Node* pSlow = pHead;

            int nCur = 0;
            while(nCur < n)
            {
                if (pFast->next == NULL)
                {
                    Node* pCurrent = pHead;
                    pHead = pHead->next;

                    cout << "need delete element: " << pCurrent->val << endl;

                    delete pCurrent;
                    pCurrent = NULL;

                    return pHead;
                }

                pFast = pFast->next;
                ++nCur;
            }

            while(pFast->next)
            {
                pSlow = pSlow->next;
                pFast = pFast->next;
            }

            Node* pNeedDeleteNode = pSlow->next;
            pSlow->next = pNeedDeleteNode->next;

            cout << "need delete element: " << pNeedDeleteNode->val << endl;
            delete pNeedDeleteNode;
            pNeedDeleteNode = NULL;

            return pHead;

        }
    private:
        Node* pHead;
};

int main()
{
    NodeManager manager;
    manager.push_back(1);
    manager.push_back(2);
    manager.push_back(3);

    manager.showList();

    cout<<"======="<<endl;
//    manager.removeNthFromEnd(2);//删除倒数第2个
    manager.removeNthFromEnd2(3);//删除倒数第2个
    manager.showList();
}

 

posted @ 2020-11-18 20:34  哈哈不是嘎嘎  阅读(129)  评论(0编辑  收藏  举报