一、题目链接:. - 力扣(LeetCode)

二、思路:

1、对原链表遍历,我们在每个结点后面申请一个与之一模一的结点,将其插入到每原来的两个结点之间。(如上图)
2、遍历原链表,进行对随机指针指向的复制
3、最后把那些复制申请的结点剪切下来,形成与原链表相同的链表。
三、代码解释
1.结构体的成员:
struct Node {
int val;
struct Node *next;
struct Node *random;
};
2.申请结点的函数
struct Node*Buynode(int val)
{
struct Node*newnode=(struct Node*)malloc(sizeof(struct Node));
if(newnode==NULL)
{
perror("malloc fail");
return NULL;
}
newnode->val=val;
newnode->next=NULL;
newnode->random=NULL;
return newnode;
}
参数val为每个结点中的数值。申请新的结点的数值是与原来的相同。
将新结点的数值赋值为val,next 和 random 指针先置为NULL
3.随机链表复制函数
struct Node*Buynode(int val)
{
struct Node*newnode=(struct Node*)malloc(sizeof(struct Node));
if(newnode==NULL)
{
perror("malloc fail");
return NULL;
}
newnode->val=val;
newnode->next=NULL;
newnode->random=NULL;
return newnode;
}
struct Node* copyRandomList(struct Node* head) {
struct Node*cur1=head;
//1.从原链表头部遍历,将每个新的结点插入到中间
while(cur1)
{
struct Node*newnode=Buynode(cur1->val);
newnode->next=cur1->next;
cur1->next=newnode;
cur1=newnode->next;
}
//2.重新遍历,确定好随机指针
cur1=head;
while(cur1)
{
if(cur1->random!=NULL)//如果原结点的random指针不是NULL
cur1->next->random=cur1->random->next;//所以,新申请的结点random指针要指向原链表的random指针所指向的结点的下一个结点,也就是那个结点的复制结点
cur1=cur1->next->next;
}
cur1=head;
struct Node*nhead=Buynode(-1),*ncur;//创建哨兵位
ncur=nhead;
while(cur1)//尾插每一个新申请的结点,从而组成一个新的链表
{
ncur->next=cur1->next;
ncur=cur1->next;
cur1=cur1->next->next;
}
return nhead->next;//返回哨兵位的下一个结点作为开头
}
如果原结点的random指针不是NULL,所以,新申请的结点random指针要指向原链表的random指针所指向的结点的下一个结点,也就是那个结点的复制结点,这样就与原链表保持一致,而且新链表中的结点与原链表的结点没有指向关系。