复杂链表的复制——26-创新互联
实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext的指针指向下一个结点外,还有一个m_pSibling的指针指向链表中任意结点或者NULL。
成都创新互联专注于凉州企业网站建设,自适应网站建设,购物商城网站建设。凉州网站建设公司,为凉州等地区提供建站服务。全流程按需求定制制作,专业设计,全程项目跟踪,成都创新互联专业和态度为您提供的服务如下如所示的一个复杂链表,没有画出_sib指针的结点表示_sib指向NULL:
对于复杂链表的复制,首先可以想到的是先遍历一遍链表复制出各个结点并设置好_next指针,复制好单向的链表之后,对于_sib的随机指针则需要每一次都从头遍历找出距当前结点多远的结点才是应该指向的随机结点,虽然可行,但不难发现这样寻找随机结点的时间复杂度是O(N*N);
首先,有一种方法,仍然是先遍历链表创建出相应的结点并设置好每一个的_next指针,之后用一个哈希桶来保存每一个原链表结点的地址和新创建出结点的地址信息,也就是在每一个原链表结点地址的下面链上新创建出对应的链表结点的地址,这样的话一次就能定位新复制出链表中每一个结点的_sib应该指向哪一个对应的结点了;虽然时间复杂度降为了O(N),但这是一种以空间换时间的方法;
另外的一种方法,是在遍历到原链表的一个结点的时候,就新创建出一个结点插入当前结点的后面,完成之后原链表就变成了两个连续重复的结点的双倍长度的链表,这样的话,原来链表中结点的_sib后面的重复的结点,也就会是新创建链表对应结点的_sib的指向,之后再从头访问链表,将原链表中每个结点对应的_sib指针后面的结点赋值给当前结点后面新创建结点的_sib,这样也就完成了新建链表的_sib指向,之后再将两个链表拆开就可以了;
程序设计如下:
#include#include 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< _val<<"->"; tmp = tmp->_next; } cout<<"NULL"< _val<<" sibling is ->"; if(tmp->_sib != NULL) cout< _sib->_val< _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; }
运行程序:
《完》
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
分享文章:复杂链表的复制——26-创新互联
文章起源:http://scyanting.com/article/dhsdpo.html