zoukankan      html  css  js  c++  java
  • 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;
    }


     

  • 相关阅读:
    laravel 的passport Oauth 认证登录请求 的 oauth_token 重置
    多个php版本的composer使用
    MySQL查询语句练习题(面试时可能会遇到哦!)
    tp5 url 线上访问 在nginx 上 出现404错误,解决办法(1.80nginx 配置 pathInfo)
    源码编译安装lnmp环境(nginx-1.14.2 + mysql-5.6.43 + php-5.6.30 )------踩了无数坑,重装了十几次服务器才会的,不容易啊!
    Mysql错误处理: /usr/bin/mysqld_safe: line xxx: xxxx Killed ... (mysql自动停止 Plugin FEDERATED is disabled 的完美解决方法)
    Plugin 'FEDERATED' is disabled. /usr/sbin/mysqld: Table 'mysql.plugin' doesn't exist
    thinkphp5的mkdir() Permission denied问题
    微信小程序 Unexpected end of JSON input/Unexpected token o in JSON at position 1
    服务器 apache配置https,http强制跳转https(搭建http与https共存)
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3322821.html
Copyright © 2011-2022 走看看