一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
对于这个题,基本会有三个思路:
1.这里链表的复制和单链表最大的不同,就是多了一个自由指针(psub),那么最简单的想法就是,遍历单链表,找到psub指向的节点,然后复制,这样做最简单,事件复杂度为O(n的平方);
2. 基于第一种方法的优化,第一种方法把事件浪费在了查找节点上,那么我们可以建立一个哈希函数,对节点建立唯一的键值对(k,v), 在复制时,利用哈希函数,时间为O(n);
3.当然哈希函数虽好,但是明显是以空间来换时间,那么有没有其他方法呢?能不能不开辟辅助空间呢?
(1)
(2)将新节点的psub连接起来。
1.设置两个指针,一前一后分别指向新旧节点;
2.新节点的psub = 老节点的psub->next;
(3)
思路为:
1.设置三个指针
2.一个作为新链表的头结点;
3.剩余两个交替指向新旧节点,具体如图
#pragma once
#include
#include
typedef struct ListNode{
int value;
ListNode* next;
ListNode* psub;
}Node, *pNode;
pNode createNode(int data)
{
pNode temp = (pNode)malloc(sizeof(Node));
temp->next = NULL;
temp->psub = NULL;
temp->value = data;
return temp;
}
void InitList(pNode* pHead)
{
*pHead = NULL;
}
void Print(pNode pHead)
{
pNode t = pHead;
while (t)
{
printf("%d->", t->value);
t = t->next;
}
printf("NULL");
}
void push_back(pNode* pHead, int data)
{
if (NULL == *pHead)
{
*pHead = createNode(data);
}
else
{
pNode tm = *pHead;
while (tm->next)
{
tm = tm->next;
}
tm->next = createNode(data);
}
}
pNode FindNode(pNode pHead, int data)
{
pNode lt = pHead;
while (NULL != lt)
{
if (lt->value == data)
{
return lt;
}
lt = lt->next;
}
return lt;
}
void pSub(pNode* pHead, int data1, int data2)
{
if (data2 == 0 || data1 == 0)
{
return;
}
pNode tem = *pHead;
while (NULL != tem)
{
if (tem->value == data1)
{
break;
}
tem = tem->next;
}
tem->psub = FindNode(*pHead, data2);
}
/*
* 第一步:将每一个节点创建出来,并插在对应节点的后面
* 第二步:将每个新建的节点的pSub连接好
* 第三步:将两个链表分开
*/
void copyNewNode(pNode pHead)
{
if (NULL == pHead)
{
return;
}
pNode temp = pHead;
while ( NULL != temp)
{
pNode newNode = createNode(temp->value);
newNode->next = temp->next;
temp->next = newNode;
temp = temp->next->next;
}
}
void ConnectPsub(pNode pHead)
{
if (NULL == pHead)
{
return;
}
pNode pn1 = pHead;
pNode pn2 = pHead->next;
while (NULL != pn2->next && NULL != pn2->next->next)
{
if (NULL != pn1->psub)
{
pn2->psub = pn1->psub->next;
}
pn1 = pn1->next->next;
pn2 = pn2->next->next;
}
if (NULL != pn2->next)
{
pn2 = pn2->next;
pn1 = pn1->next;
if (pn2->psub != NULL)
{
pn2->psub = pn1->psub->next;
}
else
{
return;
}
}
}
pNode SeparateList(pNode pHead)
{
if (NULL == pHead)
{
return pHead;
}
pNode pold = pHead;
pNode ppHead = NULL;
pNode ppNode = NULL;
ppHead = ppNode = pHead->next;
while (NULL != ppNode->next)
{
pold->next = ppNode->next;
pold = pold->next;
ppNode->next = pold->next;
ppNode = ppNode->next;
}
return ppHead;
}
#include "1.hpp"
int main()
{
pNode p;
InitList(&p);
push_back(&p, 1);
push_back(&p, 2);
push_back(&p, 3);
push_back(&p, 4);
push_back(&p, 5);
push_back(&p, 6);
Print(p);
pSub(&p, 1, 4);
pSub(&p, 2, 5);
pSub(&p, 3, 6);
pSub(&p, 4, 0);
pSub(&p, 5, 0);
pSub(&p, 6, 2);
printf("\n");
copyNewNode(p);
Print(p);
printf("\n");
ConnectPsub(p);
Print(SeparateList(p));
printf("\n");
return 0;
}