复杂链表的复制

本文参考: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)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值