题目:复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的 一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
解题思路:
题目中不仅仅要复制指向next指针的节点,还要复制random指针指向这个链表的随机节点或NULL,所以我们要考虑很多的情况,并且还要将一个指针所有的指向都复制下来,如下图给的一个指针:
所以在这个题中分为三步:
(1)先把链表复制一遍,不用管Random指向的随机节点,就变成下图:
将新节点都插入到原来的节点后面:
代码如下:
ComplexNode *pNode = pFirst;
ComplexNode *pNewNode = NULL;
for (pNode = pFirst; pNode; pNode = pNode->pNext->pNext)
{
pNewNode = (ComplexNode *)malloc(sizeof(ComplexNode)); //开辟空间,存放新节点
assert(pNewNode);
pNewNode->data = pNode->data; //将原来节点的值赋给新节点
pNewNode->pNext = pNode->pNext; //插入到原来节点后面
pNewNode->pRandom = NULL;
pNode->pNext = pNewNode;
}
(2)第二步赋值Random指向的随机节点:
从链表头通过原来的节点找节点对应的Random,然后通过原来节点的Random来找到新节点的Random,将新节点指向新节点的Random。如下图:
代码如下:
ComplexNode *pNode = pFirst;
ComplexNode *pNewNode = NULL;
ComplexNode *oldRandom=NULL;
ComplexNode *NewRandom=NULL;
for (pNode = pFirst; pNode; pNode = pNode->pNext->pNext)
{
pNewNode = pNode->pNext; //原来链表的指针域存的是新链表的地址
oldRandom = pNode->pRandom; //找到原来链表的Random
if (oldRandom!=NULL){
NewRandom = oldRandom->pNext; //通过原来链表的Random来找新链表的Random
pNewNode->pRandom = NewRandom;
}
else
{
pNewNode->pRandom = NULL;
}
}
(3)将新链表和原来的链表拆开
将原来的链表链接起来,将新链表链接起来,如下图:
先定义一个指针指向新链表头,然后返回这个指针
代码实现:
ComplexNode *pNode = pFirst;
ComplexNode *pNewNode = NULL;
ComplexNode *pNewFirst=pFirst->pNext ; //定义一个指针指向新链表头
for (pNode = pFirst; pNode; pNode = pNode->pNext)
{
pNewNode = pNode->pNext;
pNode->pNext = pNewNode->pNext;
if (pNode->pNext)
{
pNewNode->pNext = pNode->pNext->pNext;
}
else
{
pNewNode->pNext = NULL;
}
}
完整代码实现:
#pragma once
#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include<assert.h>
//定义结构体
typedef struct ComplexNode
{
int data;
struct ComplexNode *pNext;
struct ComplexNode *pRandom;
}ComplexNode;
ComplexNode *CopyNode(ComplexNode * pFirst)
{
ComplexNode *pNode = pFirst;
ComplexNode *pNewNode = NULL;
ComplexNode *oldRandom=NULL;
ComplexNode *NewRandom=NULL;
//复制链表
for (pNode = pFirst; pNode; pNode = pNode->pNext->pNext)
{
pNewNode = (ComplexNode *)malloc(sizeof(ComplexNode));
assert(pNewNode);
pNewNode->data = pNode->data;
pNewNode->pNext = pNode->pNext;
pNewNode->pRandom = NULL;
pNode->pNext = pNewNode;
}
//复制pRandom
for (pNode = pFirst; pNode; pNode = pNode->pNext->pNext)
{
pNewNode = pNode->pNext;
oldRandom = pNode->pRandom;
if (oldRandom!=NULL){
NewRandom = oldRandom->pNext;
pNewNode->pRandom = NewRandom;
}
else{
pNewNode->pRandom = NULL;
}
}
//拆链表
ComplexNode *pNewFirst=pFirst->pNext ;
for (pNode = pFirst; pNode; pNode = pNode->pNext)
{
pNewNode = pNode->pNext;
pNode->pNext = pNewNode->pNext;
if (pNode->pNext)
{
pNewNode->pNext = pNode->pNext->pNext;
}
else
{
pNewNode->pNext = NULL;
}
}
return pNewFirst;
}
//测试部分
ComplexNode * Buy(int data)
{
ComplexNode *pNode = (ComplexNode *)malloc(sizeof(ComplexNode));
assert(pNode);
pNode->data = data;
pNode->pRandom = NULL;
pNode->pNext = NULL;
return pNode;
}
void Print(ComplexNode *pFirst)
{
ComplexNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext) {
printf("[%d, (%p, %d)] ",
pNode->data,
pNode->pRandom,
pNode->pRandom ? pNode->pRandom->data : 0);
}
printf("\n");
}
void TestComplexNode()
{
ComplexNode *p1 = Buy(1);
ComplexNode *p2 = Buy(2);
ComplexNode *p3 = Buy(3);
ComplexNode *p4 = Buy(4);
p1->pNext = p2;
p2->pNext = p3;
p3->pNext = p4;
p1->pRandom = p4;
p4->pRandom = p1;
p2->pRandom = p2;
Print(p1);
ComplexNode *pNew = CopyNode(p1);
Print(pNew);
}