图的基本概念,存储结构

图的基本概念

图是由顶点集合及顶点间的关系组成的一种数据结构:G = (V, E)

V是一个非空有穷集,称作顶点集,其元素称作顶点或结点.
E = {(x,y)|x,y属于V}或者E = {<x, y>|x,y属于V && Path(x, y)
是顶点间关系的有穷集合,也叫做边的集合。

有向图和无向图:在有向图中,顶点对<x, y>是有序的,顶点对<x,y>称为顶点x到顶点y的一条
边(弧),<x, y>和<y, x>是两条不同的边,比如下图G3和G4为有向图。在无向图中,顶点对(x, y)
是无序的
,顶点对(x,y)称为顶点x和顶点y相关联的一条边,这条边没有特定方向,(x, y)和(y,x)
是同一条边,比如下图G1和G2为无向图。注意:无向边(x, y)等于有向边<x, y>和<y, x>。
在这里插入图片描述

图的存储结构

1.邻接矩阵
在这里插入图片描述

template<class W>
struct Edge
{
	Edge(int srci,int dsti,W w)
		:_srci(srci)
		,_dsti(dsti)
		,_w(w)
	{}
	bool operator>(const Edge& e) const 
	{
		return _w > e._w;
	}

	int _srci;
	int _dsti;
	W _w;
};

template<class V,class W  ,W MAX_W = INT_MAX,bool direction = false>
class Graph
{
public:
	typedef Graph<V, W, MAX_W, direction> self;
	typedef Edge<W> Edge;
	Graph(const V* vertexs, size_t n)
	:_vertexs(n)
	, _matrix(n, vector<W>(n, MAX_W))
	{
		for (int i = 0; i < n; ++i)
		{
			_vertexs[i] = vertexs[i];
		}
		for (int i = 0; i < n; ++i)
		{
			_mapIndex[_vertexs[i]] = i;
		}
	}
	int findIndex(const V& vertex)
	{
		auto it = _mapIndex.find(vertex);
		if (it == _mapIndex.end())
		{
			cout << "没找到" << endl;
			return -1;
		}
		//找到了
		return it->second;
	}	

	bool AddEdge(const V& src,const V& dst,W w)
	{
		int srci = findIndex(src);
		int dsti = findIndex(dst);

		if (srci == dsti)
		{
			return false;
		}


		_matrix[srci][dsti] = w;
		//无向图
		if (direction == false)
		{
			_matrix[dsti][srci] = w;
		}

		return true;
	}
	void print()
	{
		int n = _vertexs.size();

		for (int i = 0; i < n; i++)
		{
			cout << _vertexs[i] << "->" << '[' << i << ']' << endl;
		}
		cout << endl;


		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; ++j)
			{
				if (_matrix[i][j] == MAX_W)
				{
					cout <<"* ";
				}
				else
				{
					cout << _matrix[i][j]<<" ";
				}
			}
			cout << endl;
		}
	}

	
private:
	vector<V> _vertexs; // 所有点的集合
	map<V, int> _mapIndex; // 找点的下标
	vector<vector<W>> _matrix; // 领接矩阵

};
void test()
{
	Graph<char, int, INT_MAX, true> g("0123", 4);
	g.AddEdge('0', '1', 1);
	g.AddEdge('0', '3', 4);
	g.AddEdge('1', '3', 2);
	g.AddEdge('1', '2', 9);
	g.AddEdge('2', '3', 8);
	g.AddEdge('2', '1', 5);
	g.AddEdge('2', '0', 3);
	g.AddEdge('3', '2', 6);
	g.print();
}

在这里插入图片描述
在这里插入图片描述
2.邻接表

无向图邻接表存储
在这里插入图片描述
有向图邻接表存储
在这里插入图片描述

template<class W>
struct Edge
{
	Edge(int srci,int dsti,W w)
		:_srci(srci)
		,_dsti(dsti)
		,_w(w)
		,_next(nullptr)
	{}

	int _srci;//起点
	int _dsti;//终点
	W _w; //权值
	Edge<W>* _next;
};


template<class V, class W, W MAX_W = INT_MAX, bool direction = false>
class Graph
{
public:
	typedef Edge<W> Edge;

	Graph(const vector<V>& vertexs, size_t n)
		:_vertexs(n)
		, _chart(n, nullptr)
	{
		for (int i = 0; i < n; ++i)
		{
			_vertexs[i] = vertexs[i];
		}
		for (int i = 0; i < n; ++i)
		{
			_mapIndex[_vertexs[i]] = i;
		}
	}

	Graph(const V* vertexs, size_t n)
		:_vertexs(n)
		,_chart(n,nullptr)
	{
		for (int i = 0; i < n; ++i)
		{
			_vertexs[i] = vertexs[i];
		}
		for (int i = 0; i < n; ++i)
		{
			_mapIndex[_vertexs[i]] = i;
		}


	}

	bool AddEdge(const V& src, const V& dst, W w)
	{
		int srci = findIndex(src);
		int dsti = findIndex(dst);

		if (srci == dsti)
		{
			return false;
		}
		Edge* edge = new Edge(srci, dsti, w);

		edge->_next = _chart[srci];
		_chart[srci] = edge;
		//无向图
		if (direction == false)
		{
			Edge* edge = new Edge(dsti, srci, w);

			edge->_next = _chart[dsti];
			_chart[dsti] = edge;
		}

		return true;
	}

	int findIndex(const V& vertex)
	{
		auto it = _mapIndex.find(vertex);
		if (it == _mapIndex.end())
		{
			cout << "没找到" << endl;
			return -1;
		}
		//找到了
		return it->second;
	}

	void print()
	{
		int n = _vertexs.size();

		for (int i = 0; i < n; i++)
		{
			cout << _vertexs[i] << "->" << '[' << i << ']' << endl;
		}
		cout << endl;

		for (int i = 0; i < n; i++)
		{
			Edge* cur = _chart[i];
			while (cur != nullptr)
			{
				cout << _vertexs[cur->_srci] << "->" << _vertexs[cur->_dsti] << ":" << cur->_w << "   ";

				cur = cur->_next;
			}
			cout << "end" << endl;
		}
	}

private:
	vector<V> _vertexs; // 所有点的集合
	map<V, int> _mapIndex; // 找点的下标
	vector<Edge*> _chart; // 领接图

	};

void test()
{
	Graph<char, int, INT_MAX, true> g("0123", 4);
	g.AddEdge('0', '1', 1);
	g.AddEdge('0', '3', 4);
	g.AddEdge('1', '3', 2);
	g.AddEdge('1', '2', 9);
	g.AddEdge('2', '3', 8);
	g.AddEdge('2', '1', 5);
	g.AddEdge('2', '0', 3);
	g.AddEdge('3', '2', 6);
	g.print();
}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值