无向图

是由一组顶点和一组能够将两个顶点相连的边组成的。无向图的边仅仅是两个顶点之间的连接,没有方向。


当且仅当一幅含有V个节点的图G满足下列5个条件之一时,它就是一棵树:

l  G有V-1条边且不含环

l  G有V-1条边且是连通的

l  G是连通的,但删除任意一条边都会使它不再连通

l  G是无环图,但添加任意一条边都会产生一条环

l  G中任意一对顶点之间仅存在一条简单路径


图的几种表示方法

l  邻接矩阵。使用V*V的布尔矩阵,当顶点v和顶点w之间有连接的边时,定义v行w列的元素值为true,都则为false。

l  邻接表。可以使用一个以顶点为索引的列表数组,其中每个元素都是和该顶点相邻的顶点列表。

以下是邻接表的数据结构图示。



使用邻接表数据结构的Graph源代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Graph
{
public:
	Graph(size_t n) : arr(n), edges(0), vertaxs(n) {}
	void addEdge(size_t a, size_t b);
	void removeEdge(size_t a, size_t b);
	void addVertax(size_t n);
	void removeVertax(size_t n);

	vector<size_t> adj(size_t n) const;
	void showAdj(size_t n) const;
	void showGraph() const;

	size_t edge() const { return edges; }
	size_t vertax() const { return vertaxs; }

private:
	vector<vector<size_t>> arr;
	size_t edges;
	size_t vertaxs;
};

int main(void)
{
	Graph graph(5);

	graph.addEdge(0, 1);
	graph.addEdge(3, 4);
	graph.addEdge(1, 3);
	graph.addEdge(0, 4);
	graph.addEdge(2, 3);
	graph.addEdge(0, 2);

	cout << graph.vertax() << endl;
	cout << graph.edge() << endl;
	graph.showGraph();

	graph.removeEdge(0, 4);
	cout << endl;
	cout << graph.vertax() << endl;
	cout << graph.edge() << endl;
	graph.showGraph();

	graph.addVertax(5);
	cout << endl;
	cout << graph.vertax() << endl;
	cout << graph.edge() << endl;
	graph.showGraph();

	graph.removeVertax(3);
	cout << endl;
	cout << graph.vertax() << endl;
	cout << graph.edge() << endl;
	graph.showGraph();

	system("pause");
	return 0;
}

void Graph::addEdge(size_t a, size_t b)
{
	if (!(a < arr.size() && b < arr.size()))
		return;

	arr[a].push_back(b);
	arr[b].push_back(a);
	edges++; // 无向图
}

void Graph::removeEdge(size_t a, size_t b)
{
	if (!(a < arr.size() && b < arr.size()))
		return;

	vector<size_t>::iterator iter;
	iter = find(arr[a].begin(), arr[a].end(), b);
	if (iter != arr[a].end())
	{
		arr[a].erase(iter);
		//edges--;
	}

	iter = find(arr[b].begin(), arr[b].end(), a);
	if (iter != arr[b].end())
	{
		arr[b].erase(iter);
		edges--;
	}
}
void Graph::addVertax(size_t n)
{
	if (n != arr.size())
		return;

	arr.push_back(vector<size_t>());
	vertaxs++;
}

void Graph::removeVertax(size_t n)
{
	if (n >= arr.size())
		return;

	while (!arr[n].empty())
		removeEdge(n, arr[n][0]); // 调用removeEdge函数,不用考虑分两次删除边了
	//arr.erase(arr.begin() + n);
	vertaxs--;
}

vector<size_t> Graph::adj(size_t n) const
{
	if (n < arr.size())
		return arr[n];
	else
		return vector<size_t>();

}

void Graph::showAdj(size_t n) const
{
	if (n >= arr.size())
		return;

	vector<size_t> vec;
	vec = adj(n);
	for (size_t i = 0; i < vec.size(); i++)
		cout << vec[i] << " ";
	cout << endl;
}

void Graph::showGraph() const
{
	for (size_t i = 0; i < arr.size(); i++)
	{
		cout << i << ": ";
		showAdj(i);
	}
}


参考:

1、https://github.com/luoxn28/algorithm_data_structure (里面有常用的数据结构源代码)

2、算法(第4版) 无向图章节

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值