复杂链表的复制是一个难点,但是也是链表面试题的重点。今天我们就来看下复杂链表的赋值。
1. 复杂链表(ComplexList)
template<class T>
struct ComplexListNode
{
T _data;
ComplexListNode<T>* pNext; //next指针域
ComplexListNode<T>* pRandom; //随机指针域
};
复杂链表的复杂之处在于它多了一个随机指针域(Random),随机指针域的指针可以指向链表的任意位置,包括自己,其他任意一个结点,NULL等。
复杂链表复制的复杂之处就是对于随机指针的处理,在单纯的复制了每一个结点之后,它的随机指针域的指向需要我们分析和寻找,如果每个结点都从头遍历的话,时间复杂度就是O(n^2)。操作也比较困难。
2. 复杂链表的复制
复杂链表的复制分为三步,第一步:将所有结点复制,先不处理结点的随机指针域,将复制后的结点插入到对应结点的后面。
第二步:处理随机指针域:想一下,原链表中结点N的随机指针域指向的结点S,在第一步操作完成后,结点N对应的结点N'的随机指针域指向的结点一定是S’(S'是S的复制结点)。
第三步:将新链表分成两个链表,即原链表和复制后的链表。
3.每一步所对应的代码
typedef ComplexListNode<T> Node;
typedef Node* pNode;
第一步:复制结点
void ComNodeClone(pNode pHead)
{
if (pHead == NULL)
return;
pNode pCur = pHead;
while (pCur != NULL)
{
pNode pClone = new Node();
pClone->_data = pCur->_data;
pClone->pNext = pCur->pNext;
pClone->pRandom = NULL;
pCur->pNext = pClone;
pCur = pClone->pNext;
}
}
第二步:处理随机指针域
//第二步:处理随机指针域
void SetRandom(pNode pHead)
{
if (pHead == NULL)
return;
pNode pCur = pHead;
while (pCur != NULL)
{
pNode pClone = pCur->pNext;
if (pCur->pRandom!=NULL)
pClone->pRandom = pCur->pRandom->pNext;
pCur = pClone->pNext;
}
}
第三步:分离链表
pNode ReConnectList(pNode pHead)
{
pNode pCur = pHead;
pNode pCloneHead = NULL;
pNode pCloneNode = NULL;
if (pCur != NULL)
{
pCloneHead = pCloneNode = pCur->pNext;
pCur->pNext = pCloneNode->pNext;
pCur = pCur->pNext;
}
while (pCur != NULL)
{
pCloneNode->pNext = pCur->pNext;
pCloneNode = pCloneNode->pNext;
pCur->pNext = pCloneNode->pNext;
pCur = pCur->pNext;
}
return pCloneHead;
}
整体代码:
#include <iostream>
using namespace std;
template<class T>
struct ComplexListNode
{
T _data;
ComplexListNode<T>* pNext; //next指针域
ComplexListNode<T>* pRandom; //随机指针域
};
template<class T>
class Solution
{
typedef ComplexListNode<T> Node;
typedef Node* pNode;
public:
pNode ComplexListClone(pNode pHead)
{
ComNodeClone( pHead);
SetRandom( pHead);
return ReConnectList( pHead);
}
private:
//第一步:将所有结点复制,将复制后的结点插入到对应结点的后面
void ComNodeClone(pNode pHead)
{
if (pHead == NULL)
return;
pNode pCur = pHead;
while (pCur != NULL)
{
pNode pClone = new Node();
pClone->_data = pCur->_data;
pClone->pNext = pCur->pNext;
pClone->pRandom = NULL;
pCur->pNext = pClone;
pCur = pClone->pNext;
}
}
//第二步:处理随机指针域
void SetRandom(pNode pHead)
{
if (pHead == NULL)
return;
pNode pCur = pHead;
while (pCur != NULL)
{
pNode pClone = pCur->pNext;
if (pCur->pRandom!=NULL)
pClone->pRandom = pCur->pRandom->pNext;
pCur = pClone->pNext;
}
}
//第三步:分离链表
pNode ReConnectList(pNode pHead)
{
pNode pCur = pHead;
pNode pCloneHead = NULL;
pNode pCloneNode = NULL;
if (pCur != NULL)
{
pCloneHead = pCloneNode = pCur->pNext;
pCur->pNext = pCloneNode->pNext;
pCur = pCur->pNext;
}
while (pCur != NULL)
{
pCloneNode->pNext = pCur->pNext;
pCloneNode = pCloneNode->pNext;
pCur->pNext = pCloneNode->pNext;
pCur = pCur->pNext;
}
return pCloneHead;
}
};