复杂链表
一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL
复制这个复杂链表
解题方法:
1.将复制的链表夹在原链表中间。
//设置一个指针指向表头方便后面使用
Node* tmp = head;
//将节点复制并将新节点放在旧节点的后面
while(tmp != NULL){
//创建一个新节点
Node* node = new Node(tmp->val);
//新节点指向原链表的下一个,随机指向先初始化为空
node->next = tmp->next;
node->random = NULL;
tmp->next = node;
//将老节点偏移到下一个老节点,因为中间多了一个新节点//所以直接偏移到新节点的下一个才是原链表老节点的下一个
tmp = node->next;//当节点为最后一个时,新节点的下一个就是NULL退出循环
}
2.将复杂指针的指向也拷贝。
//将标记指针置回头节点
tmp = head;
//将原链表的随机指针也复制给新链表,此时两个链表还是纠缠在一起并且一个老一个新
//这样新节点的随机指针就指向老节点的随机指针的下一个
while(tmp != NULL){
//创造一个指针指向新节点
Node* node = tmp->next;
if(tmp->random == NULL){
//如果老节点的随机指针为空,新节点的随机指针也为空
node->random = NULL;
}else{
//否则新节点的随机指针就指向老节点的随机指针的下一个
node->random = tmp->random->next;
}
//将老节点偏移到下一个老节点,因为中间多了一个新节点//所以直接偏移到新节点的下一个才是原链表老节点的下一个
tmp = node->next;
}
3.断开纠缠的两个链表就得到了新的链表。
//将标记指针置回头节点
tmp = head;
//因为马上要将纠缠在一起的链表拆开,所以拆开前得到一下新链表的头用作处理完后的返回值
Node* newHead = head->next;
//将纠缠在一起的链表拆开为两个链表
while(tmp != NULL){
//创造一个指针指向新节点
Node* node = tmp->next;
//老节点的指向变为新节点的指向(因为新节点夹在两个老节点中间,这一步就把它绕过去了)
tmp->next = node->next;
//将老节点偏移到下一个老节点
tmp = tmp->next;
if(tmp!=NULL){
//如果老节点不是空,就将新节点指向老节点的下一个(也就是下一个新节点)
node->next = tmp->next;
}else{
//否则就给新节点的下一个赋空
//此时已经分离完毕,老节点目前为空,下一次会触发退出循环
node->next = NULL;
}
}
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
//复制复杂链表
Node* copyRandomList(Node* head) {
//如果传的空链表就返回传过来的链表
if(head == NULL) return head;
//设置一个指针指向表头方便后面使用
Node* tmp = head;
//将节点复制并将新节点放在旧节点的后面
while(tmp != NULL){
//创建一个新节点
Node* node = new Node(tmp->val);
//新节点指向原链表的下一个,随机指向先初始化为空
node->next = tmp->next;
node->random = NULL;
//将老节点的下一个指向新节点
tmp->next = node;
//将老节点偏移到下一个老节点,因为中间多了一个新节点所以直接偏移到新节点的下一个才是原链表老节点的下一个
tmp = node->next;//当节点为最后一个时,新节点的下一个就是NULL退出循环
}
//将标记指针置回头节点
tmp = head;
//将原链表的随机指针也复制给新链表,此时两个链表还是纠缠在一起并且一个老一个新
//这样新节点的随机指针就指向老节点的随机指针的下一个
while(tmp != NULL){
//创造一个指针指向新节点
Node* node = tmp->next;
if(tmp->random == NULL){
//如果老节点的随机指针为空,新节点的随机指针也为空
node->random = NULL;
}else{
//否则新节点的随机指针就指向老节点的随机指针的下一个
node->random = tmp->random->next;
}
//将老节点偏移到下一个老节点,因为中间多了一个新节点所以直接偏移到新节点的下一个才是原链表老节点的下一个
tmp = node->next;
}
//将标记指针置回头节点
tmp = head;
//因为马上要将纠缠在一起的链表拆开,所以拆开前得到一下新链表的头用作处理完后的返回值
Node* newHead = head->next;
//将纠缠在一起的链表拆开为两个链表
while(tmp != NULL){
//创造一个指针指向新节点
Node* node = tmp->next;
//老节点的指向变为新节点的指向(因为新节点夹在两个老节点中间,这一步就把它绕过去了)
tmp->next = node->next;
//将老节点偏移到下一个老节点
tmp = tmp->next;
if(tmp!=NULL){
//如果老节点不是空,就将新节点指向老节点的下一个(也就是下一个新节点)
node->next = tmp->next;
}else{
//否则就给新节点的下一个赋空
//此时已经分离完毕,老节点目前为空,下一次会触发退出循环
node->next = NULL;
}
}
return newHead;
}
};