首先简单介绍一下复杂链表的概念,复杂链表在结构上比无头单链表多了一个随机指针域,所以有更多的不确定性。
大概长这样:
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;
}