复杂链表的复制

题目:有一个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL。请完成函数ComplexNode* Clone(ComplexNode* pHead),以复制一个复杂链表。其结点的C++定义如下:
 struct ComplexNode
{
    int m_nValue;
    ComplexNode* m_pNext;
    ComplexNode* m_pSibling;
};

下图是一个含有 5 个结点的该类型复杂链表。图中实线箭头表示 m_pNext 指针,虚线箭头表示 m_pSibling 指针。为简单起见,指向 NULL 的指针没有画出。

方法一:看到这个问题,我的第一反应是分成两步:第一步是复制原始链表上的每个链表,并用m_pNext链接起来;第二步,假设原始链表中的某节点Nm_pSibling指向结点S,由于S的位置在链表上有可能在N的前面也可能在N的后面,所以要定位N的位置需要从原始链表的头结点开始找,假设从原始链表的头结点开始经过s步找到结点S,那么在复制链表上结点Nm_pSiblingS’,离复制链表的头结点的距离也是s,用这种办法我们就能为复制链表上的每个结点设置m_pSibling对含有n个结点的链表,由于定位每个结点的m_pSibling都需要从链表头结点开始经过O(n)步才能找到,因此这种方法的总时间复杂度是O(n2)

方法二换一种思路,在不用辅助空间的情况下实现O(n)的时间效率。第三种方法的第一步仍然是根据原始链表的每个结点N,创建对应的N’。这一次,我们把N’链接在N的后面。实例中的链表经过这一步之后变成了:

 

void CloneNodes(ComplexNode* pHead)
{
	ComplexNode* pNode=pHead;
	while(pNode!=NULL)
	{
		ComplexNode* pCloned=new ComplexNode();
		pCloned->m_nValue=pNode->m_nValue;
		pCloned->m_pNext=pNode->m_pNext;
		pCloned->m_pSibling=NULL;
		pNode->m_pNext=pCloned;
		pNode=pCloned->m_pNext;

	}
}

第二步是设置我们复制出来的链表上的结点的m_pSibling。假设原始链表上的Nm_pSibling指向结点S,那么其对应复制出来的N’N->m_pNext,同样S’也是S->m_pNext。这就是我们在上一步中把每个结点复制出来的结点链接在原始结点后面的原因。有了这样的链接方式,我们就能在O(1)中就能找到每个结点的m_pSibling了。例子中的链表经过这一步,就变成如下结构了:

void ConnectSiblingNodes(ComplexNode* pHead)
{
	ComplexNode* pNode=pHead;
	while(pNode)
	{
		ComplexNode* pCloned=pNode->m_pNext;
		if(pNode->m_pSibling)
			pCloned->m_pSibling=pNode->m_pSibling->m_pNext;
		pNode=pCloned->m_pNext;

	}

}


第三步是把这个长链表拆分成两个:一个原始链表,还有一个就是我们复制的链表了。

   

ComplexNode* ReconnectNodes(ComplexNode* pHead)
{
	ComplexNode* pNode=pHead;
	ComplexNode* pClonedHead=NULL;
	ComplexNode* pClonedNode=NULL;

	if(pNode!=NULL)
	{
		pClonedHead=pClonedNode=pNode->m_pNext;
		pNode->m_pNext=pClonedNode->m_pNext;
		pNode=pNode->m_pNext;
	}

	while(pNode!=NULL)
	{
		pClonedNode->m_pNext=pNode->m_pNext;
		pClonedNode=pClonedNode->m_pNext;

		pNode->m_pNext=pClonedNode->m_pNext;
		pNode=pNode->m_pNext;
	}

	return pClonedHead;
}



把上面三步合起来,就是复制链表的完整过程:

ComplexNode* Clone(ComplexNode* pHead)
{
	CloneNodes(pHead);
	ConnectSiblingNodes(pHead);
	ReconnectNodes(pHead);

}


 感谢:http://www.cnblogs.com/sopc-mc/archive/2011/10/26/2225603.html

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值