图的基本操作代码

本文深入探讨了图算法,包括广度优先搜索(BFS)、深度优先搜索(DFS)、拓扑排序、Dijkstra算法用于单源最短路径求解以及Prim算法构建最小生成树。通过邻接表和邻接矩阵两种数据结构,详细阐述了这些算法的实现和应用。
摘要由CSDN通过智能技术生成

BFS

#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
#define INF 0x777777
//邻接表存储结构
typedef struct ArcNode{  //边表结点
	int vex;
	struct ArcNode *next;
}ArcNode;
typedef struct VNode{   //顶点表结点
	int data;
	ArcNode *first;
}VNode,AdjList;
typedef struct{
	AdjList vertices[maxsize]; //邻接表
	int vexnum,arcnum;
}ALGraph;  //以邻接表存储的图
void visit(int v)
{
}
//广度优先搜索,需要借助队列实现
void BFS(ALGraph G,int v)  //从顶点V出发广度优先遍历图
{
	int visited[maxsize];
	for(int i=0;i<G.vexnum;i++)
		visited[i]=0;
	int queue[maxsize];
	int front,rear;
	int w,u;
	front=rear=0;
	visit(v);
	visited[v]=1;
	queue[rear]=v; //v入队
	rear=(rear+1)%maxsize;
	while(front!=rear)//队列不为空
	{
		u=queue[front]; //出队
		front=(front+1)%maxsize;
		w=GetFirstVex(G,u);//取出队结点u的第一个邻接顶点
		while(w>=0) //邻居顶点w存在时
		{
			if(visited[w]==0)
			{
				visit(w);
				visited[w]=1;
				queue[rear]=w;//入队
				rear=(rear+1)%maxsize;
			
			}
			w=GetNextVex(G,u,w);//取下一个邻接顶点
		}

	}
}

DFS

int visited[maxsize];
void DFS(Graph G,int v) //邻接表
{
	visit(v);
	visited[v]=1;
	int w;
	for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) //w为v尚未访问的邻接顶点
		if(visited[w]==0)
		{
			DFS(G,w);
		}
}
void DFS(graph g,int v)  //邻接矩阵
{
	visit(v);
	visited[v] = 1;
	for (int j = 0; j < g.n; j++)
	{
		if (g.edges[v][j] == 1 && visited[j] == 0)
		{
			DFS(g,j);
		}
	}	
}


拓扑排序

bool TopologicalSort(Graph G){  //邻接表
  InitStack(S);
  for(int i=0;i<G.vexnum;i++)
	  if(indegree[i]==0)   //将所有入度为0的顶点入栈
		  Push(S,i);
  int count=0;  //记录已经输出的顶点数
  while(!IsEmpty(S)){
	  Pop(S,i);
	  printf("%d ",i);//输出顶点i
	  count++;
	  for(p=G.vertices[i].firstarc;p;p=p->nextarc)
	  {    //将所有i指向的顶点入度减1,并将入度减为0的顶点入栈
		  v=p->adjvex;
		  if((--indegree[v])==0)
		  {
			  Push(S,v);
		  }
	  }
  }
  if(count<G.vexnum)  //排序失败,有向图中有回路
	  return false;
  else 
	  return true;
}
bool Topo(graph g)  //邻接矩阵
{
	int stack[maxsize];
	int top=-1;
	int indegree[maxsize];
	countIndegree(g,indegree);
	for(int i=0;i<g.n;i++)
		if(indegree[i]==0)
			stack[++top]=i;//度为0入栈
	int count=0;
	while(top>=0)
	{
		int i=stack[top--];//出栈
		count++;
		for(int j=0;j<g.n;j++)
			if(g.edges[i][j]==1)
			{
				indegree[j]--;
				if(indegree[j]==0)
					stack[++top]=j;//度为0入栈
			}
	}
	if(count<g.n)//还有元素没排序,说明有回路
		return false;
	else
		return true;
}
void countIndegree(graph g,int indegree[])  //计算各个顶点的入度
{
	memset(indegree,0,sizeof(indegree));
	for(int i=0;i<g.n;i++)
		for(int j=0;j<g.n;j++)
			if(g.edges[j][i]==1)
				indegree[i]++;
}

