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

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

wKiom1cUoRTwfKgIAABTq3oZVUw569.jpg

    这个链表不能直接进行复制,若是咱们对其进行直接复制将会发现复制后的链表的random依旧指向以前链表的位置,并无指向自身的某个节点。所以,咱们须要好好分析一下。tcp

方案一:ide

    咱们能够一个节点一个节点的进行复制,并将复制后的节点放到原节点的后边。这样就造成了一个这样的链表:wKiom1cUocHAQFu5AABCJTi2Wzw807.jpg函数

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

方案二:spa

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

    若是要将random指向自身的某个节点,咱们须要记录randomrandom指向节点指针

wKioL1cUpbHAEJLFAABaqL6hv3w299.png


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

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

方案一:

	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;
	}
相关文章
相关标签/搜索