一、题目
请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling 指向链表中的任意结点或者nullptr。
二、关键
1.在原始链表上扩充新的链表。
2.m_pSibling指针的指向问题。
3.拆分链表。
三、解释
1.解题思路一:根据原始链表中的节点N创建对应的节点N'。
第一步,复制原始链表的任意节点N并创建新节点N',再把N'连接到N的后面。
第二步,设置复制出来的节点的m_pSibling.假设原始链表上的N的m_pSibling指向节点S,那么对应复制出来的N'是N的m_pNext指向节点,同样S'也是S的m_pNext指向的节点。(如果原始链表上的节点N的m_pSibiling指向S,则它对应的复制节点N'的m_pSibling指向S的复制节点S‘。)
第三步,经过上面两步之后得到的长链表拆分成两个链表。把奇数位的节点用m_pNext链接起来就是原始链表,把偶数位的节点用m_pNext链接起来就是复制出来的链表。
2.解题思路二:分两步。第一步复制原始链表上的每个节点N创建N',然后把这些创建出来的节点用m_pNext链接起来。同时,我们把<N,N'>的配对信息放到一个哈希表中;第二步设置复制链表上每个节点的m_pSibling。如果在原始链表中节点N的m_pSibling指向节点S,那么在复制链表中,对应的N'应该指向S'。由于有了哈希表,我们可以用O(1)的时间根据S找到S'。
四、代码
complexList.h如下:
#pragma once
struct ComplexListNode
{
int m_nValue;
ComplexListNode* m_pNext;
ComplexListNode* m_pSibling;
};
ComplexListNode* CreateNode(int nValue);
void BuildNodes(ComplexListNode* pNode, ComplexListNode* pNext, ComplexListNode* pSibling);
void PrintList(ComplexListNode* pHead);
complexList.cpp如下
#include <cstdio>
#include "ComplexList.h"
ComplexListNode* CreateNode(int nValue)
{
ComplexListNode* pNode = new ComplexListNode();
pNode->m_nValue = nValue;
pNode->m_pNext = nullptr;
pNode->m_pSibling = nullptr;
return pNode;
}
void BuildNodes(ComplexListNode* pNode, ComplexListNode* pNext, ComplexListNode* pSibling)
{
if(pNode != nullptr)
{
pNode->m_pNext = pNext;
pNode->m_pSibling = pSibling;
}
}
void PrintList(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
while(pNode != nullptr)
{
printf("The value of this node is: %d.\n", pNode->m_nValue);
if(pNode->m_pSibling != nullptr)
printf("The value of its sibling is: %d.\n", pNode->m_pSibling->m_nValue);
else
printf("This node does not have a sibling.\n");
printf("\n");
pNode = pNode->m_pNext;
}
}
copycomplexList.cpp如下:
#include <cstdio>
#include "ComplexList.h"
void CloneNodes(ComplexListNode* pHead);
void ConnectSiblingNodes(ComplexListNode* pHead);
ComplexListNode* ReconnectNodes(ComplexListNode* pHead);
ComplexListNode* Clone(ComplexListNode* pHead)
{
CloneNodes(pHead);
ConnectSiblingNodes(pHead);
return ReconnectNodes(pHead);
}
void CloneNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
while(pNode != nullptr)
{
ComplexListNode* pCloned = new ComplexListNode();
pCloned->m_nValue = pNode->m_nValue;
pCloned->m_pNext = pNode->m_pNext;
pCloned->m_pSibling = nullptr;
pNode->m_pNext = pCloned;
pNode = pCloned->m_pNext;
}
}
void ConnectSiblingNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
while(pNode != nullptr)
{
ComplexListNode* pCloned = pNode->m_pNext;
if(pNode->m_pSibling != nullptr)
{
pCloned->m_pSibling = pNode->m_pSibling->m_pNext;
}
pNode = pCloned->m_pNext;
}
}
ComplexListNode* ReconnectNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
ComplexListNode* pClonedHead = nullptr;
ComplexListNode* pClonedNode = nullptr;
if(pNode != nullptr)
{
pClonedHead = pClonedNode = pNode->m_pNext;
pNode->m_pNext = pClonedNode->m_pNext;
pNode = pNode->m_pNext;
}
while(pNode != nullptr)
{
pClonedNode->m_pNext = pNode->m_pNext;
pClonedNode = pClonedNode->m_pNext;
pNode->m_pNext = pClonedNode->m_pNext;
pNode = pNode->m_pNext;
}
return pClonedHead;
}
// ====================测试代码====================
void Test(const char* testName, ComplexListNode* pHead)
{
if(testName != nullptr)
printf("%s begins:\n", testName);
printf("The original list is:\n");
PrintList(pHead);
ComplexListNode* pClonedHead = Clone(pHead);
printf("The cloned list is:\n");
PrintList(pClonedHead);
}
// -----------------
// \|/ |
// 1-------2-------3-------4-------5
// | | /|\ /|\
// --------+-------- |
// -------------------------
void Test1()
{
ComplexListNode* pNode1 = CreateNode(1);
ComplexListNode* pNode2 = CreateNode(2);
ComplexListNode* pNode3 = CreateNode(3);
ComplexListNode* pNode4 = CreateNode(4);
ComplexListNode* pNode5 = CreateNode(5);
BuildNodes(pNode1, pNode2, pNode3);
BuildNodes(pNode2, pNode3, pNode5);
BuildNodes(pNode3, pNode4, nullptr);
BuildNodes(pNode4, pNode5, pNode2);
Test("Test1", pNode1);
}
// m_pSibling指向结点自身
// -----------------
// \|/ |
// 1-------2-------3-------4-------5
// | | /|\ /|\
// | | -- |
// |------------------------|
void Test2()
{
ComplexListNode* pNode1 = CreateNode(1);
ComplexListNode* pNode2 = CreateNode(2);
ComplexListNode* pNode3 = CreateNode(3);
ComplexListNode* pNode4 = CreateNode(4);
ComplexListNode* pNode5 = CreateNode(5);
BuildNodes(pNode1, pNode2, nullptr);
BuildNodes(pNode2, pNode3, pNode5);
BuildNodes(pNode3, pNode4, pNode3);
BuildNodes(pNode4, pNode5, pNode2);
Test("Test2", pNode1);
}
// m_pSibling形成环
// -----------------
// \|/ |
// 1-------2-------3-------4-------5
// | /|\
// | |
// |---------------|
void Test3()
{
ComplexListNode* pNode1 = CreateNode(1);
ComplexListNode* pNode2 = CreateNode(2);
ComplexListNode* pNode3 = CreateNode(3);
ComplexListNode* pNode4 = CreateNode(4);
ComplexListNode* pNode5 = CreateNode(5);
BuildNodes(pNode1, pNode2, nullptr);
BuildNodes(pNode2, pNode3, pNode4);
BuildNodes(pNode3, pNode4, nullptr);
BuildNodes(pNode4, pNode5, pNode2);
Test("Test3", pNode1);
}
// 只有一个结点
void Test4()
{
ComplexListNode* pNode1 = CreateNode(1);
BuildNodes(pNode1, nullptr, pNode1);
Test("Test4", pNode1);
}
// 鲁棒性测试
void Test5()
{
Test("Test5", nullptr);
}
int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
return 0;
}