天天看點

複雜連結清單複制——時間複雜度為O(N)

        今天我們來分享一下關于複雜連結清單複制,時間複雜度為O(N)的算法。

    複雜連結清單是擁有節點值,後繼節點及随機前序節點的連結清單,複雜連結清單複制的難度在于如何找到那個随機的前序節點,一般的算法在找前序節點的效率是非常低的,需要結合被複制的連結清單去周遊查找,時間複雜度一般為O(N)。

   下面我們來舉例說明這個時間複雜度為O(N)的複雜連結清單複制算法,一般用面向過程書寫比較友善。

      首先,将要被複制的複雜連結清單如下:

複雜連結清單複制——時間複雜度為O(N)

     步驟一:在被複制的連結清單中對應插入擁有相應值的新節點

複雜連結清單複制——時間複雜度為O(N)

    步驟二:通過找到被複制連結清單的前序随機節點,找到新增節點的前序随機節點

複雜連結清單複制——時間複雜度為O(N)

    步驟三:拆掉新增結點和被複制節點間的聯系,依次連接配接接新增加節點,并恢複被複制節點之間的連接配接

複雜連結清單複制——時間複雜度為O(N)

    即可得到複制後的複雜連結清單。

複雜連結清單複制——時間複雜度為O(N)

    雖然不是很喜歡在部落格中粘貼代碼,但還是粘貼一下我的代碼吧!僅供參考!個人覺得面向過程寫的比較好。

面向過程:

Complex.h
//複雜連結清單Y(面向過程)
#pragma once
 
typedef int Type;
//定一結構體
struct Clist
{
Type _data;
Clist* _next;
Clist* _random;
Clist(Type data)
:_data(data)
,_next(NULL)
,_random(NULL)
{
}
};
 
Clist* ComplexCP(Clist*l)
{
if(l ==NULL)return NULL;
//插入連接配接上
Clist* cur = l;
while(cur)
{
Clist* next = cur->_next;
Clist* add = new Clist(cur->_data);
cur->_next = add;
add->_next = next;
 
cur = next;
}
//找到随機連結的結點
cur =l;
while(cur)
{
Clist* next = cur->_next;
Clist* prev = cur->_random;
 
if(prev != NULL)
{
Clist* Pnext = prev->_next;
next->_random = Pnext;
}
else
next->_random = NULL;
 
cur = next->_next;
}
//取出新鍊
cur = l;
Clist* newlist = NULL;
Clist* tail = NULL;
while(cur)
{
Clist* newPoint = cur->_next;
Clist* next = newPoint->_next;
 
cur->_next = next;
if(newlist == NULL)
{
newlist = newPoint;
tail = newPoint;
}
else
{
tail->_next = newPoint;
tail = tail->_next;
}
 
cur = next;
}
return newlist;
}
 
void Printf(Clist*l)
{
Clist* cur = l;
while(cur)
{
cout<<"結點 "<<cur<<" : "<<cur->_data<<" , next-> ";
if(cur->_next != NULL)
cout<<cur->_next->_data<<" , random-> ";
else
    cout<<"NULL , random-> ";
 
if(cur->_random != NULL)
   cout<<cur->_random->_data<<endl;
else
   cout<<" NULL "<<endl;
 
cur = cur->_next;
}
}
 
void TestCLCP()//複雜連結清單的複制面向過程
{
Clist* node1 = new Clist(5);
Clist* node2 = new Clist(4);
Clist* node3 = new Clist(3);
Clist* node4 = new Clist(2);
Clist* node5 = new Clist(1);
 
node1->_next = node2;
node2->_next = node3;
node3->_next = node4;
node4->_next = node5;
node5->_next = NULL;
 
node1->_random = node4;
node2->_random = NULL;
node3->_random = node5;
node4->_random = node2;
node5->_random = node1;
 
cout<<"列印node1: "<<endl;
Printf(node1);
 
Clist* CPlist = ComplexCP(node1);
cout<<endl<<"CPlist= ComplexCP(node1):>"<<endl<<"列印CPlist: "<<endl;
Printf(CPlist);
}
Run.h
#include<iostream>
#include<string>//不加.h
using namespace std;
#include"Complex.h"//複雜連結清單Y(面向過程)
 
int main()
{
cout<<"*******************************"<<endl;
cout<<"複雜連結清單的複制(面向過程):"<<endl<<endl;
TestCLCP();//複雜連結清單的複制面向過程
cout<<"*******************************"<<endl;
system("pause");
return 0;
}
           

面向對象(low)

//複雜連結清單的複制
#pragma once
 
