复制含有随机指针节点的链表
【题目】
一种特殊的链表节点类描述如下:
public class Node {
public int value;
public Node next;
public Node rand;
public Node(int data) {
this.value = data;
}
}
题目十三
Node类中的value是节点值, next指针和正常单链表中next指针的意义一
样, 都指向下一个节点, rand指针是Node类中新增的指针, 这个指针可
能指向链表中的任意一个节点, 也可能指向null。
给定一个由Node节点类型组成的无环单链表的头节点head, 请实现一个
函数完成这个链表中所有结构的复制, 并返回复制的新链表的头节点。
进阶: 不使用额外的数据结构, 只用有限几个变量, 且在时间复杂度为
O(N)内完成原问题要实现的函数。
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<time.h>
using namespace std;
class node
{
public:
int num;
node* next;
node* rand;
node()
{
num = 0;
next = NULL;
rand = NULL;
}
node(int n)
{
num = n;
next = NULL;
rand = NULL;
}
node* operator + (int r)//为了方便rand指针的产生,重载了node类的+运算符
{
node* res = this;
while (r)
{
res = res->next;
r--;
}
return res;
}
};
class List
{
public:
node *head;
node *end;
List()
{
head = NULL;
end = NULL;
}
List(List& l)
{
head = new node();
node* dum1 = l.head;
node* dum2 = head;
while (dum1)
{
dum2->num = dum1->num;
dum1 = dum1->next;
dum2 = dum2->next;
}
dum2->next = NULL;
end = dum2;
}
void insert(int dum)
{
node *n = new node();
n->num = dum;
if (!head)
{
head = n;
end = n;
}
else
{
n->next = end->next;
end->next = n;
end = n;
}
}
void genrand(int n)//list类产生rand指针的函数
{
srand(time(0));
node* temp = head;
while (temp != end)
{
int r = rand() % n;
temp->rand = (*head)+r;//不晓得怎么用类指针来调用node类的+运算符,所以用*解引用了
temp = temp->next;
}
end->rand = NULL;
}
~List()
{
node* dum = head;
node* beh = NULL;
while (dum)
{
beh = dum->next;
delete dum;
dum = beh;
}
}
};
//用hash实现copy
int main02()
{
List l;
for (int i = 0; i < 5; i++)
{
int dum;
cin >> dum;
l.insert(dum);
}
l.genrand(5);
map<node*,node*> hash;
node* dum = l.head;
while (dum)
{
node* copy = new node();
copy->num = dum->num;
hash.insert({dum,copy});
dum = dum->next;
}
for (auto it = hash.begin(); (it->first->next);it++)
{
it->second->next = hash.find(it->first->next)->second;
it->second->rand = hash.find(it->first->rand)->second;
}
hash[0][0];
return 0;
}
//直接用在链表上进行copy操作,且能实现时间复杂度为O(1)
int main()
{
List l;
for (int i = 0; i < 5; i++)
{
int dum;
cin >> dum;
l.insert(dum);
}
l.genrand(5);
node* temp = l.head;
//将copy结点链在要拷贝的结点后边
while (temp)
{
node* copy = new node(temp->num);
copy->next = temp->next;
temp->next = copy;
temp = copy->next;
}
//为copy结点赋值rand指针(深度拷贝)
temp = l.head;
while (temp->rand)
{
temp->next->rand = temp->rand->next;
temp = *temp + 2;
}
node* old = l.head;
node* copy = old->next;
//将copy链表和原链表分开
node* l1 = l.head;
node* l2 = NULL;
while (l1)
{
l2 = l1->next;
l1->next = l2->next;
l2->next = l1->next;
l1 = l1->next;
}
}