九度 题目1524:复杂链表的复制

题目来源:http://ac.jobdu.com/problem.php?pid=1524

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:342

解决:170

题目描述:

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点)。

输入:

输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行为一个整数n (1<=n<=1000):n代表将要输入的链表元素的个数。(节点编号从1开始)。
接下来有n个数,表示链表节点中的值。
接下来有n个数Ti,Ti表示第i个节点的另一个指针指向。
Ti = 0 表示这个指针为NULL。

输出:

对应每个测试案例,
输出n行,每行有二个数,第一个代表当前节点值,第二个代表当前节点的特殊指针的值。

样例输入:
5
1 2 3 4 5
3 5 0 2 0
样例输出:
1 3
2 5
3 0
4 2
5 0 
分析:

    这题是考察细心程度的。本题可以拿空间来换取时间,但有另外一种思路,即:

(1)在每个结点N之后克隆(复制)一个结点N',并把N'链接到N的后面作为N的后继结点,先不处理其pSibling指针,处理复制节点的同时把pSilbing指针赋值为NULL。如图:


(2)现在处理每个克隆(复制)结点的pSibling指针,如若原结点N的pSibling指针指向结点S,则,N'的pSibling指针指向结点S的pNext结点。如图:


(3)现在就要把结点从原链表中拆分开来,我们可以看到奇数位是原链表中原有的结点,偶数位是克隆(复制)的结点,注意:如果带有头结点的话,pCloneHead要申请分配一个空间,其余处理与不带头结点类似。如图:


我写的是带头结点的,与上图有稍微差别,注意理解!

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

struct Link_Node
{
    int iData;
    Link_Node* pNext;
    Link_Node* pSibling;
    Link_Node()
    {
        iData = 0;
        pNext = pSibling = NULL;
    }
};

void Clone_Node(Link_Node* pHead)
{
    Link_Node* pNode = pHead->pNext;
    Link_Node* pCloneNode = NULL;
    while(pNode != NULL)
    {
        pCloneNode = new Link_Node();
        pCloneNode->iData = pNode->iData;
        pCloneNode->pNext = pNode->pNext;
        pNode->pNext = pCloneNode;
        pCloneNode->pSibling = NULL;

        pNode = pCloneNode->pNext;
    }
}

void ConnectSiblingNode(Link_Node* pHead)
{
    Link_Node* pNode = pHead->pNext;
    Link_Node* pCloneNode = NULL;
    while(pNode != NULL)
    {
        pCloneNode = pNode->pNext;
        if(pNode->pSibling != NULL)
            pCloneNode->pSibling = pNode->pSibling->pNext;
        pNode = pCloneNode->pNext;
    }
}

Link_Node* ReConnetCloneLink(Link_Node* pHead)
{
    Link_Node* pNode = pHead->pNext;
    Link_Node* pCloneHead = new Link_Node();
    Link_Node* pCloneNode = pNode->pNext;
    pCloneHead->pNext = pCloneNode;
    if(pNode != NULL)
    {
        pCloneNode = pNode->pNext;
        pNode->pNext = pCloneNode->pNext;
        pNode = pNode->pNext;
    }
    while(pNode != NULL)
    {
        pCloneNode->pNext = pNode->pNext;
        pCloneNode = pCloneNode->pNext;
        pNode->pNext = pCloneNode->pNext;
        pNode = pNode->pNext;
    }
    return pCloneHead;
}

void Delete_Link(Link_Node* pHead)
{
    Link_Node* p1 = pHead;
    Link_Node* p2 = NULL;
    while(p1 != NULL)
    {
        p2 = p1->pNext;
        delete p1;
        p1 = p2;
    }
}

void Print_CloneLink(Link_Node* pHead)
{
    Link_Node* pNode = pHead->pNext;
    while(pNode != NULL)
    {
        printf("%d", pNode->iData);
        if(pNode->pSibling != NULL)
            printf(" %d\n", pNode->pSibling->iData);
        else
            printf(" 0\n");
        pNode = pNode->pNext;
    }
    Delete_Link(pHead);
}

void Clone_Link(Link_Node* pHead)
{
    Clone_Node(pHead);
    ConnectSiblingNode(pHead);
    Print_CloneLink(ReConnetCloneLink(pHead));
}

int main()
{
    int n, i, a;
    Link_Node* pHead;
    while(~scanf("%d", &n))
    {
        pHead = new Link_Node();
        Link_Node* p1 = pHead;
        Link_Node* pNode = NULL;
        for(i = 0; i < n; ++i)
        {
            pNode = new Link_Node();
            scanf("%d", &a);
            pNode->iData = a;
            p1->pNext = pNode;
            p1 = pNode;
        }
        p1 = pHead->pNext;
        Link_Node* p2 = p1;
        for(i = 0; i < n; ++i)
        {
            scanf("%d", &a);
            if(a == 0)
                p1->pSibling = NULL;
            else
            {
                while(a > 1)
                    p2 = p2->pNext, --a;
                p1->pSibling = p2;
                p2 = pHead->pNext;
            }
            p1 = p1->pNext;
        }
        Clone_Link(pHead);
        Delete_Link(pHead);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值