C++数据结构之图

图的实现是一件很麻烦的事情,很多同学可能在学数据结构时只是理解了图的基本操作和遍历原理,但并没有动手实践过。在此,我说说我的实现过程。

首先,在草稿纸上画一个图表,这里是有向图,无向图也一样,如下:

我用的是vector+vector容器作为存储结构,如下:vector+vector)
                                                 |0|——|1|——|3|
                                                 |1|——|2|——|3|
                                                 |2|——|3|
                                                 |3|
                                     

第二步,用自然语言建立这个图,注意数据结构的书一般没有说明图是怎么建立的,在此我简述一下:

       1)、加入4个顶点——G.InsertVextex(V);

       2)、在两个顶点之间增加有向弧——G.AddEdge(x, y)。

这样图就建立了。

我写了两个Graph的构造函数,也可以直接用一个数组实现1)的操作如下:

    vector<VNode> v(4);

    Graph G(v);

第三步,广度优先遍历和深度优先遍历。遍历的目的是为了对每个顶点进行一些处理,能够遍历这个图是其他操作的基础。甚至可以用遍历的方法建立这个图,就像我之前用先序遍历建立二叉树一个道理。

这三步完成,图的实现就基本解决了。至于最小生成树、关键路径等问题,以后再说。

/*************************
Date	: 2013-9-14
Author	: DVD0423
Function: 有向图

存储结构如下:(vector+vector)
	|0|——*——*——*
	|1|——*
	|2|——*——*
	|3|——*——*——*——*——*
	|4|——*——*——*
	|5|
	|6|——*——*
	|7|——*
***************************/
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef int DataType;
const DataType INIT_DATA = -1;
const int NO_NODE   = -1;
const int NO_EDGE   = -2;

class VNode{
public:
	//data member
	bool visited;				//访问标志
	DataType data;				//顶点内的数据
	vector<int> e;				//邻接的边
	//member function
	VNode(DataType val = INIT_DATA, bool flag = false):data(val), visited(flag){}
	void Visit()
	{
		cout<<data<<"	";
	}
	bool operator== (VNode &y){
		if(data == y.data && e == y.e)
			return true;
		else 
			return false;
	}
};
class Graph{
public:
	//data member
	int vexnum;					//图中顶点数
	int edgenum;				//图中边数
	vector<VNode> V;			//图的存储结构
	//member function
	Graph()
	{
		vexnum = 0;
		edgenum = 0;
	}
	Graph(vector<VNode> &v);
	int GetVexNum();
	int GetEdgeNum();
	//节点操作
	void InsertVertex(VNode &x);
	bool DeleteVertex(int x);	
	//边的操作
	//bool IfEdge(int x, int y);		//判断是否有(x, y)的边
	bool AddEdge(int x, int y);
	bool RemoveEdge(int x, int y);
	//邻边操作
	void PrintNeighbors(int x);		//
	VNode &Neighbor(VNode &x, int n);		//x的第n个邻接节点,默认n为第一个
	//广度遍历和深度遍历
	void BreadthFirstSearch();
	void BFS(VNode &x);		//队列实现
	void DepthFirstSearch();
	void DFS(VNode &x);		//递归函数
	~Graph(){};
};
Graph::Graph(vector<VNode> &v)
{	
	V.assign(v.begin(), v.end());
	vexnum = V.size();
	edgenum = GetEdgeNum();
}

int Graph::GetVexNum()
{
	vexnum = V.size();
	return vexnum;
}

int Graph::GetEdgeNum()	
{
	edgenum = 0;
	for(vector<VNode>::iterator iter = V.begin(); iter != V.end(); ++iter)
	{
		edgenum += iter->e.size();
	}
	return edgenum;
}

void Graph::InsertVertex(VNode &x)
{
	V.push_back(x);
	vexnum++;
}
//删除x节点
bool Graph::DeleteVertex(int x)
{
	if(x >= V.size() || x < 0)
	{
		cout<<"没有相应节点"<<endl;
		return false;
	}
	vector<VNode>::iterator iter = V.begin()+x;
	V.erase(iter);
	vexnum--;
	return true;
}

bool Graph::AddEdge(int x, int y)
{
	if((x >= V.size() || x < 0) || (y >= V.size() || y < 0))
	{
		cout<<"没有相应节点"<<endl;
		return false;
	}
	int size = V[x].e.size();
	for(vector<int>::iterator iter = V[x].e.begin(); iter != V[x].e.end(); ++iter)
	{
		if(V[*iter] == V[y])	//已经有(x, y)
		{
			cout<<"已经有弧(x, y)"<<endl;
			return false;
		}		
	}
	V[x].e.push_back(y);		//没有,则把y加入x的邻边队列中	
	edgenum++;
	return true;
}
bool Graph::RemoveEdge(int x, int y)
{
	if((x >= V.size() || x < 0) || (y >= V.size() || y < 0))
	{
		cout<<"没有相应节点"<<endl;
		return false;
	}
	for(vector<int>::iterator iter = V[x].e.begin(); iter != V[x].e.end(); ++iter)
	{
		if(V[*iter] == V[y])
		{
			V[x].e.erase(iter);
			edgenum--;
			return true;
		}
	}	
	cout<<"没有弧(x, y)"<<endl;
	return false;
}

//邻边操作
void Graph::PrintNeighbors(int x)
{
	cout<<"列出节点"<<x<<"的所有邻接节点"<<endl;
	for(vector<int>::iterator iter = V[x].e.begin(); iter != V[x].e.end(); ++iter)
	{
		cout<<*iter<<"	";
	}
	cout<<endl;
}

VNode &Graph::Neighbor(VNode &x, int n = 1)		
{
	
	if(n > x.e.size() || n <= 0)
	{
		cout<<"没有相应边"<<endl;
		exit(0);
	}
	return V[(x.e[n-1])];
}
/******
	遍历
**********/
void Graph::BreadthFirstSearch()
{
	for(int i = 0; i != vexnum; ++i)
	{
		if(!V[i].visited)
			BFS(V[i]);
	}
	for(vector<VNode>::iterator k = V.begin(); k != V.end(); ++k)
		k->visited = false;

}
void Graph::BFS(VNode &x)
{
	queue<VNode> q;
	q.push(x);
	while(!q.empty())
	{
		VNode &_x = q.front();
		if(!_x.visited)
		{
			_x.Visit();
			_x.visited = true;
			int size = _x.e.size();
			
			for(int i = 0; i < size; ++i)
			{	
				VNode &w = V[_x.e[i]];
				if(!w.visited)
				{
					w.Visit();
					w.visited = true;
					q.push(w);
				}
			}		
		}
		q.pop();
	}
}

void Graph::DepthFirstSearch()
{
	for(int i = 0; i != vexnum; ++i)
	{
		if(!V[i].visited)
			DFS(V[i]);
	}
	for(vector<VNode>::iterator k = V.begin(); k != V.end(); ++k)//改变访问标志,以便下次访问
		k->visited = false;
}
void Graph::DFS(VNode &x)
{

	x.Visit();
	x.visited = true;
	int size = x.e.size();
	for(int i = 0; i < size; ++i)
	{
		VNode &w = V[x.e[i]];
		if(!w.visited)
			DFS(w);
	}
}


下面是main函数

int main()
{
	Graph G;
	vector<VNode> v(4);			
	for(int i = 0; i != 4; ++i)	
	{	
		v[i].data = i;			//节点信息
		G.InsertVertex(v[i]);
	}
	//Graph G(v);
	G.AddEdge(0, 1);
	G.AddEdge(0, 3);
	G.AddEdge(1, 2);
	G.AddEdge(2, 3);
	G.AddEdge(1, 3);

	G.BreadthFirstSearch();
	return 0;
}


 

原文地址:https://www.cnblogs.com/suncoolcat/p/3322821.html