用C++ 实现复杂链表的复制

首先我们先来看一下复杂链表的结构:

这个链表不能直接进行复制,如果我们对其进行直接复制将会发现复制后的链表的random依旧指向之前链表的位置,并没有指向自身的某个节点。因此,我们需要好好分析一下。

方案一:

我们可以一个节点一个节点的进行复制,并将复制后的节点放到原节点的后边。这样就形成了一个这样的链表:

然后我们将复制后的节点指向原节点random指针指向的位置的下一个位置,遍历完整个链表。接下来最重要的是将链表按照奇偶的不同拆分为两个独立的链表便可等到与原链表一样的链表。

方案二:

我们首先让当前位置指向head,然后判断head的random是否为空,如果为空直接复制,若不为空,则需要先记住当前节点,然后向后遍历,引入计数器,遍历一次计数器++;直到找到与random相等的节点,然后将你要复制的链表的当前位置以计数器--,向后遍历,找到之后将记住的当前节点的random指向找到的节点。依次遍历即可。

如果要将random指向自身的某个节点,我们需要记录random与random指向节点

比较方案一与方案二:我们将会发现方案一的空间复杂度小,实现比较简单。方案二的空间复杂度大,代码比较冗余,但容易想到。

下面我们来看一下他们各自的代码:

方案一:

	ComplexList* Listcpy2(ComplexList* cl)
	{
		Node<T>* cur=cl->_head;
		//复制链表
		while(cur)
		{
			Node<T>* tmp=new Node(cur->_data);
			tmp->_next=cur->_next;
			cur->_next=tmp;
			cur=tmp->_next;
		}
		cur=cl->_head;
		//置它的random
		while(cur)
		{
			if(cur->_random!=NULL)
			{
				Node<T>* next=cur->_next;
				next->_random=cur->_random->_next;
				cur=cur->_next->_next;
			}
		}
		cur=cl->_head;
		Node<T>* newhead=NULL;
		Node<T>* newtail=NULL;
		//将奇偶位置的节点拆分成两个链表
		if(cur)//置头结点和尾节点
		{
			newhead=newtail=cur->_next;
			cur->_next=newhead->_next;
			cur=cur->_next;
		}
		while(cur)
		{
			newtail->_next=cur->_next;
			newtail=newtail->_next;
			cur->_next=newtail->_next;
			cur=cur->_next;
		}
		return newhead;

	}

方案二:

	ComplexList& ListCpy(ComplexList& cl)
	{   
		Node<T>* cur=cl._head;
	    Node<T>* cur1=_head;
		while(cur->_next!=NULL)
		{
			cur1->_data=cur->_data;
			cur1->_next=cur->_next;
			if(cur->_random==NULL)
			{
				cur1->_random=NULL;
			}
			else
			{
				Node<T>* cur4=cur;
				int count=1;
				cur4=cur->_next;
				//遍历找出C1当前节点的random指针指向的位置,并用一个计数
				//器记录遍历的次数
				while(cur->_random!=cur4)
				{
					if(cur4->_next==NULL)
					{
						cur4->_next=_head;
						count++;
					}
					else 
					{
						count++;

					}
					cur4=cur4->_next;
				}
				//通过对计数器的--;找到this当前节点random的指针位置,并
				//赋值
				Node<T>* cur2=cur1;
				while(count)
				{
					cur2=cur2->_next;
					if(cur2==NULL)
					{
						cur2=_head;
					}
					count--;
				}
				cur1->_random=cur2;
			}
			//让当前指针指向下一个位置
			cur=cur->_next;
			cur1=cur1->_next;
			//在上面的代码中,我们有可能改掉了C1的最后一个节点的next,让它指向                        //了第一个节点,所以此处将其的next重新置空,否则整个链表将会变成循                        //环链表
			if(cur->_next==_head)
			{
				cur->_next=NULL;
			}
		}
		return *this;
	}

最后博主再来讲一个函数,是将链表节点的random指针指向位置的函数,也就是设置random的函数

void SetRandom(ComplexList& cl,int n=-1,int count=0)//这里的参数n的表示相对头节点有几个位//置的节点,也就是我们要设置的节点。count表示相对设置的节点的位置即相对位置的节点向后指向//count次,找到random的位置。
	{
		Node<T>* cur1=_head;
		if(n==-1||count==0)
		{
			return;
		}
		while(n--)
		{
			cur1=cur1->_next;
		}
		Node<T>* cur2=cur1;
		while(count--)
		{
			if(cur2->_next==NULL)
			{
				cur2=_head;
			}
			else
			{
				cur2=cur2->_next;
			}
		}
		cur1->_random=cur2;
	}
