C++ 複雜鏈表的複製

複雜鏈表節點結構:

650) this.width=650;" src="http://s2.51cto.com/wyfs02/M01/7F/3F/wKioL1cXgd3BU56fAAAavyxy3_w404.png" title="P{PQCTDN$LZM5U}}8]$[__8.png" alt="wKioL1cXgd3BU56fAAAavyxy3_w404.png" />

struct ComplexNode
{
    ComplexNode(const int& d)
        :_data(d)
        ,_next(NULL)
        ,random(NULL)
    {}
    int _data;            //數據域
    ComplexNode* _next;               //指向下一節點
    ComplexNode* _random;             //指向隨機節點
};

複製複雜鏈表可以分爲三步來完成:

第一步:將新複製的節點插入到原來鏈表當中(插入到原節點後面)

圖示:

650) this.width=650;" src="http://s5.51cto.com/wyfs02/M02/7F/3F/wKioL1cXhHuhqAqqAAA-e3TKVJo180.png" title="BB_CRYS~](DVY[Z{@60JSGY.png" alt="wKioL1cXhHuhqAqqAAA-e3TKVJo180.png" />

代碼實現:

void CloneNodes(ComplexNode* pHead)		
{
	ComplexNode* cur = pHead;
	while(cur)
	{
		ComplexNode* NewHead = new ComplexNode();	//開闢新節點
		NewHead->_data = cur->_data;
		NewHead->_next = cur->_next;
		NewHead->_random = NULL;

		cur->_next = NewHead;		//連接新節點

		cur = NewHead->_next;		//跳轉到下一個要複製的節點
	}
}

第二步:修改新開闢的節點的_random,新的_random其實就是舊的_random的_next(新開闢的節點鏈在原來節點的後面,所以就是舊的_random->_next)

代碼實現:

void UpdateNewNodeRandom(ComplexNode* pHead)
{
	ComplexNode* cur = pHead;
	while(cur)
	{
		ComplexNode* next = cur->_next;			//指向新節點

		if(cur->_random != NULL)	//優化:隨機指針不爲空時,複製
		{
			next->_random = cur->_random->_next;	//複製隨機指針
		}

		cur = next->_next;			//下一個要複製的節點
	}
}

第三步:將複製出來的鏈表拆分出來

代碼實現:

ComplexNode* DisconnectNewNode(ComplexNode* pHead)
{
	ComplexNode* cur = pHead;		//指向原來的節點
	ComplexNode* next = NULL;		//指向複製出來的節點
	ComplexNode* pNewHead = NULL;	//新鏈表的頭節點

	if(cur != NULL)
	{
		pNewHead = next = cur->_next;	//指向新鏈表的頭
		cur->_next = next->_next;		//將新節點分離
		cur = next->_next;				
	}

	while(cur)
	{
		next->_next = cur->_next;		//往複製出的鏈表上面連接新節點

		next = next->_next;				//分離新節點
		cur->_next = next->_next;

		cur = next->_next;				
	}

	return pNewHead;					//返回新鏈表的頭結點

}

最後複製複雜鏈表就轉化下面代碼:

ComplexNode<T>* CopyComplexLinkList(ComplexNode<T>* pHead)
{
	if(pHead != NULL)					//判空
	{
		CloneNodes<T>(pHead);			//複製節點並連接在其後面	
		UpdateNewNodeRandom(pHead);		//更新新節點的隨機指針
		return DisconnectNewNode<T>(pHead);/    /拆分鏈表並返回新鏈表的頭結點
	}
	return NULL;
}

創建複雜鏈表:

ComplexNode* CreatList()
{
	ComplexNode* Node1 = new ComplexNode(1);    //創建節點
	ComplexNode* Node2 = new ComplexNode(2);
	ComplexNode* Node3 = new ComplexNode(3);
	ComplexNode* Node4 = new ComplexNode(4);
	ComplexNode* Node5 = new ComplexNode(5);
	
	Node1->_next = Node2;       //連接節點
	Node2->_next = Node3;
	Node3->_next = Node4;
	Node4->_next = Node5;

	Node1->_random = Node3;    //置_random
	Node2->_random = Node4;
	Node3->_random = Node1;
	Node4->_random = Node5;
	Node5->_random = Node2;

	return Node1;            //返回頭
}

打印鏈表:

void Print(ComplexNode* _head)
{
	ComplexNode* cur = _head;
	while(cur)
	{
		cout<<"("<<cur->_data<<","<<cur->_random->_data<<")"<<"->";
		cur = cur->_next;
	}
	cout<<"Nvl."<<endl;
}

測試代碼:

void Test()
{
	ComplexNode* head = CreatList();
	Print(head);
	cout<<"---------------------------------------"<<endl;
	ComplexNode* NewHead = CopyList(head);
	Print(NewHead);
}

測試結果:

650) this.width=650;" src="http://s4.51cto.com/wyfs02/M00/7F/57/wKioL1cazUfx91BwAAAPPOEHytw195.png" title="Y5XQCKUTWQ`YJ[LY2}93H%E.png " alt="wKioL1cazUfx91BwAAAPPOEHytw195.png" />

總結:複雜鏈表的複製分爲三步:第一步就是把新複製出來的節點插入源鏈表中,第二步修改新插入節點的隨機指針,第三步就是將新節點從源中拆分出來,並合併成一個新鏈表。

本文出自 “Pzd流川楓” 博客,請務必保留此出處http://xujiafan.blog.51cto.com/10778767/1766972

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章