复杂链表的复制

  题目:复杂链表的复制。一个链表的每个节点,有一个指向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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值