时间: 2024-11-01 01:34:48

用C++ 实现复杂链表的复制的相关文章

浅谈复杂链表的复制

链表是一种很常见的数据结构,单链表.双向链表.循环链表和复杂链表都是其衍生物.复杂链表之所以命名为复杂链表,也正是由于其结构的复杂.它比其他其他种类的链表多了一个指针域,这个指针域可以指向链表中的任一结点,也可以为空. 其结构定义如下: struct ComplexNode { DataType _data; struct ComplexNode * _next; struct ComplexNode * _random;//随机域 }; 结构示例: ps:蓝色指针为next域,红色为rando

【剑指offer】复杂链表的复制

转载请注明出处:http://blog.csdn.net/ns_code/article/details/26154691 题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n (1<=n<=1000):n代表将要输入的链表元素的个数.(节点编号从1开始).接下来有n个数,表示链表节点中的值.接下来有n个数Ti,Ti表示第i个节点的另

剑指offer之【复杂链表的复制】

题目: 复杂链表的复制 链接: https://www.nowcoder.com/practice/f836b2c43afc4b35ad6adc41ec941dba?tpId=13&tqId=11178&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为

19--复杂链表的复制。

/* 题目: 复杂链表的复制. struct ComplexListNode { int m_vlaue; ComplexListNode *m_next; ComplexListNode *m_pSibling; }: m_next,连接下一个结点,m_pSibling随便链接结点其他节点. 这样复制结点就有难度,一次遍历明显不可能全部解决. 策略: 第一种方法: 先复制一遍链表,让m_pnext把结点连接起来.第二轮在复制另一个指针,复杂度为O(n*n); 第二种方法: 先复制一遍链表,然后

算法题:复制复杂链表之复制连接法

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 上篇文章算法题:复制复杂链表之空间换时间法我们给出了用映射的方法来为新复制的链表中的每个结点设置any指针,本文给出的是<剑指offer>上给出的算法与代码,<剑指offer>上提到该算法的实现三个步骤:        第一步:复制原始链表的任意结点N并创建新结点N',在把N'连接到N的后面:        第二步:设置每个结点的any指针:        第三步:将长链表分成两个链表,一个是原始链表,另外一个就是我们所要求的复制

C语言之复杂链表的复制(图示详解)

什么是复杂链表? 复杂链表指的是一个链表有若干个结点,每个结点有一个数据域用于存放数据,还有两个指针域,其中一个指向下一个节点,还有一个随机指向当前复杂链表中的任意一个节点或者是一个空结点.今天我们要实现的就是对这样一个复杂链表复制产生一个新的复杂链表. 复杂链表的数据结构如下: 1 typedef int DataType; //数据域的类型 2 3 //复杂链表的数据结构 4 5 typedef struct ComplexNode 6 7 { 8 9 DataType _data ; //

复杂链表的复制-剑指Offer

复杂链表的复制 题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 思路 分三步(分而治之) 将链表复制下来追加到每个元素的后面,例如A->A'->B->B'->C->C'... 复制每个元素的random指针 从整体的链表中间隔的取出复制出来的链表 代码 /* public class RandomListNode { int label; RandomListNode next = null; Random

剑指Offer--026-复杂链表的复制

链接 牛客OJ:复杂链表的复制 九度OJ:http://ac.jobdu.com/problem.php?pid=1524 GitHub代码: 026-复杂链表的复制 CSDN题解:剑指Offer–026-复杂链表的复制 牛客OJ 九度OJ CSDN题解 GitHub代码 复杂链表的复制 1524-复杂链表的复制 剑指Offer–026-复杂链表的复制 026-复杂链表的复制 题意 题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点)

【编程题目】复杂链表的复制☆

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

剑指offer (27) 复杂链表的复制

题目:请实现一个函数,复制一个复杂链表,在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点,还有一个m_pSibling指向链表中的任意节点或者NULL struct ComplexListNode { int m_nValue; ComplexListNode* m_pNext; ComplexListNode* m_pSibling; }; 方法一: step1. 复制原始链表的每一个节点,并用m_pNext链接起来 step2. 设置每个结点的m_pSibling指针 由于m