复杂链表的复制27

题目描述:请实现函数ComplexListNode *Clone(ComplexListNode *pHead); 复制一个复杂链表。在复杂链表中,每个节点除了有一个m_Next指针指向下一个节点外,还有一个s_Sibling指向链表中的任意节点或者NULL。

复杂链表节点定义如下:

//复杂链表的定义
struct ComplexListNode{
  int m_value;  //节点存储的值
  ComplexListNode *m_next;  //节点指针
  ComplexListNode *m_Sibling; //兄弟节点
  void show(); //打印所有节点值
};

解题思路:
A.空间换时间

  1. 复制原始链表上的每个节点N,创建N’,然后把这些创建出来的节点用m_Next链接起来。同时我们把(N, N’)的配对信息放到一个哈希表中。
  2. 设置复制链表上每个结点的m_Sibling。如果在原始链表中节点N的m_Sibling指向节点S, 那么在复制链表中,对应的N’应该指向S’。由于有了哈希表。我们可以用O(1)的时间根据S找到S’。

B.不适用辅助空间

  1. 在原始链表的每个节点N创建对应N’,然后把N’链接在N的后面。
  2. 设置复制出来的节点的m_Sibling。假设原始链表上的N的m_Silbling指向节点S,那么对应复制出来的N’是N的m_Next指向的节点,同样S’也是S的m_Next指向的节点。 即原始链表上的节点N的m_Sibling指向S,则它对应的复制节点N’的m_Sibling指向S的下一节点S’。
  3. 把这个长链表分成两个链表:把奇数位置的节点用m_Next链接起来就是原始链表。把偶数位置的节点用m_Next链接起来就是复制出来的链表。

测试用例:

int main(){
    //m_next: 1->2->3->4->5->NULL;   m_Sibling:  1->3、2->5、4->2
    ComplexListNode *p1 = new ComplexListNode;
    p1 = NULL;  
    addToTail(&p1, 1); 
    addToTail(&p1, 2); //末尾加入2
    addToTail(&p1, 3); //末尾加入3
    addToTail(&p1, 4); //末尾加入4
    addToTail(&p1, 5); //末尾加入5
    addToTail(&p1, 6); //末尾加入6
    // p1->show(); //Output:1,2,3,4,5,6
    // std::cout << std::endl;
    // std::cout << p1->m_value << std::endl;  //Output: 1   
    p1->m_Sibling = p1->m_next->m_next;
    // std::cout << p1->m_Sibling->m_value << std::endl;  //Output: 3
    p1->m_next->m_Sibling = p1->m_next->m_next->m_next->m_next;
    // std::cout << p1->m_next->m_Sibling->m_value <<std::endl;  //Output: 5
    p1->m_next->m_next->m_next->m_next->m_Sibling = p1->m_next;
    // std::cout << p1->m_next->m_next->m_next->m_next->m_Sibling->m_value << std::endl; //Output: 2

    //复制复杂链表
    ComplexListNode *clone = new ComplexListNode;
    clone = Clone(p1);


    //检查结果
    p1->show(); //Output:1,2,3,4,5,6
    std::cout << std::endl;
    std::cout << p1->m_value << std::endl;  //Output: 1    
    std::cout << p1->m_Sibling->m_value << std::endl;  //Output: 3
    std::cout << p1->m_next->m_Sibling->m_value <<std::endl;  //Output: 5
    std::cout << p1->m_next->m_next->m_next->m_next->m_Sibling->m_value << std::endl; //Output: 2

    return 0;
}

函数实现:(B方法,不使用辅助空间)

//实现链表m_next节点的复制,并以此将N'接到N节点的后面
void CloneNodes(ComplexListNode *pHead){
    //副本节点
    ComplexListNode *pNode = pHead;
    while(pNode != NULL){
        //克隆节点
        ComplexListNode *pClone = new ComplexListNode;
        pClone->m_value = pNode->m_value;
        pClone->m_next = pNode->m_next;
        pClone->m_Sibling = NULL;  //第一步先全部初始化为NULL
        //把pClone接到原链表的后面
        pNode->m_next = pClone;
        //更新节点
        pNode = pClone->m_next;
    }
}
//复制m_Sibling节点
void ConnectSiblingNodes(ComplexListNode *pHead){
    //副本 
    ComplexListNode *pNode = pHead;
    while(pNode != NULL){
        //当前克隆的链表节点已经是2合1的链表
        ComplexListNode *pClone = pNode->m_next;
        //如果原链表节点有m_Sibling
        if(pNode->m_Sibling != NULL){
            //在2合1链表中sibling的位置就是
            pClone->m_Sibling = pNode->m_Sibling->m_next;
        }
        //更新pNode,pClone的下一节点就是原m_next节点
        pNode = pClone->m_next;
    }
}
//将2合1的链表拆开,奇数位置是原链表,偶数位置是克隆的链表
ComplexListNode* ReconnectNodes(ComplexListNode *pHead){
    //副本
    ComplexListNode *pNode = pHead;
    //克隆头
    ComplexListNode *cloneHead = new ComplexListNode;
    cloneHead = NULL;
    //存储克隆节点
    ComplexListNode *cloneNode = new ComplexListNode;
    cloneNode = NULL;

    if(pNode != NULL){
        //克隆偶数位置
        cloneHead = cloneNode = pNode->m_next;
        //更新pNode
        pNode->m_next = cloneNode->m_next;
        pNode = pNode->m_next;
    }
    while(pNode != NULL){
        cloneNode->m_next = pNode->m_next;
        cloneNode = cloneNode->m_next;
        pNode->m_next = cloneNode->m_next;
        pNode = pNode->m_next;
    }
    return cloneHead;
}
// 函数实现
ComplexListNode* Clone(ComplexListNode *pHead){
    //第一步,复制原有m_next节点
    CloneNodes(pHead);
    //第二部,复制m_Sibling节点,将两个链表链在一起实现
    ConnectSiblingNodes(pHead);
    //第三步,分解链表。奇数位置为原节点,偶数位置为克隆的节点
    return ReconnectNodes(pHead);
}

其他函数实现:

void ComplexListNode::show(){
    ComplexListNode *temp = this;
    while(temp != NULL){
       std::cout << temp->m_value << " ";
       temp = temp->m_next;
    }
}

//在一个链表的末尾添加一个节点
void addToTail(ComplexListNode **head, int value){//由于会改动链表指针,所以必须把head参数设为指向指针的指针。否则出了这个函数作用域,改动便无效。
    //1.首先创建要插入的节点
    ComplexListNode *pNew = new ComplexListNode;
    pNew->m_value = value; //指定值
    pNew->m_next = NULL; //!!!切记指定下一节点为NULL

    //2.如果传入的节点为空,可直接创键头节点
    if(*head == NULL)
        *head = pNew;
    else{//否则3.
        //定义一个临时节点
        ComplexListNode *temp = *head;
        while(temp->m_next != NULL) //循环指向末尾节点, !!!切记必须指向下一节点
            temp = temp->m_next;
        //对末尾的下一个节点赋值,取代之(末尾)
        temp->m_next = pNew;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值