面试题26复杂连标的复制

来源:互联网 发布:mac的usb不支持 编辑:程序博客网 时间:2024/06/08 01:54
题目:有一个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL。其结点的C++定义如下:

                struct ComplexNode

{

    int m_nValue;

    ComplexNode* m_pNext;

    ComplexNode* m_pSibling;

};

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

 

                  程序员面试题精选100题(49)-复杂链表的复制 - 何海涛 - 微软、Google等面试题

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

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

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



难点在于:如何复制虚线部分的指针.
其实有个很巧妙的方法, 给A,B,C,D,E编号, 分别为0,1,2,3,4.如果所示. 这样m_pSibling的clone就很简单.
For example:
     节点 b 对应的是原节点B, B->m_pSibling 是E, E的编号是4. 这样新列表的第4个节点的地址赋给b->m_pSibling就可以了.
但关键一点是原列表每个节点的编号保存在哪呢? 如果编号没有地方保存, 也不能降低clone的复杂度. 我们注意到没每个节电有一个m_nValue成员, 我们可以利用它来做文章. 即首先把每个节电的m_nValue备份出来, 临时用来保存编号, 等clone完成后, 再restore.
同时还要把a,b,c.d,e的地址也按顺序保存在一个数组里,以方便获取他们的地址.
 
#include<iostream>using namespace std;struct complexnode{int _val;complexnode* _next;complexnode* _sibling;};void clonenodes(complexnode* Head){complexnode* Node=Head;while(Node!=NULL){complexnode* clone=new complexnode();clone->_val=Node->_val;clone->_next=Node->_next;clone->_sibling=NULL;Node->_next=clone;Node=clone->_next;}}void connectsiblingnodes(complexnode* Head){complexnode* node=Head;while(node!=NULL){complexnode* clone=node->_next;if(node->_sibling!=NULL)clone->_sibling=node->_sibling->_next;node=clone->_next;}}complexnode* reconnectnode(complexnode* Head){complexnode* node=Head;complexnode* cloneHead=NULL;complexnode* clonenode=NULL;if(node!=NULL){cloneHead=clonenode=node->_next;node->_next=clonenode->_next;node=node->_next;}while(node!=NULL){clonenode->_next=node->_next;clonenode=clonenode->_next;node->_next=clonenode->_next;node=node->_next;}return cloneHead;}complexnode* clone(complexnode* Head){clonenodes(Head);connectsiblingnodes(Head);return reconnectnode(Head);}


原创粉丝点击