【C++】简单图

存储方法

以下图为例,分别用邻接矩阵、邻接表和链式前向星建图。

A
B
C
D

邻接矩阵

  • ( i , j ) (i,j) (i,j)表示 i → j i\to j ij是否连通
ABCD
A0110
B0001
C0001
D1000

邻接表

假设边目录结点从 A ∼ D A\sim D AD分别为 0 ∼ 3 0\sim 3 03

1
2
3
3
0
A
B
C
D

链式前向星

  • 链式前向星是静态链表,结构类似于邻接表,故略。

邻接矩阵

存储结构

typedef struct{
	int map[N][N];//邻接矩阵
	char V[N];//顶点表 
	int n,e;//顶点数,边数 
}Graph;

建图

void build(Graph &g){
	cin>>g.n>>g.e;
	for(int i=0;i<g.n;i++){
		cin>>g.V[i];//输入顶点 
	}
	for(int i=0;i<g.e;i++){
		int x,y;
		cin>>x>>y;
		g.map[x][y]=1;//输入边 
	}
}

深度搜索

int visit[N];//访问数组 
void DFS(Graph g,int k){
	cout<<g.V[k]<<' ';
	visit[k]=1;
	for(int i=0;i<g.n;i++){
		if(!visit[i]&&g.map[k][i]){
			DFS(g,i);
		}
	}
	for(int i=0;i<g.n;i++){
		if(!visit[i]){
			DFS(g,i);
		}
	}
}

广度搜索

int visit[N];//访问数组
void BFS(Graph g,int k){
	queue<int> q;
	q.push(k);//入队起始节点 
	visit[k]=1;
	while(!q.empty()){//在队列里循环搜索分支直到队空 
		cout<<g.V[q.front()]<<' ';
		for(int i=0;i<g.n;i++){
			if(!visit[i]&&g.map[q.front()][i]){ 
				q.push(i);
				visit[i]=1;
			}
		}
		q.pop();
	}
	for(int i=0;i<g.n;i++){//查找孤立结点 
		if(!visit[i]){
			BFS(g,i);
		}
	}
} 

示例

#include <iostream>
#include <queue>
using namespace std;
#define N 100

int visit[N];//访问数组

typedef struct{
	int map[N][N];//邻接矩阵
	char V[N];//顶点表 
	int n,e;//边数,顶点数 
}Graph;

void build(Graph &g){
	cin>>g.n>>g.e;
	for(int i=0;i<g.n;i++){
		cin>>g.V[i];//输入顶点 
	}
	for(int i=0;i<g.e;i++){
		int x,y;
		cin>>x>>y;
		g.map[x][y]=1;//输入边 
	}
}

void DFS(Graph g,int k){
	cout<<g.V[k]<<' ';
	visit[k]=1;
	for(int i=0;i<g.n;i++){
		if(!visit[i]&&g.map[k][i]){
			DFS(g,i);
		}
	}
	for(int i=0;i<g.n;i++){
		if(!visit[i]){
			DFS(g,i);
		}
	}
}

void BFS(Graph g,int k){
	queue<int> q;
	q.push(k);//入队起始节点 
	visit[k]=1;
	while(!q.empty()){//在队列里循环搜索分支直到队空 
		cout<<g.V[q.front()]<<' ';
		for(int i=0;i<g.n;i++){
			if(!visit[i]&&g.map[q.front()][i]){ 
				q.push(i);
				visit[i]=1;
			}
		}
		q.pop();
	}
	for(int i=0;i<g.n;i++){//查找孤立结点 
		if(!visit[i]){
			BFS(g,i);
		}
	}
} 

int main(){
	Graph g;
	build(g);
	DFS(g,0);
	//BFS(g,0); 
	return 0;
}
/*
4 5
a b c d
0 1
0 2
1 3
2 3
3 0
*/

邻接表

存储结构

typedef struct ArcNode{
	int idx;
	ArcNode *next=NULL;
}ArcNode;//边结点

