复制带有随机指针的链表

#include<iostream>
#include<map>

struct ListNode
{
	int value;
	ListNode *next;
	ListNode *random;
	ListNode(int value, ListNode* node, ListNode* random) : value(value), next(node),random(random)
	{
	}
};




void traverseList(ListNode *head)
{
	while (head != NULL)
	{
		std::cout << head->value << "    ";
		head = head->next;
	}
	std::cout << std::endl;
}


ListNode *copyRandomList(ListNode *oldList)
{
	//因为有随机指针的存在,所以无法边遍历原来的链表边进行新链表的拷贝,因为随机指针指向的链表节点可能还没有make
	//所以我们需要先mknode出来原链表的每一个节点,新copy的节点可以直接复制原链表的节点的值,但是指针不能直接copy呀
	//新节点的next和random指针要指向的是新创建的节点的位置
	
	//原始思路:
	//1.我们可以用vector容器存储新创建的这些节点
	//2.遍历原链表,依次看原链表的每个节点的值是多少,next指向的节点的值是谁,random指向的节点的值是多少
	//3.在vecrot中找到与原链表节点的值相同的那个节点,
	//再在vector中找到与原链表的该节点next指向的节点的值对应的节点,
	//更新vecrot中找到与原链表节点的值相同的那个节点的next值
	//同理:再在vector中找到与原链表的该节点random指向的节点的值对应的节点,
	//再在vector中找到与原链表的该节点random指向的节点的值对应的节点,
	//更新vecrot中找到与原链表节点的值相同的那个节点的random值

	//缺点:为了寻找指向关系的节点,多次遍历vecrot,及其没有效率,
	//2.如果存在值相同的节点,那么就需要对vector的每一个新节点元素添加是否已经处理过的标记,即
	//vector的元素是一个结构struct,分别是1.used标记2.makenode的新节点

	//优化:由于慢是慢在了不断地遍历vector查找新节点上,我们完全可以用map容器,去优化这个查找的速度,
	//所以想到了用map,最开始的想法是用map的key存储节点的值,value存储该节点,但是如果链表有重复的元素呢,即有两个节点的vaule是相同的
	//map会发生替换,map存的新节点就会少一个
	//所以我们可以直接就用原链表的节点或者原链表的节点的指针作为这个key值,不但可以比vector更快的找到新节点位置,而且不会导致新节点缺少

	//其实,链表的相互指向的逻辑,天然就带有map的感觉,一一对应的那种逻辑

	std::map<ListNode*, ListNode*> assistMap;

	//第一次循环就是制作辅助map
	ListNode *cur = oldList;
	while (cur != NULL)
	{
		ListNode * nodeTemp = new ListNode(cur->value, nullptr, nullptr);
		assistMap.insert(std::pair<ListNode*, ListNode*>(cur, nodeTemp));
		cur = cur->next;
	}

	//第二次循环,就是给map的vaule部分的新节点,赋值,分别定出他的next和random应该指向的位置
	cur = oldList;
	while (cur != NULL)
	{
		//首先在map中找到与旧链表对应的cur的新节点的位置
		ListNode* curMatch = assistMap[cur];

		//然后在map中找到与旧链表的cur的next指向的节点对应的新节点的位置curnextMatch,让curMatch->next 指向curnextMatch
		ListNode* curnextMatch = assistMap[cur->next];
		curMatch->next = curnextMatch;

		//然后在map中找到与旧链表的cur的random指向的节点对应的新节点的位置currandomMatch,让curMatch->random 指向currandomMatch
		ListNode* currandomMatch = assistMap[cur->random];//map[NULL]的值为NULL
		curMatch->random = currandomMatch;

		cur = cur->next;
	}


	return assistMap[oldList];//返回由value节点组成的链表的表头
}

int main()
{
	
	ListNode * node1 = new ListNode(7, nullptr, nullptr);
	ListNode * node2 = new ListNode(13, nullptr, nullptr);
	ListNode * node3 = new ListNode(11, nullptr, nullptr);
	ListNode * node4 = new ListNode(10, nullptr, nullptr);
	ListNode * node5 = new ListNode(1, nullptr, nullptr);
	node1->next = node2;
	node1->random = node5;
	node2->next = node3;
	node2->random = node1;
	node3->next = node4;
	node3->random = node5;
	node4->next = node5;
	node4->random = node3;

	ListNode *head = node1;
	std::cout << "oldList" << std::endl;
	traverseList(head);


	ListNode *newListHead = copyRandomList(head);

	std::cout << "newList" << std::endl;
	traverseList(newListHead);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值