要求:
一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
思路:
复杂链表的复制,难点在于random指针的复制。见下图:
按照一般的思路,单链表是无法进行 3–>1 的复制的。为了克服这个问题,我们将复制的节点,依次链接进入链表中,然后利用后移一个的特性完成复制,见下图:
然后定义一个头节点,用于返回,定义一个尾节点,用于尾插。同时将原来的链表链接回去,这样就完成了复制。
1、复杂链表的结构
typedef DataType int;
typedef struct ComplexNode
{
DataType _data; // 数据
struct ComplexNode * _next; // 指向下一个节点的指针
struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
}ComplexNode;
2、复杂链表生成节点函数
ComplexNode* BuyComplexList(DataType x)
{
ComplexNode* tmp = NULL;
tmp = (ComplexNode*)malloc(sizeof(ComplexNode));
if (tmp == NULL)
{
printf("wrong\n");
return 0;
}
tmp->_data = x;
tmp->_next = NULL;
tmp->_random = NULL;
return tmp;
}
3、后插函数
void pushback(ComplexNode **list, DataType x)
{
ComplexNode* tail = *list;
//判空
if (*list == NULL)
{
*list = BuyComplexList(x);
}
else
{
while (tail->_next)
{
tail = tail->_next;
}
tail->_next = BuyComplexList(x);
}
}
4、查找函数
返回_data符合的节点
ComplexNode* findlist(ComplexNode* list, DataType x)
{
while (list)
{
if (list->_data == x)
{
return list;
}
list = list->_next;
}
return NULL;
}
5、打印复杂链表
void printlist(ComplexNode* list)
{
while (list)
{
printf("%d ", list->_data);
list = list->_next;
}
printf("\n");
}
6、复杂链表的复制
ComplexNode* CopyComplexList(ComplexNode* List)
{
assert(List);
//cur指向当前节点,next指向cur下一个节点
ComplexNode* head = List;
ComplexNode* tail = NULL;
ComplexNode* cur = head;
ComplexNode* copy = NULL;
ComplexNode* next = cur;
while (cur)
{
//1、拷贝、链接、置random
next = cur->_next;
//copy 就是复制的节点
copy = BuyComplexList(cur->_data);
cur->_next = copy;
copy->_next = next;
//让copy的random指向cur的random的后一个
if (cur->_random)
{
copy->_random = cur->_random->_next;
}
cur = next;
}
//2、拆、链接
//将cur从尾置成头,将copy置成cur下一个节点
cur = head;
copy = cur->_next;
//链接头,将第一个节点的链接特殊处理
cur->_next = copy->_next;
cur = copy->_next;
head = tail = copy;
//链接后面节点
while (cur)
{
copy = cur->_next;
cur->_next = copy->_next;
cur = copy->_next;
tail->_next = copy;
tail = tail->_next;
}
tail->_next = NULL;
return head;
}
7、创建一个复杂链表并检验
int main()
{
ComplexNode *List = NULL;
//创建一个复杂链表,见上图
pushback(&List, 1);
pushback(&List, 2);
pushback(&List, 3);
pushback(&List, 4);
pushback(&List, 5);
findlist(List, 1)->_random = findlist(List, 2);
findlist(List, 2)->_random = findlist(List, 4);
findlist(List, 3)->_random = findlist(List, 1);
findlist(List, 4)->_random = NULL;
findlist(List, 5)->_random = findlist(List, 5);
//检验复杂链表的复制
printlist(CopyComplexList(List));
//节点4这样检验会出问题,因为4指向了NULL,没有_data的存在
printf("%d\n", findlist(List, 1)->_random->_data);
return 0;
}