复杂链表带有next指针和random随机指针的链表复制:
原链表:1 -> 2 -> 3 -> 4 ,
random指向:
1 -> 3
2 -> 4
3 -> 2
4 -> NULL
思路1 暴力做法
1.先把原链表按照next指针复制为新链表,先不管random指针;
2.按顺序找原链表的每个节点的random指针指向的节点,然后遍历新链表找到对应的节点,吧新链表的randon指向调整,
时间复杂度为O(N*N)
思路2 链表拼接法(用红色节点表示新创建的节点)
1.先按顺序创建和原链表 相同的新节点,然后把新节点连接在原节点后面
如下图,红色为新节点。
//原链表1 -> 2 -> 3 -> 4
//新链表1 -> 1 -> 2 -> 2 -> 3 -> 3 -> 4 -> 4
2.按顺序找到原链表的每个节点的random指向,对应的新链表的节点random,指向原节点random的下一个节点
比如:
原链表 1 -> 3
新链表 1 -> 3
新链表的 3 刚好链接在原链表的 3 后面。
3.此时新链表的random指向已经调整好。分离出新链表就可以。
原链表:1 -> 2 -> 3 -> 4 ,
random指向:
1 -> 3
2 -> 4
3 -> 2
4 -> NULL
思路1 暴力做法
1.先把原链表按照next指针复制为新链表,先不管random指针;
2.按顺序找原链表的每个节点的random指针指向的节点,然后遍历新链表找到对应的节点,吧新链表的randon指向调整,
时间复杂度为O(N*N)
思路2 链表拼接法(用红色节点表示新创建的节点)
1.先按顺序创建和原链表 相同的新节点,然后把新节点连接在原节点后面
如下图,红色为新节点。
//原链表1 -> 2 -> 3 -> 4
//新链表1 -> 1 -> 2 -> 2 -> 3 -> 3 -> 4 -> 4
2.按顺序找到原链表的每个节点的random指向,对应的新链表的节点random,指向原节点random的下一个节点
比如:
原链表 1 -> 3
新链表 1 -> 3
新链表的 3 刚好链接在原链表的 3 后面。
3.此时新链表的random指向已经调整好。分离出新链表就可以。
从头节点开始(从0开始),第偶数个节点是原链表,第奇数个节点是新节点(红色节点)
第二种思路的代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <windows.h>
#include <assert.h>
using namespace std;
typedef int DataType;
typedef struct ComplexNode
{
DataType _data; // 数据
struct ComplexNode* _next; // 指向下一个节点的指针
struct ComplexNode* _random; // 指向随机节点(可以是链表中的任意节点 or 空)
}ComplexNode;
void Display(ComplexNode* list) //打印链表
{
assert(list);
ComplexNode* node = list;
while (node)
{
cout << node->_data << " ";
node = node->_next;
}
cout << endl;
}
ComplexNode* Find(ComplexNode* list, int key) //查找结点
{
assert(list);
ComplexNode* head = list;
while (head)
{
if (head->_data == key)
{
return head;
}
head = head->_next;
}
return NULL;
}
ComplexNode* MakeList(DataType* a, int n) //构建复杂链表
{
ComplexNode* head = new ComplexNode;
head->_data = a[0];
ComplexNode* list = head;
for (int i = 1; i < n; i++)
{
ComplexNode* node = new ComplexNode;
node->_data = a[i];
node->_next = NULL;
head->_next = node;
head = head->_next;
node = node->_next;
}
//_random指针指向
Find(list, 1)->_random = Find(list, 3); //1 -> 3
Find(list, 2)->_random = Find(list, 4); //2 -> 4
Find(list, 3)->_random = Find(list, 2); //3 -> 2
Find(list, 4)->_random = NULL; //4 -> NULL
return list;
}
ComplexNode* CopyList(ComplexNode* list)
{
assert(list);
ComplexNode* head = list;
ComplexNode* newhead = new ComplexNode;
ComplexNode* newlist = newhead;
ComplexNode* cur = head;
//1.复制新节点,然后链接在被复制的节点后面
//原链表1 -> 2 -> 3 -> 4
//新链表1 -> 1 -> 2 -> 2 -> 3 -> 3 -> 4 -> 4
while (cur)
{
head = cur;
ComplexNode* newnode = new ComplexNode;
newnode->_data = head->_data;
newnode->_next = NULL;
cur = head->_next;
newnode->_next = head->_next;
head->_next = newnode;
}
//2.找到原链表的_random指针指向的节点(head),新节点的_random 指向 原_random 节点的下一个节点(head->_next)
//因为新节和原节点值相同,且新点紧跟在原节点后面
head = list;
cur = head;
ComplexNode* newnode = head->_next;
while (cur->_next && newnode->_next)
{
head = cur;
head = head->_random;
if (head != NULL)
{
newnode->_random = head->_next;
}
else
newnode->_random = NULL; //如果原链表的_random指向空 则新节点的_random也指向空
cur = cur->_next->_next;
newnode = newnode->_next->_next;
}
//3.分离出新链表。(偶数节点是原链表,奇数节点是新链表)
head = list;
newhead = head->_next;
newlist = newhead;
while (head && head->_next)
{
head = head->_next->_next;
newhead->_next = head;
newhead = newhead->_next;
}
return newlist;
}
int main()
{
int a[] = { 1,2,3,4 };
ComplexNode* list = MakeList(a, sizeof(a) / sizeof(a[0]));
//Display(list);
ComplexNode* newlist = CopyList(list);
Display(newlist);
system("pause");
return 0;
}