Dijkstra

//Dijkstra算法--单源最短路径
//dist[v]数组表示从初始点到点v的最短路径长度
//path数组表示在最短路径上的前一个顶点
//visited[]为标记数组,0表示没有并入最短路径,1表示已经并入最短路径

void Dijkstra(Graph g,int v,int dist[],int path[])
{
	int visited[maxsize];
	int min,i,j,k;
	for(i=0;i<g.n;i++) //初始化
	{
		dist[i]=g.edges[v][i];
		visited[i]=0;
		if(g.edges[v][i]<INF)
			path[i]=v;
		else
			path[i]=-1;
	}
	visited[v]=1;
	path[v]=-1;
	for(i=0;i<g.n-1;i++)
	{
		min=INF;
		for(j=0;j<g.n;j++)//选择到v的路径最小的顶点
			if(visited[j]==0&&dist[j]<min)
			{
				k=j;
				min=dist[j];
			}
		visited[k]=1;//以k为中间点,对其他点进行检查
		for(j=0;j<g.n;j++)
		{
			if(visited[j]==0&&dist[k]+g.edges[k][j]<dist[j])
			{
				dist[j]=dist[k]+g.edges[k][j];
				path[j]=k;
			}
		}
		 
	}
}//dist数组存放了v点到其余顶点的最短路径长度,path[]中存放了v点到其余各顶点的最短路径

BFS求无权图的单源最短路径

typedef struct graph
{
	int edges[maxsize][maxsize];
	int n,e;
}graph;
void BFS_MIN_Distance(graph g,int v,int dist[])
{
	int visit[maxsize]={0};
	for(int i=0;i<g.n;i++)
		dist[i]=-1;
	visit[v]=1;
	dist[v]=0;
	int queue[maxsize];
	int front=0,rear=0;
	queue[rear++]=v;
	while(front!=rear)
	{
		int p=queue[front++];
		for(int i=0;i<g.n;i++)
			if(visit[i]==0&&g.edges[p][i]==1)
			{
				visit[i]=1;
				dist[i]=dist[p]+1;
				queue[rear++]=i;
			}
	}
}

Floyd

void Floyd(Graph *g,int path[][maxsize],int a[][maxsize])  //每对顶点的最短路径
{
	int i,j,k;
	for(i=0;i<g->n;i++)//初始化
		for(j=0;j<g->n;j++)
		{
			a[i][j]=g->edges[i][j];
			path[i][j]=-1;
		}
	for(k=0;k<g->n;k++)
		for(i=0;i<g->n;i++)
			for(j=0;j<g->n;j++)
				if(a[i][j]>a[i][k]+a[k][j])
				{
					a[i][j]=a[i][k]+a[k][j];
					path[i][j]=k;
				}
}

Prim

//Prim算法,大体与dijkstra算法差不多,区别在于更新其他顶点的权值时候比较的对象不同
/void Prim(graph g,int v,int &sum)//sum是最小生成树权值
{
	int visit[maxsize]={0};
	int dist[maxsize];  //各个顶点到当前最小生成树的权值
	for(int i=0;i<g.n;i++)
		dist[i]=g.edges[v][i];
	visit[v]=1;
	int sum=0;
	for(int i=0;i<g.n-1;i++)
	{
		int min=maxsize;
		int k;
		for(int j=0;j<g.n;j++)
		{
			if(visit[j]==0&&dist[j]<min)
			{
				min=dist[j];
				k=j;
			}
		}
		visit[k]=1;
		sum+=min;
		for(int j=0;j<g.n;j++)
			if(visit[j]==0&&g.edges[k][j]<dist[j])
				dist[j]=g.edges[k][j];
	}
}
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值