复杂链表的复制——26

    实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext的指针指向下一个结点外,还有一个m_pSibling的指针指向链表中任意结点或者NULL。

如下如所示的一个复杂链表,没有画出_sib指针的结点表示_sib指向NULL:

wKiom1dL6PPCK0slAAAJ7cowRHk137.png    对于复杂链表的复制,首先可以想到的是先遍历一遍链表复制出各个结点并设置好_next指针,复制好单向的链表之后,对于_sib的随机指针则需要每一次都从头遍历找出距当前结点多远的结点才是应该指向的随机结点,虽然可行,但不难发现这样寻找随机结点的时间复杂度是O(N*N);

    首先,有一种方法,仍然是先遍历链表创建出相应的结点并设置好每一个的_next指针,之后用一个哈希桶来保存每一个原链表结点的地址和新创建出结点的地址信息,也就是在每一个原链表结点地址的下面链上新创建出对应的链表结点的地址,这样的话一次就能定位新复制出链表中每一个结点的_sib应该指向哪一个对应的结点了;虽然时间复杂度降为了O(N),但这是一种以空间换时间的方法;

    另外的一种方法,是在遍历到原链表的一个结点的时候,就新创建出一个结点插入当前结点的后面,完成之后原链表就变成了两个连续重复的结点的双倍长度的链表,这样的话,原来链表中结点的_sib后面的重复的结点,也就会是新创建链表对应结点的_sib的指向,之后再从头访问链表,将原链表中每个结点对应的_sib指针后面的结点赋值给当前结点后面新创建结点的_sib,这样也就完成了新建链表的_sib指向,之后再将两个链表拆开就可以了;


程序设计如下:

#include <iostream>#include <assert.h>using namespace std;int list_num = 0;struct ComplexListNode//复杂链表结点数据结构{    int _val;    ComplexListNode* _next;    ComplexListNode* _sib;    ComplexListNode(int val)//构造函数        :_val(val)         ,_next(NULL)         ,_sib(NULL)    {}  };ComplexListNode* Buy_Node(int val)//构建复杂链表结点{    ComplexListNode* node = new ComplexListNode(val);    return node;}//插入结点void Push_Node(ComplexListNode** phead, int val){    if((*phead) == NULL)        (*phead) = Buy_Node(val);    else    {           ComplexListNode* tmp = (*phead);        while(tmp->_next != NULL)            tmp = tmp->_next;        tmp->_next = Buy_Node(val);    }    ++list_num;}//设置自由结点的指向void SetSibPointer(ComplexListNode* head, int* positions){    assert(head && positions);    ComplexListNode* tmp = head;    ComplexListNode *p[list_num];    for(size_t i = 0; i < list_num; ++i)    {        p[i] = tmp;        tmp = tmp->_next;    }    tmp = head;    for(size_t i = 0; i < list_num; ++i)    {        if(positions[i] != 0)            tmp->_sib = p[positions[i]];        tmp = tmp->_next;    }}//销毁链表void DestoryList(ComplexListNode* head){    if(head != NULL)    {        ComplexListNode* tmp = head;        while(head != NULL)        {            head = head->_next;            delete tmp;            tmp = NULL;            tmp = head;        }    }}//打印链表void PrintList(ComplexListNode* head){    if(head != NULL)    {        ComplexListNode *tmp = head;        while(tmp != NULL)        {            cout<<tmp->_val<<"->";            tmp = tmp->_next;        }        cout<<"NULL"<<endl;        tmp = head;        while(tmp != NULL)        {            cout<<tmp->_val<<" sibling is ->";            if(tmp->_sib != NULL)                cout<<tmp->_sib->_val<<endl;            else                cout<<"NULL"<<endl;            tmp = tmp->_next;        }    }}//复制复杂链表ComplexListNode* Clone(ComplexListNode* head){    if(head != NULL)    {        ComplexListNode *tmp = head;        ComplexListNode *newnode = NULL;        //复制每个结点并插入当前结点的后面        while(tmp != NULL)        {            newnode = Buy_Node(tmp->_val);            newnode->_next = tmp->_next;            tmp->_next = newnode;            tmp = newnode->_next;        }        //设置新创建链表结点的sib指针的指向        tmp = head;        newnode = tmp->_next;        while(tmp != NULL)        {            if(tmp->_sib != NULL)                newnode->_sib = tmp->_sib->_next;            tmp = newnode->_next;            if(tmp != NULL)                newnode = tmp->_next;        }        //拆分两个链表        tmp = head;        ComplexListNode* NewHead = tmp->_next;        newnode = tmp->_next;        while(tmp != NULL)        {            tmp->_next = newnode->_next;            tmp = tmp->_next;            if(tmp != NULL)            {                newnode->_next = tmp->_next;                newnode = newnode->_next;            }        }        return NewHead;    }}int main(){    ComplexListNode* head = NULL;    Push_Node(&head, 7);    Push_Node(&head, 5);    Push_Node(&head, 8);    Push_Node(&head, 2);    Push_Node(&head, 6);    Push_Node(&head, 9);    Push_Node(&head, 3);    int positions[7] = {2,5,0,4,0,0,4};    SetSibPointer(head, positions);    cout<<"Complex List: ";    PrintList(head);     ComplexListNode* NewComplexListHead = Clone(head);    cout<<"New Complex List: ";    PrintList(NewComplexListHead);    cout<<"Complex List: ";    PrintList(head);    DestoryList(head);    DestoryList(NewComplexListHead);    return 0;}


运行程序:

wKiom1dL6cCxD161AAAZUCd7cOU228.png



《完》

本文出自 “敲完代码好睡觉zzz” 博客,请务必保留此出处http://2627lounuo.blog.51cto.com/10696599/1784471

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值