复制复杂链表

什么是复杂链表???

     如图,这是一个复杂链表,每个结点包含两个指针域,其中next指针域相互连接构成一个单链表,而另一个指针域Sibling则随意指向链表中的任意位置,或者指向NULL。

复制复杂链表!!!
实现这个问题的方法比较多,下面来介绍三种方法。。


方法一:
    新建一个头结点,先不考虑Sibling,将整个单链表复制一份。然后寻找每个结点的Sibling所指向的位置。以寻找2这个结点的Sibling为例:设置一个计步器count,然后以游标指针cur遍历整个链表,如果cur的地址等于2这个结点的Sibling,则寻找成功,这时在新链表中走上count步所找到的结点就是我们要找的结点。这个方法效率最低。

代码如下:
pLinkNode CloneComplexLinklist(pLinkNode head)
{
	pLinkNode cur = head->next;
	if (NULL == head->next)         //判断是不是空链表
	{
		return NULL;
	}
	pLinkNode newNode= NULL;
	pLinkNode newhead = NULL;
	CreateNode(&newhead, cur->data);
	pLinkNode last= newhead;          //新建一个头结点
	cur = cur->next;
	while (NULL != cur)                //复制整个链表
	{
		CreateNode(&newNode, cur->data);
		last->next = newNode;
		cur = cur->next;
		last = last->next;
	}
	cur = head->next;
	pLinkNode p = newhead;
	int s = 0;                           //计步器
	//链接Sibling
	while (NULL != cur) 
	{
		last = head->next;
		while (cur->Sibling&&cur->Sibling != last)  //找到当前结点cur的Sibling在旧链表中的位置
		{
			s++;
			last = last->next;
		}
		//如果这个位置不为空
		if (NULL != cur->Sibling)
		{
			last=newhead;
			while (s>0)                //寻找cur所对应结点p的Sibling在新链表中的位置
			{
				s--;
				last=last->next;
			}
			p->Sibling = last;            //链接p的Sibling
		}
		cur = cur->next;
		p = p->next;
	}
	return newhead;                    //返回头结点
}







方法二:
    利用哈希表,在复制新链表的同时我们将新旧结点<N,N'>的关系保存下来,这时我们就能在O(1)的时间内通过N的Sibling找到N'的Sibling。这个方法已经很高了,但是却有O(n)的空间耗费。



方法三:
    同方法一一样先复制一个单链表,不同的是这次每复制一个结点都将它链接到原结点后面,如图:


//复制新的结点链接在原来结点后面
void CopyLinkNode(pLinkNode head)
{
	pLinkNode cur = head->next;
	pLinkNode newNode = NULL;
	while (NULL != cur)
	{
		CreateNode(&newNode,cur->data);     //新建结点newNode
		newNode->next = cur->next;          //将这个结点链接到当前结点的后面
		cur->next = newNode;
		cur = newNode->next;
	}
}




    接下来设置新节点的Sibling。例如要设置1’的Sibling,只需让1’的Sibling指向1的Sibling的next就可以了,还要注意1的Sibling要不为NULL才行。
//链接新建结点的Sibling指针
void ConnectSiblingNode(pLinkNode head)
{
	pLinkNode cur = head->next;
	pLinkNode tail = NULL;
	while (NULL!=cur)
	{
		tail = cur->next;
		tail->Sibling = cur->Sibling;       //tail指针的Sibling指cur的Sibling的位置
		if (NULL != tail->Sibling)          //如果tail的Sibling指针不空,值链接新节点的Sibling
		{
			tail->Sibling = tail->Sibling->next;
		}
		cur = tail->next;
	}
}




最后一步将两个链表拆分开就可以了。
//拆分两个链表
pLinkNode SeparateLinkList(pLinkNode head)
{
	if (NULL == head->next)
	{
		return NULL;
	}
	pLinkNode newhead =head->next->next;    //指向新链表的的指针
	pLinkNode last =newhead;
	pLinkNode cur = newhead->next;
	head->next->next = cur;
	while (NULL!=cur)         //拆分这个链表
	{
		last->next = cur->next;
		last = last->next;
		cur->next =last->next;
		cur = cur->next;
	}
	return newhead;                           //返回新链表的地址
}





将上面三个函数封装成一个函数
//复制复杂链表
pLinkNode CloneComplexLinklist(pLinkNode head)
{
	pLinkNode newlist = NULL;
	CopyLinkNode(head);        //复制新的结点链接在原来结点后面
	ConnectSiblingNode(head);    //链接新建结点的Sibling指针
	newlist=SeparateLinkList(head);  //拆分链表
	return newlist;
}
奋斗

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值