typedef struct{
	char data;
	ArcNode *firstNode=NULL;
}VNode;//顶点结点

typedef struct{
	VNode adjaV[N];//顶点的邻接表数组 
	int n,e;//点数,边数 
}Graph;

建图

void build(Graph &g){
	cin>>g.n>>g.e;
	for(int i=0;i<g.n;i++){
		cin>>g.adjaV[i].data;//输入顶点 
	}
	for(int i=0;i<g.e;i++){
		int x,y;
		cin>>x>>y;//输入边
		ArcNode *p=new ArcNode();
		p->idx=y;
		p->next=g.adjaV[x].firstNode;
		g.adjaV[x].firstNode=p;
	}
}

深度搜索

int visit[N];//访问数组
void DFS(Graph g,int k){
	cout<<g.adjaV[k].data<<' ';
	visit[k]=1;
	for(ArcNode *p=g.adjaV[k].firstNode;p!=NULL;p=p->next){//递归查找 
		if(!visit[k]){
			DFS(g,p->idx);
		}
	}
	for(int i=0;i<g.n;i++){//查找孤立顶点 
		if(!visit[i]){
			DFS(g,i);
		}
	}
}

广度搜索

int visit[N];//访问数组
void BFS(Graph g,int k){
	queue<int> q;
	q.push(k);//入队起始节点
	visit[k]=1;
	while(!q.empty()){//在队列里循环搜索分支直到队空 
		cout<<g.adjaV[q.front()].data<<' ';
		for(ArcNode *p=g.adjaV[q.front()].firstNode;p!=NULL;p=p->next){
			if(!visit[p->idx]){ 
				q.push(p->idx);
				visit[p->idx]=1;
			}
		}
		q.pop();
	}
	for(int i=0;i<g.n;i++){//查找孤立顶点
		if(!visit[i]){
			BFS(g,i);
		}
	}
} 

示例

#include <iostream>
#include <queue>
using namespace std;
#define N 100

int visit[N];//访问数组

typedef struct ArcNode{
	int idx;
	ArcNode *next=NULL;
}ArcNode;//边结点

typedef struct{
	char data;
	ArcNode *firstNode=NULL;
}VNode;//顶点结点

typedef struct{
	VNode adjaV[N];//顶点的邻接表数组 
	int n,e;//点数,边数 
}Graph;

void build(Graph &g){
	cin>>g.n>>g.e;
	for(int i=0;i<g.n;i++){
		cin>>g.adjaV[i].data;//输入顶点 
	}
	for(int i=0;i<g.e;i++){
		int x,y;
		cin>>x>>y;//输入边
		ArcNode *p=new ArcNode();
		p->idx=y;
		p->next=g.adjaV[x].firstNode;
		g.adjaV[x].firstNode=p;
	}
}

void DFS(Graph g,int k){
	cout<<g.adjaV[k].data<<' ';
	visit[k]=1;
	for(ArcNode *p=g.adjaV[k].firstNode;p!=NULL;p=p->next){//递归查找 
		if(!visit[k]){
			DFS(g,p->idx);
		}
	}
	for(int i=0;i<g.n;i++){//查找孤立顶点 
		if(!visit[i]){
			DFS(g,i);
		}
	}
}

void BFS(Graph g,int k){
	queue<int> q;
	q.push(k);//入队起始节点
	visit[k]=1;
	while(!q.empty()){//在队列里循环搜索分支直到队空 
		cout<<g.adjaV[q.front()].data<<' ';
		for(ArcNode *p=g.adjaV[q.front()].firstNode;p!=NULL;p=p->next){
			if(!visit[p->idx]){ 
				q.push(p->idx);
				visit[p->idx]=1;
			}
		}
		q.pop();
	}
	for(int i=0;i<g.n;i++){//查找孤立顶点
		if(!visit[i]){
			BFS(g,i);
		}
	}
} 

int main(){
	Graph g;
	build(g);
	DFS(g,0);
//	BFS(g,0); 
	return 0;
}
/*
4 5
a b c d
0 1
0 2
1 3
2 3
3 0
*/

