实现函数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 <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; }
运行程序: