题目
复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
解法一
(暴力求解)
1. 这个复杂链表是以单链表为基础的,可以先复制一个单链表,random 指针在原链表上的位置与新链表是相对应的,建立同步投影指针 shadow,与 cur 在原链表上同步,找新链表上的 random ,(如果找不到,说明原链表指针指向了未知地址)。
2. 考虑复杂情况,原链表带环,可以找到入口点并记录,将带环链表转化为无环链表处理,再处理无环的情况。
写代码
- 处理空链表情况
- 用找环入口点函数判断是否带环
- 若带环,先复制尾,到入口点,复制环,又到入口点,复制完毕,拆环(原链表),保留尾,接环用。然后就是不带环链表 random 指针的复制。
- 若不带环,不带环链表复制。
- 复制 random 封装函数(要用两次,还很长)。
代码
//尾插
void PushBackCom(ComplexNode** ppList, int x)
{
assert(ppList);
ComplexNode* newTail = (ComplexNode*)malloc(sizeof(ComplexNode));
newTail->data = x;
newTail->next = NULL;
newTail->random = NULL;
if (*ppList == NULL)
*ppList = newTail;
else{
ComplexNode* plist = *ppList;
while (plist->next != NULL){
plist = plist->next;
}
plist->next = newTail;
}
}
//求入口点
ComplexNode* IntranceOfRingCom(ComplexNode* pList)
{
ComplexNode* fast = pList;
ComplexNode* slow = pList;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
break;
}
if (fast != slow || fast->next == NULL)
return NULL;
while (pList != slow)
{
pList = pList->next;
slow = slow->next;
}
return pList;
}
void copyRandom(ComplexNode* cur, ComplexNode* n_cur)
{
ComplexNode* newComList = n_cur;
ComplexNode* pList = cur;
while (n_cur != NULL)
{
if (cur->random != NULL)
{
ComplexNode* shadow = newComList;
ComplexNode* cur2 = pList;
while (cur->random != cur2 && cur2 != NULL)
{
shadow = shadow->next;
cur2 = cur2->next;
}
n_cur->random = shadow;
if (shadow == NULL)//在这里出现NULL,意味着有random指向非本链表的位置
printf("warn : point to unknowed node.");
}
else
n_cur->random = NULL;
n_cur = n_cur->next;
cur = cur->next;
}
}
ComplexNode* copyComplexList(ComplexNode* pList)
{
if (pList == NULL)return NULL;
ComplexNode* intr = IntranceOfRingCom(pList);
ComplexNode* newComList = NULL;
PushBackCom(&newComList, pList->data);
if (intr != NULL)
{
ComplexNode* n_intr = newComList;
ComplexNode* n_cur = newComList;
ComplexNode* cur = pList;
while (cur != intr)//尾复制
{
cur = cur->next;
PushBackCom(&n_cur, cur->data);
n_cur = n_cur->next;
n_intr = n_intr->next;
}
while (cur->next != intr)//环复制
{
cur = cur->next;
PushBackCom(&n_cur, cur->data);
n_cur = n_cur->next;
}
copyRandom(pList, newComList);
//接环,现在n_cur刚好是尾
n_cur->next = n_intr;
}
else
{
ComplexNode* n_cur = newComList;
ComplexNode* cur = pList;
while (cur->next != NULL)
{
cur = cur->next;
PushBackCom(&n_cur, cur->data);
n_cur = n_cur->next;
}
copyRandom(pList, newComList);
}
return newComList;
}
方法二
(没有处理带环情况,可参考方法一处理带环情况)
代码
ComplexNode* copyComplexList2(ComplexNode* pList)
{
if (pList == NULL)return NULL;
ComplexNode* cur = pList;
ComplexNode* newcode;
while (cur != NULL)
{
newcode = (ComplexNode*)malloc(sizeof(ComplexNode));
newcode->data = cur->data;
newcode->next = cur->next;
newcode->random = NULL;
cur->next = newcode;
cur = cur->next->next;
}
cur = pList;
newcode = pList->next;
while (cur != NULL)
{
if (cur->random != NULL)
newcode->random = cur->random->next;
newcode = cur->next;
cur = cur->next->next;
}
newcode = pList->next;
ComplexNode* ret = pList->next;
cur = pList;
cur->next = cur->next->next;
cur = cur->next;
while (cur != NULL)
{
newcode->next = newcode->next->next;
cur->next = cur->next->next;
cur = cur->next;
newcode = newcode->next;
}
return ret;
}