这次依然是两道算法题,复制单链表,及复制图。先后对其加以分析,最后会给出一些粗浅总结。
题目一,复制一个单链表(SLL - single linked list), 其节点除了一个基本的后向指针(next), 还有一个指向链表中任意一个节点的随机指针(random)。
struct ranSLLNode{
char* cValue;
ranSLLNode* pNext;
ranSLLNode* pRandom;
ranSLLNode(): pNext(0), pRandom(0){
cValue = new char[CSIZE];
memset(cValue, 0, CSIZE);
}
~ranSLLNode(){
delete cValue;
cValue=0;
pNext=0;
pRandom=0;
}
};
如果是普通单链表,很简单:遍历原始链表,同时逐个创建节点拷贝,总共一次遍历;现在每个节点多了一个随机指针,假设对于原节点pnode, 其复制拷贝节点cpnode, 问题在于如果pnode中的random指向的是之后的节点px, 则由于px的拷贝节点尚未创建,cpnode的random目前无法赋值。
解法一:利用map, 存放每个原节点和其复制节点的关联。这样,当遍历走到某个节点时,如果随机指针指向的节点还未创建,那就直接创建它!反正在map中,每个节点和其拷贝只会存在一份。恩,是个办法。
ranSLLNode* clone_01(ranSLLNode* phead){
map<ranSLLNode*, ranSLLNode*> mnodes;
ranSLLNode *curr = phead;
while(1){
if(mnodes.find(curr) == mnodes.end()){
ranSLLNode *p = new ranSLLNode;
p->cValue = curr->cValue;
mnodes[curr] = p;
}
if(mnodes.find(curr->pRandom) == mnodes.end()){
ranSLLNode *p = new ranSLLNode;
p->cValue = curr->pRandom->cValue;
mnodes[curr->pRandom] = p;
mnodes[curr]->pRandom = p;
}else{
mnodes[curr]->pRandom = mnodes[curr->pRandom];
}
if(curr->pNext != 0){
if(mnodes.find(c