链式前向星

  • 链式前向星就是静态链表实现的邻接表。

存储结构

int visit[N];//访问数组
char data[N];//顶点数据
int head[N];//邻接顶点的第一个顶点
int to[2*N],nex[2*N];//链接的顶点编号,链接的下一个to编号
int n,e;//顶点数,边数 

建图

void build(){
	memset(head,-1,sizeof(head));
	memset(to,-1,sizeof(to));
	memset(nex,-1,sizeof(nex));
	cin>>n>>e;
	for(int i=0;i<n;i++){
		cin>>data[i];//输入顶点 
	}
	for(int i=0;i<e;i++){
		int x,y;
		cin>>x>>y;
		to[i]=y;
		nex[i]=head[x];
		head[x]=i;
	}
}

深度搜索

int visit[N];//访问数组
void DFS(int k){
	cout<<data[k]<<' ';
	visit[k]=1;
	for(int i=head[k];i!=-1;i=nex[i]){//递归查找
		if(!visit[to[i]]){
			DFS(to[i]);
		}
	}
	for(int i=head[k];i!=-1;i=nex[i]){//查找孤立顶点
		if(!visit[to[i]]){
			DFS(to[i]);
		}
	}
}

广度搜索

int visit[N];//访问数组
void BFS(int k){
	queue<int> q;
	q.push(k);//入队起始节点 
	visit[k]=1;
	while(!q.empty()){//在队列里循环搜索分支直到队空 
		cout<<data[q.front()]<<' ';
		for(int i=head[q.front()];i!=-1;i=nex[i]){
			if(!visit[to[i]]){ 
				q.push(to[i]);
				visit[to[i]]=1;
			}
		}
		q.pop();
	}
	for(int i=head[k];i!=-1;i=nex[i]){//查找孤立结点 
		if(!visit[to[i]]){
			BFS(to[i]);
		}
	}
} 

示例

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define N 100

int visit[N];//访问数组
char data[N];//顶点数据
int head[N];//邻接顶点的第一个顶点
int to[2*N],nex[2*N];//链接的顶点编号,链接的下一个to编号
int n,e;//顶点数,边数 

void build(){
	memset(head,-1,sizeof(head));
	memset(to,-1,sizeof(to));
	memset(nex,-1,sizeof(nex));
	cin>>n>>e;
	for(int i=0;i<n;i++){
		cin>>data[i];//输入顶点 
	}
	for(int i=0;i<e;i++){
		int x,y;
		cin>>x>>y;
		to[i]=y;
		nex[i]=head[x];
		head[x]=i;
	}
}

void DFS(int k){
	cout<<data[k]<<' ';
	visit[k]=1;
	for(int i=head[k];i!=-1;i=nex[i]){//递归查找
		if(!visit[to[i]]){
			DFS(to[i]);
		}
	}
	for(int i=head[k];i!=-1;i=nex[i]){//查找孤立顶点
		if(!visit[to[i]]){
			DFS(to[i]);
		}
	}
}

void BFS(int k){
	queue<int> q;
	q.push(k);//入队起始节点 
	visit[k]=1;
	while(!q.empty()){//在队列里循环搜索分支直到队空 
		cout<<data[q.front()]<<' ';
		for(int i=head[q.front()];i!=-1;i=nex[i]){
			if(!visit[to[i]]){ 
				q.push(to[i]);
				visit[to[i]]=1;
			}
		}
		q.pop();
	}
	for(int i=head[k];i!=-1;i=nex[i]){//查找孤立结点 
		if(!visit[to[i]]){
			BFS(to[i]);
		}
	}
} 

int main(){
	build();
	DFS(0);
//	BFS(0); 
	return 0;
}
/*
4 5
a b c d
0 1
0 2
1 3
2 3
3 0
*/

版权声明

  • 本文档归cout0所有,仅供学习使用,未经允许,不得转载。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cout0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值