复杂链表的复制

精选软件工程师面试题-复杂链表的复制

(2011-02-28 21:06:55)
转载


个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL。其结点的C++定义如下:

               structComplexNode

{

   int m_nValue;

   ComplexNode* m_pNext;

   ComplexNode* m_pSibling;

};

               下图是一个含有5个结点的该类型复杂链表。图中实线箭头表示m_pNext指针,虚线箭头表示m_pSibling指针。为简单起见,指向NULL的指针没有画出。

 

                 

请完成函数ComplexNode*Clone(ComplexNode* pHead),以复制一个复杂链表。

分析: 此题目已经有很多人在blog上做过分析, 我没有一个比较精练的, 在次我描述出我的想法. 仅供参考.
这个题目的难点在于如何对 m_pSibling指针复制,使新的列表具有和原列表同样的结构.
如原列表是ABCDE,Clone列表是abcde. 



难点在于:如何复制虚线部分的指针.
其实有个很巧妙的方法, 给A,B,C,D,E编号,分别为0,1,2,3,4.如果所示. 这样m_pSibling的clone就很简单.
Forexample:
    节点 b 对应的是原节点B, B->m_pSibling 是E, E的编号是4.这样新列表的第4个节点的地址赋给b->m_pSibling就可以了.
但关键一点是原列表每个节点的编号保存在哪呢?如果编号没有地方保存, 也不能降低clone的复杂度. 我们注意到没每个节电有一个m_nValue成员, 我们可以利用它来做文章.即首先把每个节电的m_nValue备份出来, 临时用来保存编号, 等clone完成后, 再restore.
同时还要把a,b,c.d,e的地址也按顺序保存在一个数组里,以方便获取他们的地址.
 
这样这个算法就很简单了,只对原列表遍历两次就可以完成复制, 时间复杂度为O(2n):
  1. 备份原列表每个节点的 m_nValue 到数组backupValue. 同时分别设置他们为所在节点的序号值.
  2. 由原列表 clone出新列表(只设置每个接点的m_pNext值). 新列表每个节点的m_pSibling 置为 NULL.同时新列标的每个节点地址按顺序保留到数组newListAddrees中.
  3. Clone m_pSibling:从原列表取一个节点, 如果此节点的m_pSibling为NULL, 取下一个.假设此节点为M. 由M->m_nValue 找到 m(newListAddrees[M->m_nValue]). 并设置m_pSibling:newListAddrees[M->m_nValue]->m_pSibling=newListAddrees[M->m_pSibling->m_nValue].直到原列表的节点的m_pSibling全复制完.
  4. 由backupValue恢复原列表的m_nValue.
  5. 设置新列表的m_nValue.
代码: 
   ComplexNode* CloneList(ComplexNode* pHead)
    {
       ComplexNode*  pNode = pHead;
       ComplexNode** ppBackupNewList;
       int          nTotal = 0;
       int          i = 0;
       while(pNode)
       {
           nTotal++;
           pNode = pNode->m_pNext;
       }
       ppBackupNewList = (ComplexNode **)malloc(sizeof(ComplexNode *)*nTotal);
   
       pNode = pHead;
       while(pNode != NULL)
       {
           ppBackupNewList[i] = (ComplexNode *)malloc(sizeof(ComplexNode));
           if (i > 0)
               ppBackupNewList[i - 1]->m_pNext =ppBackupNewList[i];
           ppBackupNewList[i]->m_pSibling = NULL;
           ppBackupNewList[i]->m_nValue =pNode->m_nValue;
           pNode->m_nValue = i++;
           pNode = pNode->m_pNext;
       }
       ppBackupNewList[nTotal - 1]->m_pNext = NULL;
   
       pNode = pHead;
       while(pNode != NULL)
       {
           if (pNode->m_pSibling)
               ppBackupNewList[pNode->m_nValue]->m_pSibling=
                                ppBackupNewList[pNode->m_pSibling->m_nValue];
           pNode = pNode->m_pNext;
       }
   
       i = 0;
       pNode = pHead;
       while(pNode != NULL)
       {
           pNode->m_nValue =ppBackupNewList[i++]->m_nValue;
           pNode = pNode->m_pNext;
       }
   
       pNode = ppBackupNewList[0];
       free(ppBackupNewList);
   
       return pNode;
   }

你可能感兴趣的:(c,算法,面试,Blog,null)