template<class T>
class CListNode
{
public:
	T _data;
	CListNode<T>* _prev;
	CListNode<T>* _next;
	CListNode()
	{}
	CListNode(T data)
		:_data(data)
		,_prev(NULL)
		,_next(NULL)
	{
	}
};
 
template<class T>
class CList
{
public:
	typedef CListNode<T> Node;
	//構造,拷貝構造(*),find,Insert,析構
	CList()
		:_head(NULL)
	{
	}
	CList(CList<T>& l)
		:_head(NULL)
	{
		Node* Lhead = l._head;
		if(Lhead != NULL)
		{
			Node* prev = NULL;
			Node* cur = Lhead;
			while(cur)//鍊上
			{
				Node* next = cur->_next;
				Node* add = new Node(cur->_data);
 
				cur->_next = add;
				add->_next = next;
 
				prev = add;
				cur = next;
			}
			//add加上prev
			cur = Lhead;
			while(cur)
			{
				Node* prev = cur->_prev ;
				Node* next = cur->_next;
 
				if(prev != NULL)
				{
					Node* Pnext = prev->_next;
					next->_prev = Pnext;
				}
				else
					next->_prev = NULL;
 
				cur = next->_next;
			}
			//拆鍊
			cur = Lhead;
			Node* next = cur->_next;
			_head = next;
			while(next->_next)
			{
				Node* Cnext = next->_next;//你有一萬個見他的理由,卻沒有了一個見面的身份
				Node* Nnext = Cnext->_next;
				
				cur->_next = Cnext;
				cur = next->_next;
				next->_next = Nnext;
				next = cur->_next;
			}
			cur->_next = next->_next;
		}
	}
	CList*  operator=(CList<T> l)
	{
		swap(l._head, _head);
		return this;
	}
 
	~CList()
	{
		_Clear(_head);
		_head = NULL;
	}
 
	bool PushBack(T data)
	{
		return _PushBack(_head, data);
	}
	Node* Find(const T& data)
	{
		return _Find(_head, data);
	}
	void Print()
	{
		//cout<<"列印連結清單: ";
		_Print(_head);
		cout<<endl;
	}
protected:
	void _Clear(Node*  cur)
	{
		if(cur == NULL) return;
		Node* pt = cur->_next;
		delete cur;
		_Clear(pt);
	}
	void _Print(Node* cur)
	{
		if(cur == NULL) return;
 
		cout<<"節點 0x"<<cur<<" : "<<cur->_data<<" 前序節點->"<<cur->_prev->_data <<" , 後繼節點: ";
		if(cur->_next == NULL)
			cout<<"無";
		else
			cout<<cur->_next->_data<<endl;
		_Print(cur->_next);
	}
	bool _PushBack(Node* & cur, T& data)
	{
		if(cur == NULL)
		{
			cur=new Node(data);
			return true;
		}
		else
		{
			return _PushBack(cur->_next, data);
		}
 
	}
	Node* _Find(Node*& cur,const T& data)
	{
		if(cur == NULL) return NULL;
 
		if(cur->_data == data) return cur;
		else
		return _Find(cur->_next, data);
	}
protected:
	Node* _head;
};
 
void CLCP()//複雜連結清單的複制
{
	CList<int> LS;
	LS.PushBack(5);
	LS.PushBack(2);
	LS.PushBack(1);
	LS.PushBack(4);
	LS.PushBack(3);
	
	for(int i=1; i<6; i++)
	{
		CListNode<int>* cur = LS.Find(i);
		CListNode<int>* prev = LS.Find((2+i)%5);
		if(prev == NULL)
			prev = LS.Find(1);
		cur->_prev = prev;
 
	}
 
	cout<<"LS連結清單列印: "<<endl;
	LS.Print();
	cout<<endl;
 
	CList<int> LSCP(LS);
	cout<<"LSCP連結清單列印: "<<endl;
	LSCP.Print();
 
	CList<int> LSCP2;
	LSCP2 = LS;
	cout<<"LSCP2連結清單列印: "<<endl;
	LSCP2.Print();
}
Run.c
#include<iostream>
#include<string>
using namespace std;
#include"BST.h"
#include"VK.h"
#include"ComplexCP.h"
 
int main()
{
	cout<<"*******************************"<<endl;
	cout<<"複雜連結清單的複制:"<<endl<<endl;
	CLCP();//複雜連結清單的複制
	cout<<"*******************************"<<endl;
	system("pause");
	return 0;
}
           

運作界面

複雜連結清單複制——時間複雜度為O(N)

今天的分享到此為止,望共同進步!

繼續閱讀