复杂链表的复制

首先简单介绍一下复杂链表的概念,复杂链表在结构上比无头单链表多了一个随机指针域,所以有更多的不确定性。

大概长这样:

typedef struct SList{
    Datatype _data;
    struct SList* _pNext;   //指向下一个结点
    struct SList* _Random;  //指向随机的某一个结点,也可能指向空
}Node,*PNode;

那么复杂链表该如何复制呢?

思路1:先将原链表按照Next的顺序尾插复制一遍,然后遍历查找他的随机指针域,记录位置,依次给每个链表的随机指针域赋值,但是这样的复制非常低效,假如每一个指针的随机指针域都指向最后一个结点,那么就是说每次复制的时候都要把整个链表遍历一遍,他的时间复杂度是O(n^2).

思路2:每次给原链表的每一个结点插入一个新结点,新结点的数据域和前一个结点相同,那么新结点的随机指针域就是前一个结点的随机指针域所指向的结点的下一个结点,这样我们复制起来就会变得轻松许多,之后再把新复制的链表拆分下来,就完成本次复制。这个算法的时间复杂度只有O(n).

按照思路2写下的代码如下:
头文件:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int Datatype;

typedef struct SList{
    Datatype _data;
    struct SList* _pNext;   //指向下一个结点
    struct SList* _Random;  //指向随机的某一个结点,也可能指向空
}Node,*PNode;

void SListInit(PNode* PHead);

void SListPushBack(PNode* PHead,Datatype data);

PNode FindNode(PNode PHead, int num);

PNode CopyComplexList(PNode* PHead);

功能模块:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Apr_18.h"

PNode BuyNode(Datatype data)        //申请新结点
{
    PNode NewNode;
    NewNode = (PNode)malloc(sizeof(Node));
    NewNode->_data = data;
    NewNode->_pNext = NULL;
    return NewNode;
}

void SListInit(PNode* PHead)
{
    assert(PHead);

    *PHead = NULL;
}

void SListPushBack(PNode* PHead, Datatype data) //尾插
{
    PNode NewNode;
    assert(PHead);

    if (NULL == (*PHead))
    {
        (*PHead) = BuyNode(data);
    }
    else
    {
        PNode PCur = (*PHead);
        NewNode = BuyNode(data);
        while (PCur->_pNext)
        {
            PCur = PCur->_pNext;
        }
        PCur->_pNext = NewNode;
    }
}

PNode FindNode(PNode PHead, int num)    //查找第num个结点
{
    PNode PCur;
    if (NULL == PHead)
        return NULL;

    PCur = PHead;
    while (--num)
    {
        if (PCur->_pNext)
            PCur = PCur->_pNext;
    }
    return PCur;
}

PNode CopyComplexList(PNode* PHead) //复杂链表的复制
{
    PNode PCur;
    PNode NewNode;
    PNode PPre;
    if (!PHead)
        return;

    PCur = (*PHead);
    while (PCur)    //将新结点复制一份到原结点的后一位
    {
        NewNode = BuyNode(PCur->_data);
        NewNode->_pNext = PCur->_pNext;
        PCur->_pNext = NewNode;
        PCur = NewNode->_pNext;
    }

    PCur = (*PHead);
    NewNode = PCur->_pNext;
    while (NewNode->_pNext) //复制随机指针
    {
        NewNode->_Random = PCur->_Random->_pNext;
        PCur = PCur->_pNext->_pNext;
        NewNode = NewNode->_pNext->_pNext;
    }

    PCur = (*PHead);
    NewNode = PCur->_pNext;
    PPre = NewNode;
    while (PCur)   //拆分新链表
    {
        PCur->_pNext = NewNode->_pNext;
        PCur = PCur->_pNext;
        if (PCur)
        {
            NewNode->_pNext = PCur->_pNext;
            NewNode = NewNode->_pNext;
        }
    }
    return PPre;
}

测试模块:

#include"Apr_18.h"

void Test()
{
    PNode PHead,tmp,tmp2;
    SListInit(&PHead);
    SListPushBack(&PHead, 1);
    SListPushBack(&PHead, 2);
    SListPushBack(&PHead, 3);
    SListPushBack(&PHead, 4);
    tmp = FindNode(PHead, 3);
    PHead->_Random = tmp;
    tmp->_Random = tmp;
    tmp = FindNode(PHead, 1);
    tmp2 = FindNode(PHead, 2);
    tmp2->_Random = tmp;
    tmp = CopyComplexList(&PHead);
}

int main()
{
    Test();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值