图的基本运算(邻接矩阵)

1.将图存入邻接矩阵中

typedef struct{
	char v[100];//顶点值,例如A,B,C,D...
	int a[100][100];//边的权值
	int node,edge;//顶点数和边数
}M;
M G;
void create(M &G)
{
	for(int i=0;i<G.node;i++)
	{
		cin>>G.v[i];
	}
	for(int i=0;i<G.node;i++)
	{
		for(int j=0;j<G.node;j++) 
		G.a[i][j]=0;
	}
	for(int k=0;k<G.edge;k++)
	{
		int i,j,w;
		cin>>i>>j>>w;
		G.a[i][j]=w;
		G.a[j][i]=G.a[i][j];
	} 
}

2.输出邻接矩阵

void print(M &G)
{
	for(int i=0;i<G.node;i++)
	{
		for(int j=0;j<G.node;j++)
		{
			if(i!=j&&G.a[i][j]==0)
			{
				cout<<"#";
			}else{
				cout<<G.a[i][j];
			}
			if(j<(G.node-1))
			{
				cout<<" ";
			} 
		}
		cout<<endl;	 
	} 
} 

3.求所有顶点的度(无向图)

无向图的度就是每行之和或每列之和

int du(M &G)
{
	for(int i=0;i<G.node;i++)
	{
		int ans=0; 
		for(int j=0;j<G.node;j++){
			 ans+=G.a[i][j]; 
		}
		if(i==G.node-1) 
		cout<<ans<<endl;
		else
		cout<<ans<<" ";	 
	} 
} 

4.求出度为0的顶点个数(有向图)

有向图每行之和是每个顶点各自的出度,每列之和分别是每个顶点的入度
所以就设立一个ans数组,把每行的a[i][j]相加,存到ans[i]里面,然后遍历ans,ans【i】为0就t++,最后输出t

ps.计算求出度/入度为1,2,3…都是这个算法

5.求某一顶点的出度和邻接点

注:x是所求顶点的下标,ans存放的是邻接点们的下标

void find(M &G,int x)
{
	int an=0,ans[100],i=0; 
	for(int j=0;j<G.node;j++)
	{
		if(G.a[x][j]==1)
		{
			an++; 
			ans[i]=j;
			i++; 
		} 
	}
		 
	cout<<an<<endl;
	if(an==0)
	cout<<endl;
	else{
		for(int j=0;j<i-1;j++)
		{
			cout<<G.v[ans[j]]<<",";	
		} 
		cout<<G.v[ans[i-1]]<<endl;
	}  
} 

6.求度最大的顶点编号

和3类似

void duda(M &G)
{
	int maxx=0,ans[100];
	memset(ans,0,sizeof(ans));
	for(int i=0;i<G.node;i++)
	{
		for(int j=0;j<G.node;j++)
		{
			if(G.a[i][j]==1)
			{
				ans[i]++;
			}
		}
		maxx=max(maxx,ans[i]); 
	}
	int aa[100],j=0;
	for(int i=0;i<G.node;i++)
	{
		if(ans[i]==maxx)
		{
			aa[j]=i;
			j++;
		}	 
	}
	for(int i=0;i<j-1;i++)
	{
		cout<<aa[i]<<" ";
	} 
	cout<<aa[j-1]<<endl; 
} 

7.在邻接矩阵中删除指定顶点

#include<bits/stdc++.h>
using namespace std;
typedef struct{
	char v[100];
	int a[100][100];
	int node,edge;
}M;
int n,m;
void create(M &G)
{
	for(int i=0;i<G.node;i++)
	{
		cin>>G.v[i];
	}
	for(int i=0;i<G.node;i++)
	{
		for(int j=0;j<G.node;j++) 
		G.a[i][j]=0;
	}
	for(int k=0;k<G.edge;k++)
	{
		int i,j;
		cin>>i>>j;
		G.a[i][j]=1;
		G.a[j][i]=G.a[i][j];
	} 
}
void print(M &G,int bj)
{
	cout<<G.node<<" "<<G.edge<<endl;
	for(int i=0;i<n;i++)
	{
		if(i!=bj)
		cout<<G.v[i];
		if(bj==n-1) 
		{
			if(i!=bj&&i<n-2)
			cout<<" ";
		}else{
			if(i!=bj&&i<n-1)
			cout<<" ";
		}
	}
	cout<<endl;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(bj!=i&&bj!=j)
			{
				cout<<G.a[i][j];
				if(bj==n-1)
				{
					if(j<n-2)
					cout<<" ";
				}else{
					if(j<n-1)
					cout<<" ";
				}	
			}	
		}
		if(i!=bj)
		cout<<endl;	 
	} 
} 
int deletenode(M &G, char x)
{
	int bj=-1;
	for(int i=0;i<G.node;i++)
	{
		if(G.v[i]==x)
		{
			bj=i;
			G.node--;
			break;
		}
	}
	int cnt=0;
	for(int i=0;i<n;i++)
	{
		if(G.a[bj][i]==1)
		{
			cnt++;
			G.a[bj][i]=G.a[i][bj]=0;
		}
	}
//	cout<<cnt<<endl;
	G.edge-=cnt; 
	return bj;
}
int main()
{
	M G ;
	char x;
	while(cin>>n>>m)
	{
		G.node=n;
		G.edge=m;
		create(G);
		cin>>x;
		int ans=deletenode(G,x);
		if(ans==-1)
		printf("not exist\n");
		else{
			print(G,ans);
		}
		
	}
	return 0;
} 
	 
	 

emmmmm感觉我这个不算删除,就是在输出的时候注意一下不要输出和要删除的顶点有关的边,而且写的略有繁琐,如果有大神有更简便的写法,不吝赐教!

8.深度优先遍历

typedef struct{
	char v[100];
	int a[100][100];
	int node,edge;
	bool vis[100];
}M;//这里比之前多了一个标记数组,用来标记顶点是否被搜索过了

所以在初始化的时候记得把vis也一起初始化

for(int i=0;i<G.node;i++)
	{
		for(int j=0;j<G.node;j++) 
		G.a[i][j]=0;
	}

核心算法

void dfs(M &G,int x)
{
	cout<<G.v[x];
	G.vis[x]=true;
	for(int i=0;i<n;i++)
	{
		if(G.a[x][i]!=0&&!G.vis[i])
		dfs(G,i);
	}
	
}

一般来说是从下标为0的点开始搜索,即dfs(G,0)

9.广度优先遍历

其余部分和深搜差不多
核心算法如下

void bfs(M &G,int x)
{
	cout<<G.v[x];
	G.vis[x]=true;
	queue<int>q;
	q.push(x);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<G.node;i++)
		{
			if(!G.vis[i]&&G.a[u][i]==1)
			{
				cout<<G.v[i];

				G.vis[i]=true;
				q.push(i);
			}
		}
	}
}
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值