複雜鏈表的複製

    複雜鏈表的概念:ide

    在複雜鏈表中,每一個結點除了有一個_pnext指針指向下一個結點外,還有一個_pSibling指向鏈表中的任意結點或者NULL。以下圖函數

wKiom1cY2x2gFuGTAAAWm0pVDaw768.png

    複雜鏈表每一個結點的結構以下:測試

    //複雜鏈表結點的結構spa

    template<class T>指針

    struct ComplexListNodeorm

    {blog

     ComplexListNode()get

     :_pnext(NULL)it

     ,_pSibling(NULL)io

     { }

    

     ComplexListNode(const T& x)

     :_pnext(NULL)

     ,_pSibling(NULL)

     ,value(x)

     { }

    

     T value;//數據

     ComplexListNode* _pnext;//指向下一個結點

     ComplexListNode* _pSibling;//指向任意結點

    };


    複雜鏈表的複製:

    方法1:

    第一步,複製鏈表的每個結點,並用_pnext連接起來;第二步,設置鏈表每個結點的_pSibling。假設原始鏈表的某個結點N的_pSibling指向結點S,而S的位置可在N前也可在N後,因此要肯定S的位置須要從頭結點開始找,若從頭開始沿着_pnext通過s步找到S,那麼複製鏈表上的N'結點的_pSibling離複製鏈表的頭結點的距離也是沿着_pnext指針s步。因爲定位每一個結點的_pSibling都須要從頭結點開始通過O(n)步才能找到,因此時間複雜度爲O(n^2)。比較浪費時間。


    方法2:

    第一步,複製鏈表的每個結點,並用_pnext連接起來;第二步,設置每一個結點的_pSibling。若是在原始鏈表的結點N的_pSibling指向結點S,那麼複製鏈表時,對應的N'應該指向S'。由於有了哈希表,用O(1)的時間根據S找到S’。這種方法以空間換時間。


    方法3:

    第一步,對應於每個結點,建立一個新的結點,並鏈接在原結點的後邊。以下圖所示:

wKiom1cY5HzhpoQTAAAa1clkMCM236.png    參考代碼:

    //建立每一個新的結點pCloned 分別鏈接到每一個原結點的後邊

    template<class T>

    void ClonedNodes(ComplexListNode<T>* pHead)

    {

     ComplexListNode<T>* pNode = pHead;

     while (pNode != NULL)

     {

     ComplexListNode<T>* pCloned = new ComplexListNode<T>(pNode->value);

     pCloned->_pnext = pNode->_pnext;

     pNode->_pnext = pCloned;

     pNode = pCloned->_pnext;

     }

    }

    第二步,設置複製出來結點的_pSibling,假設原始鏈表的A指向C,那麼對應複製出來的A'對應C'。以下圖所示:

wKiom1cY5mXyPByjAAAc-iXk-fI942.png    參考代碼:   

    //設置複製出來每一個結點的_pSibling的值

    template<class T>

    void ConnectSiblingNodes(ComplexListNode<T>* pHead)

    {

     ComplexListNode<T>* pNode = pHead;

     while (pNode)

     {

     ComplexListNode<T>* pCloned = pNode->_pnext;

     if(pNode->_pSibling != NULL)

     {

     pCloned->_pSibling = pNode->_pSibling->_pnext;

     }

     pNode = pCloned->_pnext;

     }

    }

    第三步,拆分鏈表,奇數位置的結點用_pnext連接起來構成原始鏈表,偶數位置的結點用_pnext連接起來構成複製的複雜鏈表。以下圖所示:

wKiom1cY6GGxYu4TAAAcfEEKMVs018.png    參考代碼:   

    //拆分合並的鏈表,把奇數位置上的結點用_pnext連接起來就是原始鏈表,把偶數位置上的結點用_pnext連接起來就是複製出來的鏈表

    template<class T>

    ComplexListNode<T>* ReconnectNodes(ComplexListNode<T>* pHead)

    {

     ComplexListNode<T>* pNode = pHead;

     ComplexListNode<T>* pClonedHead = NULL;

     ComplexListNode<T>* pClonedNode = NULL;

     if(pNode != NULL)

     {

     pClonedHead = pClonedNode = pHead->_pnext;

     pNode->_pnext = pClonedNode->_pnext;

     pNode = pNode->_pnext;

     }

     while (pNode != NULL)

     {

     pClonedNode->_pnext = pNode->_pnext;

     pClonedNode = pClonedNode->_pnext;

     pNode->_pnext = pClonedNode->_pnext;

     pNode = pNode->_pnext;

     }

     return pClonedHead;

    }


    將以上三步合起來,就是複製的完整過程

    //複製複雜鏈表函數

    template<class T>

    ComplexListNode<T>* Clone(ComplexListNode<T>* pHead)

    {

     ClonedNodes<T>(pHead);

     ConnectSiblingNodes<T>(pHead);

     return ReconnectNodes<T>(pHead);

    }


    測試代碼以下:    

    void test()

    {

     ComplexListNode<double> List1(1.2);

     ComplexListNode<double> List2(1.4);

     ComplexListNode<double> List3(2.3);

     ComplexListNode<double> List4(3.6);

     ComplexListNode<double> List5(4.5);

    

     List1._pnext = &List2;

     List2._pnext = &List3;

     List3._pnext = &List4;

     List4._pnext = &List5;

     List1._pSibling = &List3;

     List4._pSibling = &List2;    

     List2._pSibling = &List5;

    

     ComplexListNode<double>* pHead = Clone(&List1);

    }

相關文章
相關標籤/搜索