重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext的指针指向下一个结点外,还有一个m_pSibling的指针指向链表中任意结点或者NULL。
成都创新互联公司"三网合一"的企业建站思路。企业可建设拥有电脑版、微信版、手机版的企业网站。实现跨屏营销,产品发布一步更新,电脑网络+移动网络一网打尽,满足企业的营销需求!成都创新互联公司具备承接各种类型的做网站、成都网站制作项目的能力。经过10年的努力的开拓,为不同行业的企事业单位提供了优质的服务,并获得了客户的一致好评。
如下如所示的一个复杂链表,没有画出_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; }
运行程序:
《完》