您的位置:首页 > 职场人生

经典面试题之复杂链表复制的简单实现

2015-11-24 18:12 666 查看

经典面试之复杂链表的简单实现

对于复杂链表复制问题,如果只是单纯的实现这个功能,他其实是不难的。你可以在时间空间没有要求的情况下勉强的实现它。(主要问题就在于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>

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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: