本文參考:http://zhedahht.blog.163.com/blog/static/254111742010819104710337/
題目:有一個複雜鏈表,其結點除了有一個m_pNext指標指向下一個結點外,還有一個m_pSibling指向鏈表中的任一結點或者NULL。其結點的C++定義如下:
struct ComplexNode
{
int m_nValue;
ComplexNode* m_pNext;
ComplexNode* m_pSibling;
};
是一個含有5個結點的該類型複雜鏈表。圖中實線箭頭表示m_pNext指標,虛線箭頭表示m_pSibling指標。為簡單起見,指向NULL的指標沒有畫出。
方法一:最基本的思路就是先不考慮m_pSibling指標項,將原鏈表複製。對於m_pSibling,由於新舊鏈表中結點位置關係是對應的,根據原鏈表中結點的m_pSibling所指結點在原鏈表中的位置序號,就可以確定新鏈表中對應結點的m_pSibling所指的結點。
ComplexNode*Clone(ComplexNode* pHead){ ComplexNode *pNewHead,*pNewTempTail,*pCurrent,*pNewCurrent; pNewHead=pNewTempTail=NULL; //複製鏈表,暫不處理m_pSibling項 for(pCurrent=pHead;pCurrent!=NULL;pCurrent=pCurrent->m_pNext) { ComplexNode * pTemp=newComplexNode; pTemp->m_nValue=pCurrent->m_nValue; pTemp->m_pNext=NULL; pTemp->m_pSibling=NULL; if(pNewHead==NULL) { pNewHead=pTemp; pNewTempTail=pTemp; } else { pNewTempTail->m_pNext=pTemp; pNewTempTail=pTemp; } } /*對新鏈表中每個結點pNewCurrent,求原鏈表中對應位置結點pCurrent的 m_pSibling所直接點的位置index, 然後在新鏈表中找到第index個結點, 讓當pNewCurrent的m_pSibling指向它。*/ pCurrent=pHead,pNewCurrent=pNewHead; while(pCurrent!=NULL) { if(pCurrent->m_pSibling==NULL) {pCurrent=pCurrent->m_pNext; continue;} int index=0; ComplexNode * pTemp; //找pCurrent->m_pSibling在鏈表中的位置 for(pTemp=pHead;pCurrent->m_pSibling!=pTemp;pTemp=pTemp->m_pNext) index++; //找到新鏈表中對應位置的結點 for(pTemp=pNewHead;index!=0;pTemp=pTemp->m_pNext) index--; //賦值給 pNewCurrent的m_pSibling pNewCurrent->m_pSibling=pTemp; //處理下一個結點 pCurrent=pCurrent->m_pNext; pNewCurrent=pNewCurrent->m_pNext; } return pNewHead; }
時間複雜度O(n2),空間複雜度O(1)。
方法二:前面的方法在匹配對應點的時候根據序號來對應,花了較多的時間。這一步可以使用O(n)的輔助空間來提高效率。儲存結點的地址對應關係,<p0,p0'>,<p1,p1'>,...p0,p1等是原鏈表中各結點的地址,p0',p1'等是新鏈表中各結點的地址。使用hash表,hash(p0)=p0',hash(p1)=p1'。。。
方法三:參考文章中的巧妙解法,是直接在原鏈表中儲存結點的對應關係,即暫時把複製的結點插在原結點後面,等把m_pSibling項處理完後再把鏈表分離。步驟:第一步,CloneNodes:第二步,LinkNewNodeSibling:第三步,SeprateNewFromOld:
//Clone every node of the original list,and insert the new node after it.void CloneNodes(ComplexNode* pHead){ComplexNode *pCurrent;pCurrent=pHead;while(pCurrent!=NULL){ComplexNode *pTemp=new ComplexNode;pTemp->m_nValue=pCurrent->m_nValue;pTemp->m_pNext=pCurrent->m_pNext;pTemp->m_pSibling=NULL;pCurrent->m_pNext=pTemp;pCurrent=pTemp->m_pNext;}}//Link every new node's sibling.void LinkNewNodeSibling(ComplexNode* pHead){ComplexNode *pCurrent,*pCurrentClone;for(pCurrent=pHead;pCurrent!=NULL;pCurrent=pCurrent->m_pNext->m_pNext){pCurrentClone=pCurrent->m_pNext;if(pCurrent->m_pSibling!=NULL)pCurrentClone->m_pSibling=pCurrent->m_pSibling->m_pNext;}}//Seperate the new list from original list.ComplexNode* SeparateNewFromOld(ComplexNode* pHead){if(pHead==NULL)return NULL;ComplexNode *pNewHead,*pNewTempTail,*pCurrent;pNewHead=pHead->m_pNext;pNewTempTail=pNewHead;for(pCurrent=pHead;pCurrent!=NULL;pCurrent=pCurrent->m_pNext){pNewTempTail->m_pNext=pCurrent->m_pNext;pCurrent->m_pNext=pCurrent->m_pNext->m_pNext;pNewTempTail=pNewTempTail->m_pNext;pNewTempTail->m_pNext=NULL;} return pNewHead;}//Clone the original list.ComplexNode* Clone(ComplexNode* pHead){CloneNodes(pHead);LinkNewNodeSibling(pHead);return SeparateNewFromOld(pHead);}
時間複雜度O(n),空間複雜度O(1)。