说明:本文仅供学习交流,转载请标明出处,欢迎转载!
题目:复制一个复杂链表,所谓复杂链表指的是每个节点含有两个指针,一个指向单链表的下一个结点,一个指向单链表中的任意某个结点,或者该指针为空。
为了方便起见,我们将待复制的链表称为原型链表,将复制后的新链表称为复制链表,将指向下一个结点的指针定义为next指针,指向其他位置的指针定义为any指针。《剑指offer》上给出了三种解决方法:(1)常规法;(2)空间换时间法;(3)紧随复制法。书上并给出了第三种方法的实现代码。这里我根据书上的提示,给出第二种方法的代码。
在给出代码之前我们先理解下实现的算法思想。我们知道,如果没有any指针,我们可以很容易得完成复制任务。但是有了any指针,我们就需要考虑如何复制每一个结点的any指针。算法2给出的思想是在构建一个单链表的过程中,设置复制结点与原型结点的一一映射关系,这样在创建完新的单链表之后,我们可以通过原型结点的any指针指向的结点位置,通过查询映射表来获得复制结点的any指针的指向,显然我们可以用hash表或者其他具有映射思想的数据结构,如红黑树。在C++STL中,我们可以采用map容器来实现这一映射。
为了更清晰地理解该复制过程,我们给出如下复杂链表:
该复制链表的创建代码如下:
#include<iostream>
#include<map>
using namespace std;
struct Node
{
int value;
Node* next;
Node* any;//指向某个结点
Node(int v):value(v),any(NULL),next(NULL){}
};
/*创建一个链表,1->2->3->4->5->6->7*/
Node* CreateList()//创建一个单链表
{
Node *head;
Node *n1=new Node(1);
Node *n2=new Node(2);
Node *n3=new Node(3);
Node *n4=new Node(4);
Node *n5=new Node(5);
Node *n6=new Node(6);
Node *n7=new Node(7);
head=n1;
n1->next=n2;
n1->any=n3;
n2->next=n3;
n2->any=n4;
n3->next=n4;
n4->next=n5;
n5->any=n7;
n5->next=n6;
n6->next=n7;
n7->next=NULL;
return head;
}
void FreeList(Node *head)//将链表空间释放
{
if(head==NULL)
{
return ;
}
else
{
Node *temp=head->next;
delete head;
head=temp;
FreeList(head);
}
}
void VisitList(Node *head)//遍历链表中的元素,用递归的方法遍历
{
if(!head) return ;
Node *p=head;
while(p)
{
cout<<"("<<p->value;
if(p->any)
{
cout<<","<<p->any->value<<")";
}
else
{
cout<<",nil)";
}
if(p->next)
{
cout<<"->";
}
p=p->next;
}
cout<<endl;
}
复制复杂链表的实现代码如下:
Node *Clone(Node *head)//用hash法保存any指针
{
if(head==NULL)return NULL;
Node *p=head;//p用于扫描原链表
Node *head1=NULL,*p1=NULL;//head1指向复制链表,p1用于扫描复制链表
map<Node*,Node*>m;
while(p)//依次复制将结点值和next指针
{
if(!head1)
{
p1=new Node(p->value);
head1=p1;
}
else
{
p1->next=new Node(p->value);
p1=p1->next;
}
m[p]=p1;//建立原结点与新结点直接的映射关系
p=p->next;
}
p=head;
p1=head1;
while(p)//依次复制每个结点的any指针
{
p1->any=m[p->any];
p=p->next;
p1=p1->next;
}
return head1;
}
测试代码如下:
int main()
{
Node *head=CreateList();
cout<<"原链表输出为:";
VisitList(head);
Node *head1=Clone(head);
cout<<"复制链表输出为:";
VisitList(head1);
FreeList(head);//释放链表空间
return 0;
}
测试结果如下:
参考资料------------《剑指offer》