复杂链表的复制

复杂链表带有next指针和random随机指针的链表复制:


原链表:1 -> 2 -> 3 -> 4 ,
random指向:
                      1 -> 3
      2 -> 4
      3 -> 2
      4 -> NULL


思路1  暴力做法
1.先把原链表按照next指针复制为新链表,先不管random指针;
2.按顺序找原链表的每个节点的random指针指向的节点,然后遍历新链表找到对应的节点,吧新链表的randon指向调整,
时间复杂度为O(N*N)


思路2  链表拼接法(用红色节点表示新创建的节点)
1.先按顺序创建和原链表
相同的新节点,然后把新节点连接在原节点后面
如下图,红色为新节点。
//原链表1 -> 2 -> 3 -> 4
//新链表1 -> 1 -> 2 -> 2 -> 3 -> 3 -> 4 -> 4


2.按顺序找到原链表的每个节点的random指向,对应的新链表的节点random,指向原节点random的下一个节点
比如:
原链表 1 -> 3
新链表 1 -> 3
新链表的 3 刚好链接在原链表的 3 后面。


3.此时新链表的random指向已经调整好。分离出新链表就可以。

从头节点开始(从0开始),第偶数个节点是原链表,第奇数个节点是新节点(红色节点)



第二种思路的代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <windows.h>
#include <assert.h>
using namespace std;



typedef int DataType;
typedef struct ComplexNode 
{
	DataType _data; // 数据 

	struct ComplexNode* _next; // 指向下一个节点的指针 

	struct ComplexNode* _random; // 指向随机节点(可以是链表中的任意节点 or 空) 

}ComplexNode;


void Display(ComplexNode* list)  //打印链表
{
	assert(list);
	ComplexNode* node = list;
	while (node)
	{
		cout << node->_data << " ";
		node = node->_next;
	}
	cout << endl;
}

ComplexNode* Find(ComplexNode* list, int key)  //查找结点
{
	assert(list);
	ComplexNode* head = list;
	while (head)
	{
		if (head->_data == key)
		{
			return head;
		}
		head = head->_next;
	}
	return NULL;
}

ComplexNode* MakeList(DataType* a, int n)    //构建复杂链表
{
	ComplexNode* head = new ComplexNode;
	head->_data = a[0];
	ComplexNode* list = head;
	for (int i = 1; i < n; i++)
	{
		ComplexNode* node = new ComplexNode;
		node->_data = a[i];
		node->_next = NULL;
		head->_next = node;
		head = head->_next;
		node = node->_next;
	}
	//_random指针指向
	Find(list, 1)->_random = Find(list, 3);  //1 -> 3
	Find(list, 2)->_random = Find(list, 4);  //2 -> 4
	Find(list, 3)->_random = Find(list, 2);	 //3 -> 2	
	Find(list, 4)->_random = NULL;		 //4 -> NULL

	return list;
}



ComplexNode* CopyList(ComplexNode* list)
{
	assert(list);
	ComplexNode* head = list;
	ComplexNode* newhead = new ComplexNode;
	ComplexNode* newlist = newhead;
	ComplexNode* cur = head;

	//1.复制新节点,然后链接在被复制的节点后面
	//原链表1 -> 2 -> 3 -> 4
	//新链表1 -> 1 -> 2 -> 2 -> 3 -> 3 -> 4 -> 4

	while (cur)
	{
		head = cur;
		ComplexNode* newnode = new ComplexNode;
		newnode->_data = head->_data;
		newnode->_next = NULL;
		cur = head->_next;

		newnode->_next = head->_next;
		head->_next = newnode;
	}

	//2.找到原链表的_random指针指向的节点(head),新节点的_random 指向 原_random 节点的下一个节点(head->_next)
	//因为新节和原节点值相同,且新点紧跟在原节点后面

	head = list;
	cur = head;

	ComplexNode* newnode = head->_next;
	while (cur->_next && newnode->_next)
	{
		head = cur;

		head = head->_random;

		if (head != NULL)
		{
			newnode->_random = head->_next;
		}
		else
			newnode->_random = NULL; //如果原链表的_random指向空 则新节点的_random也指向空

		cur = cur->_next->_next;
		newnode = newnode->_next->_next;
	}
	//3.分离出新链表。(偶数节点是原链表,奇数节点是新链表)
	head = list;
	newhead = head->_next;
	newlist = newhead;
	while (head && head->_next)
	{
		head = head->_next->_next;
		newhead->_next = head;
		newhead = newhead->_next;
	}
	return newlist;
}

int main()
{
	int a[] = { 1,2,3,4 };
	ComplexNode* list = MakeList(a, sizeof(a) / sizeof(a[0]));
	
	//Display(list);

	ComplexNode* newlist = CopyList(list);
	Display(newlist);
	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值