剑指offer:复杂链表的复制

所谓复杂链表,指的是:

每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点(可以指向自己,可以为空)。

结构如下:

struct RandomListNode
{
	RandomListNode(int x)
		:label(x)
		, next(NULL)
		, random(NULL)
	{}

	int label;//节点的值
	struct RandomListNode *next;//指向下一个节点
	struct RandomListNode *random;//指向任意节点(可以指向自己,可以为空)
};

现在有一个复杂链表:


这个链表:

节点1的random指节点2;

节点2的random指向节点4;

节点3的random指向节点2;

节点4的random指向自己;

节点5的random为空。

如何复制复杂链表?分三步:

一:把要拷贝的节点插入这个链表


如图所示,被红色圈住的节点表示要新拷贝的节点,它们的random默认为空。

二:可以发现,每一个要新拷贝的节点,它的random等于所对应旧节点random的下一个,所以可以赋值。


三:把新旧节点分开,就可实现复杂链表的复制:

具体方法有很多,我介绍一种:

	cur = pHead;
	Node* newhead = NULL;//新链表的头
	Node* newtail = NULL;//新链表的尾
	while (cur)
	{
		Node* copy = cur->next;//新节点
		Node* next = copy->next;//记录cur的下一个节点
		cur->next = next;//跳过copy

		if (newhead == NULL)
		{
			newhead = copy;
			newtail = copy;
		}
		else
		{
			newtail->next = copy;
			newtail = copy;
		}

		cur = next;
	}

完整代码:

/复杂链表的复制
RandomListNode* Clone(RandomListNode* pHead)
{
	typedef RandomListNode Node;
	//1.把1 2 3 4 5变为1 1 2 2 3 3 4 4 5 5
	Node* cur = pHead;
	while (cur)
	{
		Node* next = cur->next;
		Node* copy = new Node(cur->label);
		cur->next = copy;
		copy->next = next;
		cur = next;
	}
	//2.此时,新节点的radom就是旧节点radom的下一个,然后置新节点的radom
	cur = pHead;
	while (cur)
	{
		Node* copy = cur->next;
		if (cur->random != NULL)
		{
			copy->random = cur->random->next;
		}
		cur = copy->next;
	}
	//3.分开
	cur = pHead;
	Node* newhead = NULL;//新链表的头
	Node* newtail = NULL;//新链表的尾
	while (cur)
	{
		Node* copy = cur->next;
		Node* next = copy->next;
		cur->next = next;

		if (newhead == NULL)
		{
			newhead = copy;
			newtail = copy;
		}
		else
		{
			newtail->next = copy;
			newtail = copy;
		}

		cur = next;
	}
	return newhead;
}

猜你喜欢

转载自blog.csdn.net/han8040laixin/article/details/80577246