面试题26:复杂链表的复制

/*请实现函数ComplexListNode* Clone(ComplexListNode *pHead),复制一个复制链表,在复杂链表中,
每个结点除了一个m_pNext指针指向下一个节点外,还有一个m_pSibling指向链表中的任意结点或者NULL*/
#include <iostream>
using namespace std;
//复杂链表结点定义
struct ComplexLinkListNode
{
    int m_nValue;
    ComplexLinkListNode *m_pNext;
    ComplexLinkListNode *m_pSibling;
};
//创建链表结点
ComplexLinkListNode *CreateLinkListNode(int ival)
{
    ComplexLinkListNode *OneNode = new ComplexLinkListNode();
    OneNode -> m_nValue = ival;
    OneNode -> m_pNext = NULL;
    OneNode -> m_pSibling =NULL;
    return OneNode;
}
//连接结点
void ConnectLinkList(ComplexLinkListNode *pNode1, ComplexLinkListNode *pNode2, ComplexLinkListNode *pNode3)
{
    pNode1 -> m_pNext = pNode2;
    pNode1 -> m_pSibling = pNode3;
}
//释放空间(递归实现,从尾结点开始递归删除结点)
void FreeSpace(ComplexLinkListNode *pHead)
{
    if(pHead != NULL)
    {
        FreeSpace(pHead -> m_pNext);
        delete pHead;
    }
}
//第一步:复制结点并连接成这样A -> A' -> B -> B' ...
void CloneNodes(ComplexLinkListNode *pHead)
{
    ComplexLinkListNode *pNode = pHead;
    while(pNode != NULL)
    {
        //动态分配空间创建一个复制结点
        ComplexLinkListNode *pCloned = new ComplexLinkListNode();
        //复制头结点值,指针
        pCloned -> m_nValue = pNode -> m_nValue;
        pCloned -> m_pNext = pNode -> m_pNext;
        pCloned -> m_pSibling = NULL;
        //连接头结点和其复制结点
        pNode -> m_pNext = pCloned;
        //指向下一个需要复制的结点
        pNode = pCloned -> m_pNext;
    }
}
//第二步:复制结点任意结点之间的连接
void ConnectSiblingNodes(ComplexLinkListNode *pHead)
{
    ComplexLinkListNode *pNode = pHead;
    while(pNode != NULL)
    {
       ComplexLinkListNode *pCloned = pNode -> m_pNext;
       if(pNode -> m_pSibling != NULL)
       {
           pCloned -> m_pSibling = pNode -> m_pSibling -> m_pNext;
       }
       pNode = pCloned -> m_pNext;
    }
}
//第三步:拆分链表 ->  奇数位置上的点组成原链表,偶数位置上的点组成复制出来的链表
ComplexLinkListNode *ReconnectNodes(ComplexLinkListNode *pHead)
{
    //创建指向原链表结点的指针,并赋头结点的初值
    ComplexLinkListNode *pNode = pHead;
    //创建指向复制链表头结点的指针
    ComplexLinkListNode *pClonedHead = NULL;
    //创建指向复制链表结点的指针
    ComplexLinkListNode *pClonedNode = NULL;
    //从头结点开始拆分链表
    if(pNode != NULL)
    {
        pClonedHead = pClonedNode = pNode -> m_pNext;
        pNode -> m_pNext = pClonedNode -> m_pNext;
        //指向下一个原链表的结点
        pNode = pNode -> m_pNext;
    }
    while(pNode != NULL)
    {
        //复制结点之间的连接
        pClonedNode -> m_pNext = pNode -> m_pNext;
        pClonedNode = pClonedNode -> m_pNext;
        //原链表结点之间的连接
        pNode -> m_pNext = pClonedNode -> m_pNext;
        pNode = pNode -> m_pNext;
    }
    //返回复制链表的头结点
    return pClonedHead;
}
//第四步:封装以上三步
ComplexLinkListNode *Clone(ComplexLinkListNode *pHead)
{
    CloneNodes(pHead);
    ConnectSiblingNodes(pHead);
    return ReconnectNodes(pHead);
}
//输出链表
void PrintLinklist(ComplexLinkListNode *pHead)
{
    if(pHead == NULL)
    return;
    while(pHead != NULL)
    {
        cout << pHead -> m_nValue << " ";
        pHead = pHead -> m_pNext;
    }
    cout << endl;
}
//=======测试代码======
void Test(char *TestName, ComplexLinkListNode *pHead)
{
    if(TestName != NULL)
    cout << TestName << " Begins: " << endl;
    cout << "The original Linklist is: " << endl;
    PrintLinklist(pHead);

    ComplexLinkListNode *pClonedHead = Clone(pHead);
    cout << "The cloned Linklist is: " << endl;
    PrintLinklist(pClonedHead);
    FreeSpace(pHead);
    FreeSpace(pClonedHead);
}
//=======测试用例======
//          -----------------
//         \|/              |
//  1-------2-------3-------4-------5
//  |       |      /|\             /|\
//  --------+--------               |
//          -------------------------
void Test1()
{
    ComplexLinkListNode *pNode1 = CreateLinkListNode(1);
    ComplexLinkListNode *pNode2 = CreateLinkListNode(2);
    ComplexLinkListNode *pNode3 = CreateLinkListNode(3);
    ComplexLinkListNode *pNode4 = CreateLinkListNode(4);
    ComplexLinkListNode *pNode5 = CreateLinkListNode(5);

    ConnectLinkList(pNode1, pNode2, pNode3);
    ConnectLinkList(pNode2, pNode3, pNode5);
    ConnectLinkList(pNode3, pNode4, NULL);
    ConnectLinkList(pNode4, pNode5, pNode2);

    Test("Test1", pNode1);
}
// m_pSibling指向结点自身
//          -----------------
//         \|/              |
//  1-------2-------3-------4-------5
//         |       | /|\           /|\
//         |       | --             |
//         |------------------------|
void Test2()
{
    ComplexLinkListNode *pNode1 = CreateLinkListNode(1);
    ComplexLinkListNode *pNode2 = CreateLinkListNode(2);
    ComplexLinkListNode *pNode3 = CreateLinkListNode(3);
    ComplexLinkListNode *pNode4 = CreateLinkListNode(4);
    ComplexLinkListNode *pNode5 = CreateLinkListNode(5);

    ConnectLinkList(pNode1, pNode2, NULL);
    ConnectLinkList(pNode2, pNode3, pNode5);
    ConnectLinkList(pNode3, pNode4, pNode3);
    ConnectLinkList(pNode4, pNode5, pNode2);

    Test("Test2", pNode1);
}
// m_pSibling形成环
//          -----------------
//         \|/              |
//  1-------2-------3-------4-------5
//          |              /|\
//          |               |
//          |---------------|
void Test3()
{
    ComplexLinkListNode *pNode1 = CreateLinkListNode(1);
    ComplexLinkListNode *pNode2 = CreateLinkListNode(2);
    ComplexLinkListNode *pNode3 = CreateLinkListNode(3);
    ComplexLinkListNode *pNode4 = CreateLinkListNode(4);
    ComplexLinkListNode *pNode5 = CreateLinkListNode(5);

    ConnectLinkList(pNode1, pNode2, NULL);
    ConnectLinkList(pNode2, pNode3, pNode5);
    ConnectLinkList(pNode3, pNode4, NULL);
    ConnectLinkList(pNode4, pNode5, pNode2);
    Test("Test3", pNode1);
}
//只有一个结点
void Test4()
{
    ComplexLinkListNode *pNode1 = CreateLinkListNode(1);
    ConnectLinkList(pNode1, NULL, pNode1);// ConnectLinkList(pNode1, pNode1, NULL)是不同的,
                                            //这个函数会循环输出
    Test("Test4", pNode1);
}
//输入为空指针的鲁棒性测试
void Test5()
{
    Test("Test5", NULL);
}
int main()
{
    Test1();
    cout << endl;
    Test2();
    cout << endl;
    Test3();
    cout << endl;
    Test4();
    cout << endl;
    Test5();
    return 0;
}
/*把复杂链表的复制过程分解成三个步骤,同时把每个步骤都用图形化的方式表示出来,写代码的时候为每一个步骤
定义一个子函数,最后在复制函数中先后调用这三个函数*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值