经典面试之复杂链表的简单实现
对于复杂链表复制问题,如果只是单纯的实现这个功能,他其实是不难的。你可以在时间空间没有要求的情况下勉强的实现它。(主要问题就在于Random指针的重新定位了)
我就简单说说那些个常规方法的繁琐实现了:
void ComplexListCopy(ComplexList &List, ComplexList &ListCopy);
1.借助于一个指针数组保存源链表的地址,然后在连接新链表之时重新遍历源链表,进行random的定位。大概的伪代码实现如下
void ComplexListCopy(ComplexList &List, ComplexList &ListCopy)void ComplexListcopy(complexList &List,ComplexList &ListCop)
{
ComplexListNode* parr[100];
int Len = Length(List);///得到源链表长度
ComplexListNode *cur = List.head._next;//第一个
int i = 0;
//除了random,其他问题都没有;
while(cur)
{
parr[i++] = cur;
ComplexListNode *tmp = BuyNode(cur->_data);
PushBack(ListCop,tmp);
cur = cur->_next;
}
//通过遍历数组以及List确定ListCop的random连接问题
ComplexListNode *curC = ListCop.head._next;
i = 0;
while(curC)
{
ComplexListNode* tmp = List.head._next;//List 的头
int count = 0;
//找到random指向的下标数
while(tmp != parr[i])
{
tmp=tmp->_next;
}
tmp = ListCop.head._next;
while(count--)
{
curC->_randomPiont = tmp;
}
i++;
curC = curC->_next;
}
}
然而这个实在是太戳了,,浪费空间浪费时间。那么一种比较好的做法就是,不借助第三方变量,直接处在源链表中插入,然后通过相对位置处理了randomPoint 问题。这个图画的有些失败,简单说说
1上边的,,红色代表源链表,黄色为元链表中random的指向。你要做的就是,复制一个相同内容的节点插入它后边(途中黑色)
2根据相对位置处理链表中randomPoint的指向(下图中粉色的线条)
<span style="color: rgb(255, 0, 0);"> </span>黑色<span style="color:#ff0000;">->_randomPoint = 红色->_randomPoint->_next;</span>
<span style="color: rgb(255, 0, 0);"> </span>黑色<span style="color:#ff0000;">->_randomPoint = 红色->_randomPoint->_next;</span>
void ComplexListCopy(ComplexList &List, ComplexList &ListCopy)
cursi->_randomPoint = curdi->_randomPoint->_next;
3将红黑两个链表进行分离。
具体实现
数据类型的定义
<span style="color:#330099;">typedef int DataType;
typedef struct ComplexListNode
{
DataType _data;
struct ComplexListNode * _next;
struct ComplexListNode * _randomPoint;
}ComplexListNode;</span>
<span style="color:#330099;">typedef struct ComplexList
{
<span style="white-space:pre"> </span>ComplexListNode head;
}ComplexList;
</span>
基本框架的搭建
void Init(ComplexList &List)
{
List.head._data = 0;
List.head._next = NULL;
List.head._randomPoint = NULL;
}
void Destroy(ComplexList&List)
{
ComplexListNode* cur = &List.head;
while (cur)
{
ComplexListNode *tmp = cur;
cur = cur->_next;
free(tmp);
}
}
ComplexListNode* BuyNode(DataType x)
{
ComplexListNode* ret = (ComplexListNode*)malloc(sizeof(ComplexList));
if (ret == NULL)
return NULL;
ret->_data = x;
ret->_next = NULL;
ret->_randomPoint = NULL;
return ret;
}
ComplexListNode* FindNode(ComplexList &List, DataType x)
{
ComplexListNode* cur = List.head._next;
while (cur)
{
if (cur->_data == x)
return cur;
cur = cur->_next;
}
return NULL;
}
void PushFront(ComplexList &List, DataType x)
{
ComplexListNode* tmp = BuyNode(x);
tmp->_next = List.head._next;
List.head._next = tmp;
}
//siPos源,diPos目标
void MakeComplex(ComplexList &List, DataType siData, DataType diData)
{
<span style="white-space:pre"> </span>ComplexListNode *siPos = FindNode(List, siData);
<span style="white-space:pre"> </span>ComplexListNode *diPos = FindNode(List, diData);
<span style="white-space:pre"> </span>if (siPos == NULL || diPos == NULL)
<span style="white-space:pre"> </span>return;
<span style="white-space:pre"> </span>siPos->_randomPoint = diPos;
}
void ShowComList(ComplexList &List)
{
ComplexListNode* cur = List.head._next;
printf("List :");
while (cur)
{
printf("%2d -->", cur->_data);
cur = cur->_next;
}
printf("\nListComp:");
cur = List.head._next;
while (cur)
{
if (cur->_randomPoint)
printf("%2d -->", cur->_randomPoint->_data);
else
printf(" -->");
cur = cur->_next;
}
printf("\n");
}
核心函数实现
void ComplexListCopy(ComplexList &List, ComplexList &ListCopy)
{
ComplexListNode *curdi = List.head._next;
//BuyNode And Insert in List;
if (curdi == NULL)
return;
<span style="white-space:pre"> </span>//实现插入
while (curdi)
{
ComplexListNode *tmp = BuyNode(curdi->_data);
tmp->_next = curdi->_next;
curdi->_next = tmp;
curdi = tmp->_next;
}
curdi = List.head._next;
ComplexListNode *cursi = curdi->_next;
ListCopy.head._next = cursi;
//实现对_randomPoint 指针指向的处理
while (curdi&&cursi)
{
if(curdi->_randomPoint!=NULL)
cursi->_randomPoint = curdi->_randomPoint->_next;
curdi = cursi->_next;
if(curdi)
cursi = curdi->_next;
}
curdi = &List.head;
cursi = curdi->_next;
<span style="white-space:pre"> </span>//分开两条新旧两条链表
while (cursi)
{
curdi->_next = cursi->_next;
curdi = curdi->_next;
cursi->_next = curdi->_next;
cursi = cursi->_next;
}
}
以下是输出实例
对于这个复杂链表的实现问题呢,其实重点还是思路问题,即使你有一定的语言基础,也不见得能想到这里。
所以没事的时间多多联系,开拓思路还是有好处的。
void ComplexListCopy(ComplexList &List, ComplexList &ListCopy)
cursi->_randomPoint = curdi->_randomPoint->_next;