经典面试题之复杂链表复制的简单实现
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;