复杂单链表的复制

要求:
一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。

思路:
复杂链表的复制,难点在于random指针的复制。见下图:
这里写图片描述

按照一般的思路,单链表是无法进行 3–>1 的复制的。为了克服这个问题,我们将复制的节点,依次链接进入链表中,然后利用后移一个的特性完成复制,见下图:
这里写图片描述

然后定义一个头节点,用于返回,定义一个尾节点,用于尾插。同时将原来的链表链接回去,这样就完成了复制。
这里写图片描述

1、复杂链表的结构

typedef DataType int;

typedef struct ComplexNode
{
    DataType _data; // 数据 
    struct ComplexNode * _next; // 指向下一个节点的指针 
    struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空) 
}ComplexNode;

2、复杂链表生成节点函数

ComplexNode* BuyComplexList(DataType x)
{
    ComplexNode* tmp = NULL;
    tmp = (ComplexNode*)malloc(sizeof(ComplexNode));
    if (tmp == NULL)
    {
        printf("wrong\n");
        return 0;
    }

    tmp->_data = x;
    tmp->_next = NULL;
    tmp->_random = NULL;

    return tmp;
}

3、后插函数

void pushback(ComplexNode **list, DataType x)
{
    ComplexNode* tail = *list;
    //判空
    if (*list == NULL)
    {
        *list = BuyComplexList(x);
    }

    else
    {
        while (tail->_next)
        {
            tail = tail->_next;
        }

        tail->_next = BuyComplexList(x);
    }
}

4、查找函数
返回_data符合的节点

ComplexNode* findlist(ComplexNode* list, DataType x)
{
    while (list)
    {

        if (list->_data == x)
        {
            return list;
        }

        list = list->_next;
    }

    return NULL;
}

5、打印复杂链表

void printlist(ComplexNode* list)
{
    while (list)
    {
        printf("%d ", list->_data);
        list = list->_next;
    }

    printf("\n");
}

6、复杂链表的复制

ComplexNode* CopyComplexList(ComplexNode* List)
{
    assert(List);
    //cur指向当前节点,next指向cur下一个节点
    ComplexNode* head = List;
    ComplexNode* tail = NULL;
    ComplexNode* cur = head;
    ComplexNode* copy = NULL;
    ComplexNode* next = cur;

    while (cur)
    {
        //1、拷贝、链接、置random
        next = cur->_next;
        //copy 就是复制的节点
        copy = BuyComplexList(cur->_data);

        cur->_next = copy;
        copy->_next = next;
        //让copy的random指向cur的random的后一个
        if (cur->_random)
        {
            copy->_random = cur->_random->_next;
        }

        cur = next;
    }

    //2、拆、链接
    //将cur从尾置成头,将copy置成cur下一个节点
    cur = head;
    copy = cur->_next;

    //链接头,将第一个节点的链接特殊处理
    cur->_next = copy->_next;
    cur = copy->_next;

    head = tail = copy;

    //链接后面节点
    while (cur)
    {
        copy = cur->_next;
        cur->_next = copy->_next;
        cur = copy->_next;
        tail->_next = copy;
        tail = tail->_next;
    }

    tail->_next = NULL;

    return head;
}

7、创建一个复杂链表并检验

int main()
{
    ComplexNode *List = NULL;
    //创建一个复杂链表,见上图
    pushback(&List, 1);
    pushback(&List, 2);
    pushback(&List, 3);
    pushback(&List, 4);
    pushback(&List, 5);
    findlist(List, 1)->_random = findlist(List, 2);
    findlist(List, 2)->_random = findlist(List, 4);
    findlist(List, 3)->_random = findlist(List, 1);
    findlist(List, 4)->_random = NULL;
    findlist(List, 5)->_random = findlist(List, 5);

    //检验复杂链表的复制
    printlist(CopyComplexList(List));
    //节点4这样检验会出问题,因为4指向了NULL,没有_data的存在
    printf("%d\n", findlist(List, 1)->_random->_data);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值