图论基础入门

一、存图

存图方式一共有三种:邻接矩阵、邻接表、前向星

纯前向星还需要再加上排序的时间复杂度(当排序不是主要复杂度时适用),如果快排,时间复杂度是O(n log n),可以用别的排序方式优化,即基数排序(不写纯前向星了,不会写基数排序 )

事实上,不用排序也能模仿出来前向星的核心思路,即链式前向星,链式前向星也是最常用的存图方式

邻接矩阵

cpp 复制代码
int edge[100][100],vis[100],m,n;
void add_edge(int u,int v,int w) //添加边
{
	edge[u][v]=w;
}
void dfs(int x) //遍历
{
	vis[x]=1;
	cout<<x;
	for(int i=1;i<=n;i++)
	{
		if(edge[x][i]&&!vis[i])
		{
			cout<<"->";
			dfs(i);
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		add_edge(u,v,w);
		add_edge(v,u,w);
	}
	dfs(1);
	return 0;
}

/*
test

4 5
1 2 5
1 3 8
1 4 7
2 3 6
3 4 9

*/

邻接表(链式前向星)

cpp 复制代码
int n,m,cnt,head[100],vis[100];
struct edge{
	int nxt,to,w;
}e[100];
void add_edge(int u,int v,int w)
{
	e[++cnt] = (edge){head[u],v,w};
	head[u] = cnt;
}
void dfs(int x)
{
	cout<<x;
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
	{
		if(!vis[e[i].to])
		{
			cout<<"->";
			dfs(e[i].to);
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		add_edge(u,v,w);
		add_edge(v,u,w);
	}
	dfs(1);
	return 0;
}

邻接表(vector存边)

cpp 复制代码
vector<pair<int,int>> e[100];
int n,m,vis[100];
void add_edge(int u,int v,int w) //存边
{
	e[u].push_back(make_pair(v,w));
}
void dfs(int x) //遍历
{
	cout<<x;
	vis[x]=1;
	for(int i=0;i<e[x].size();i++)
	{
		if(!vis[e[x][i].first])
		{
			cout<<"->";
			dfs(e[x][i].first);
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		add_edge(u,v,w);
		add_edge(v,u,w);
	}
	dfs(1);
	return 0;
}

二、遍历

由于邻接表使用广泛,因此以邻接表为例说明图的遍历

1.DFS遍历

DFS(Depth First Search),维护一个栈,每次从栈中取出点/放入点,以栈的出栈顺序遍历图

对于栈的使用,可以利用天然的递归栈 (递归形式) ,也可以手写栈 (递推形式)

DFS递归形式

cpp 复制代码
void dfs(int x)
{
	cout<<x;
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
	{
		if(!vis[e[i].to])
		{
			cout<<"->";
			dfs(e[i].to);
		}
	}
}

DFS非递归形式

cpp 复制代码
void dfs(int x)
{
	stack<int> order; //原先天然的递归栈用手写栈代替
	order.push(x);vis[x]=1;
	while(!order.empty())
	{
		x=order.top();
		order.pop();
		cout<<x<<"->";
		for(int i=head[x];i;i=e[i].nxt)
		{
			if(!vis[e[i].to])
			{
				vis[e[i].to]=1;
				order.push(e[i].to);
			}
		}
	}
}

2. BFS遍历

BFS(Breadth First Search),维护一个队列,每次从队列中取出点/放入点,以队列的出队顺序遍历图

cpp 复制代码
void bfs(int x)
{
	queue<int> order;
	order.push(x);
	vis[x]=1;
	while(!order.empty())
	{
		x=order.front();
		cout<<x<<" ";
		order.pop();
		for(int i=head[x];i;i=e[i].nxt)
		{
			if(!vis[e[i].to])
			{
				vis[e[i].to]=1;
				order.push(e[i].to);
			}
		}
	}
}

对于BFS,因为是 "广度优先" ,可以用于最短路径算法,具体请移步我的下一篇博客

相关推荐
天上路人1 小时前
AI神经网络降噪算法在语音通话产品中的应用优势与前景分析
深度学习·神经网络·算法·硬件架构·音视频·实时音视频
好吃的肘子1 小时前
MongoDB 应用实战
大数据·开发语言·数据库·算法·mongodb·全文检索
汉克老师2 小时前
GESP2025年3月认证C++二级( 第三部分编程题(1)等差矩阵)
c++·算法·矩阵·gesp二级·gesp2级
sz66cm2 小时前
算法基础 -- 小根堆构建的两种方式:上浮法与下沉法
数据结构·算法
緈福的街口2 小时前
【leetcode】94. 二叉树的中序遍历
算法·leetcode
小刘要努力呀!2 小时前
嵌入式开发学习(第二阶段 C语言基础)
c语言·学习·算法
野曙3 小时前
快速选择算法:优化大数据中的 Top-K 问题
大数据·数据结构·c++·算法·第k小·第k大
Codeking__4 小时前
”一维前缀和“算法原理及模板
数据结构·算法
休息一下接着来4 小时前
C++ 条件变量与线程通知机制:std::condition_variable
开发语言·c++·算法
Code哈哈笑4 小时前
【机器学习】支持向量回归(SVR)从入门到实战:原理、实现与优化指南
人工智能·算法·机器学习·回归·svm