例题解析



1.拷贝节点插入原节点的后面(核心)
这样做的目的是方便找 random 节点,知道原节点可以找 random,知道上一个 random 可以找下一个 random 。

- struct Node* cur=head;
- while(cur)
- {
- //通过一前一后两个指针来插入节点
- struct Node* next=cur->next;
- struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
- copy->val=cur->val;
- //链接
- cur->next=copy;
- copy->next=next;
- //cur移动
- cur=next;
- }
2.放置每个拷贝节点的 random
我们可以通过原节点的 random 轻松找到拷贝的 random

- cur=head;
- //放置拷贝节点的random
- while(cur)
- {
- //从cur的下一个节点开始遍历
- struct Node* copy=cur->next;
- //如果原节点的random为空,拷贝节点的random也为空
- if(cur->random==NULL)
- {
- copy->random=NULL;
- }
- else
- //否则拷贝节点的random等于原节点的random的拷贝节点
- {
- copy->random=cur->random->next;
- }
- //cur后移动一位
- cur=copy->next;
- }
3.将拷贝节点与原链表解开,尾插到一起,并恢复原链表的链接
- cur=head;
- //创建新链表的头尾节点便于插入
- struct Node* copyhead=NULL,*copytail=NULL;
- while(cur)
- {
- struct Node* copy=cur->next;
- struct Node* next=copy->next;
- //copy节点尾插到新链表
- if(copyhead==NULL)
- {
- copy= copyhead=copytail;
- }
- else
- {
- copytail->next=copy;
- copytail=copytail->next;
- }
- //恢复原节点
- cur->next=next;
-
- cur=next;
- }
完整代码:
- /**
- * Definition for a Node.
- * struct Node {
- * int val;
- * struct Node *next;
- * struct Node *random;
- * };
- */
-
- struct Node* copyRandomList(struct Node* head) {
- //拷贝节点到原节点的后面
- struct Node* cur=head;
- while(cur)
- {
- //通过一前一后两个指针来插入节点
- struct Node* next=cur->next;
- struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
- copy->val=cur->val;
- //链接
- cur->next=copy;
- copy->next=next;
- //cur移动
- cur=next;
- }
- cur=head;
- //放置拷贝节点的random
- while(cur)
- {
- //从cur的下一个节点开始遍历
- struct Node* copy=cur->next;
- //如果原节点的random为空,拷贝节点的random也为空
- if(cur->random==NULL)
- {
- copy->random=NULL;
- }
- else
- //否则拷贝节点的random等于原节点的random的拷贝节点
- {
- copy->random=cur->random->next;
- }
- //cur后移动一位
- cur=copy->next;
- }
- cur=head;
- //创建新链表的头尾节点便于插入
- struct Node* copyhead=NULL,*copytail=NULL;
- while(cur)
- {
- struct Node* copy=cur->next;
- struct Node* next=copy->next;
- //copy节点尾插到新链表
- if(copytail==NULL)
- {
- copyhead=copytail=copy;
- }
- else
- {
- copytail->next=copy;
- copytail=copytail->next;
- }
- //恢复原节点
- cur->next=next;
-
- cur=next;
- }
- return copyhead;
- }
4.顺序表和链表的区别

拓展学习:
