十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
首先我们先来看一下复杂链表的结构:
目前创新互联建站已为成百上千家的企业提供了网站建设、域名、网络空间、网站托管、服务器托管、企业网站设计、青山网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
这个链表不能直接进行复制,如果我们对其进行直接复制将会发现复制后的链表的random依旧指向之前链表的位置,并没有指向自身的某个节点。因此,我们需要好好分析一下。
方案一:
我们可以一个节点一个节点的进行复制,并将复制后的节点放到原节点的后边。这样就形成了一个这样的链表:
然后我们将复制后的节点指向原节点random指针指向的位置的下一个位置,遍历完整个链表。接下来最重要的是将链表按照奇偶的不同拆分为两个独立的链表便可等到与原链表一样的链表。
方案二:
我们首先让当前位置指向head,然后判断head的random是否为空,如果为空直接复制,若不为空,则需要先记住当前节点,然后向后遍历,引入计数器,遍历一次计数器++;直到找到与random相等的节点,然后将你要复制的链表的当前位置以计数器--,向后遍历,找到之后将记住的当前节点的random指向找到的节点。依次遍历即可。
如果要将random指向自身的某个节点,我们需要记录random与random指向节点
比较方案一与方案二:我们将会发现方案一的空间复杂度小,实现比较简单。方案二的空间复杂度大,代码比较冗余,但容易想到。
下面我们来看一下他们各自的代码:
方案一:
ComplexList* Listcpy2(ComplexList* cl) { Node* cur=cl->_head; //复制链表 while(cur) { Node * 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 * next=cur->_next; next->_random=cur->_random->_next; cur=cur->_next->_next; } } cur=cl->_head; Node * newhead=NULL; Node * 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* cur=cl._head; Node * cur1=_head; while(cur->_next!=NULL) { cur1->_data=cur->_data; cur1->_next=cur->_next; if(cur->_random==NULL) { cur1->_random=NULL; } else { Node * 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 * 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* cur1=_head; if(n==-1||count==0) { return; } while(n--) { cur1=cur1->_next; } Node * cur2=cur1; while(count--) { if(cur2->_next==NULL) { cur2=_head; } else { cur2=cur2->_next; } } cur1->_random=cur2; }