数据结构-图

来源:互联网 发布:个体户域名备案 编辑:程序博客网 时间:2024/05/22 23:57

图的基本算法

图主要是DFS+BFS,其他都可变形得到

#include<stdio.h>#include<stdlib.h>#define MAX 200000000//表示节点间不可达#define NodeNum 50//假设小于50个节点//有向图算法。无向图与有向图类似//图的标配//1.数组(标识是否访问过)//2.存储结构(邻接矩阵/邻接表)//3.访问的数据结构(BFS中队列,非递归DFS中的栈)int path[NodeNum]={0};int NodeMapIndex[NodeNum]={0};//将字母映射为数字int Metrix[NodeNum][NodeNum]={0};int visit[NodeNum]={0};//visit数组(全局,标识是否访问过)int lowCost[NodeNum]={0};//到达每个顶点的最小代价(在Prim与Dijkstra表示的意义不同)int dist[NodeNum][NodeNum]={0};//Floyd存储最点距离//图的邻接表定义typedef struct ArcNode{int adjvex;int value;//权值ArcNode *nextarc;}ArcNode;typedef struct VNode{char data;//图中的顶点数据,当然也可以是整形ArcNode*firstarc;}VNode,Adjlist[NodeNum];typedef struct{Adjlist vertices;int vexnum,arcnum;}AlGraph;//创建图-邻接矩阵int CreateGraph1(){int n,i,j,value;scanf("%d",&n);if(n>0){for(i=0;i<n;i++){for(j=0;j<n;j++){Metrix[i][j]=0;}}while(scanf("%d%d%d",&i,&j,&value)&&i>=0&&i<n&&j>=0&&j<n){Metrix[i][j]=value;//如果是无向图则需要再加一个节点Metrix[j][i]=value;}return n;}else{puts("节点数不能为负!");return -1;}}//创建有向图-邻接表void CreateGraph2(AlGraph &G){int n,i,j,value;scanf("%d",&n);getchar();if(n>0){char ch1,ch2;G.vexnum=n;//创建n个节点for(i=0;i<n;){scanf("%c",&ch1);getchar();if(ch1>='a'&&ch1<='z'){G.vertices[i].data=ch1;G.vertices[i].firstarc=NULL;NodeMapIndex[ch1-'a']=i;//将字母映射为数字i++;}}//创建弧G.arcnum=0;while(1){//输入弧节点scanf("%c %c %d",&ch1,&ch2,&value);getchar();if(!(ch1>='a'&&ch1<='z'&&ch2>='a'&&ch2<='z')){break;}//定位ch1---ch2ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=NodeMapIndex[ch2-'a'];p->value=value;p->nextarc=G.vertices[NodeMapIndex[ch1-'a']].firstarc;G.vertices[NodeMapIndex[ch1-'a']].firstarc=p;G.arcnum++;//如果是无向图则需要再加一个节点}}else{puts("节点数不能为负!");}}//创建无向图-邻接表void CreateGraph3(AlGraph &G){int n,i,j,value;scanf("%d",&n);getchar();if(n>0){char ch1,ch2;G.vexnum=n;//创建n个节点for(i=0;i<n;){scanf("%c",&ch1);getchar();if(ch1>='a'&&ch1<='z'){G.vertices[i].data=ch1;G.vertices[i].firstarc=NULL;NodeMapIndex[ch1-'a']=i;//将字母映射为数字i++;}}//创建弧G.arcnum=0;while(1){//输入弧节点scanf("%c %c %d",&ch1,&ch2,&value);getchar();if(!(ch1>='a'&&ch1<='z'&&ch2>='a'&&ch2<='z')){break;}//定位ch1--->ch2ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=NodeMapIndex[ch2-'a'];p->value=value;p->nextarc=G.vertices[NodeMapIndex[ch1-'a']].firstarc;G.vertices[NodeMapIndex[ch1-'a']].firstarc=p;//如果是无向图则需要再加一个节点//定位ch2--->ch1p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=NodeMapIndex[ch1-'a'];p->value=value;p->nextarc=G.vertices[NodeMapIndex[ch2-'a']].firstarc;G.vertices[NodeMapIndex[ch2-'a']].firstarc=p;G.arcnum++;}}else{puts("节点数不能为负!");}}void CrashAlGraph(AlGraph &G){for(int i=0;i<G.vexnum;i++){visit[i]=0;}ArcNode*p,*q;for(int i=0;i<G.vexnum;i++){p=G.vertices[i].firstarc;G.vertices[i].firstarc=NULL;while(p){q=p;p=p->nextarc;free(q);q=NULL;}}puts("Crashed!");}void VisitNode(int v){printf("%c ",'a'+v);}void DFS(AlGraph G,int v){visit[v]=1;VisitNode(v);ArcNode *p=G.vertices[v].firstarc;for(;p;p=p->nextarc){int w=p->adjvex;if(visit[w]==0){DFS(G,w);}}}//非递归DFS类似于树的先序非递归void DFS2(AlGraph G,int v){ArcNode*Stack[NodeNum],*p;int top=0;visit[v]=1;VisitNode(v);p=G.vertices[v].firstarc;while(top>0||p){while(p){if(visit[p->adjvex]==1){p=p->nextarc;}else{visit[p->adjvex]=1;VisitNode(p->adjvex);Stack[top++]=p;p=G.vertices[p->adjvex].firstarc;}}if(top>0){p=Stack[--top];p=p->nextarc;}}}//广度优先void BFS(AlGraph G,int v){int Queue[NodeNum]={0};int front=0,rear=0;if(visit[v]==0){Queue[rear++]=v;while(front<rear){int u=Queue[front++];visit[u]=1;VisitNode(u);ArcNode *p=G.vertices[u].firstarc;//将所有未访问得临节点入队for(;p;p=p->nextarc){int w=p->adjvex;if(visit[w]==0){Queue[rear++]=w;}}}}}//访问图每个节点void VisitGraph(AlGraph G){for(int i=0;i<G.vexnum;i++){visit[i]=0;}for(int i=0;i<G.vexnum;i++){if(visit[i]==0){DFS2(G,i);//BFS(G,i);}}puts("");for(int i=0;i<G.vexnum;i++){visit[i]=0;}}//判断 a 到 c 是否有路经-邻接表(a是否可到c)int IsPath1(AlGraph G,char a,char c){DFS(G,NodeMapIndex[a-'a']);//BFS(G,NodeMapIndex[a-'a']);return visit[ NodeMapIndex[c-'a']];}//判断 a 到 c 是否有路经-邻接矩阵(可用弗洛伊德算法)//略//找到a到c所有的路径void FindPath(AlGraph G,char a,char c,int len){visit[NodeMapIndex[a-'a']]=1;path[len++]=NodeMapIndex[a-'a'];if(a==c){for(int i=0;i<len;i++){printf("%c ",G.vertices[path[i]].data);}puts("");}else{ArcNode*p=G.vertices[NodeMapIndex[a-'a']].firstarc;for(;p;p=p->nextarc){int w=p->adjvex;if(visit[w]==0){FindPath(G,G.vertices[w].data,c,len);}}}visit[NodeMapIndex[a-'a']]=0;}//无向图的连通分量(DFS/BFS)略//有向图的强连通分量(加点法:a->c且c->a则a,c是同一个连通分量)略//拓扑排序(邻接表存储)//王道//(逆邻接表存储略)int TopSort(AlGraph G){int i=0,j=0,top=0;int Degree[NodeNum]={0};int Stack[NodeNum]={0};int SortArr[NodeNum]={0};ArcNode*p;//计算所有顶点入度for(i=0;i<G.vexnum;i++){p=G.vertices[i].firstarc;for(;p;p=p->nextarc){int w=p->adjvex;Degree[w]++;}}//入度为0入栈for(i=0;i<G.vexnum;i++){if(Degree[i]==0){Stack[top++]=i;}}while(top>0){int v=Stack[--top];SortArr[j++]=v;p=G.vertices[v].firstarc;//临接点入度减一为0入栈for(;p;p=p->nextarc){if(--Degree[p->adjvex]==0){Stack[top++]=p->adjvex;}}}if(j<G.vexnum)return 0;else{for(i=0;i<G.vexnum;i++){VisitNode(SortArr[i]);}puts("");return 1;}}//DFS在确保含有拓扑序列的条件下用于输出TopSort序列//王道//(不能用来判断是否无环)int finish[NodeNum]={0};int time=0;//递归完成时间(子节点总是先于自己递归完成)void TopDFS(AlGraph G,int v){visit[v]=1;ArcNode*p=G.vertices[v].firstarc;for(;p;p=p->nextarc){int w=p->adjvex;if(visit[w]==0){TopDFS(G,w);}}finish[time++]=v;}//以TopDFS输出拓扑序列void TopSort2(AlGraph G){for(int i=0;i<G.vexnum;i++){visit[i]=0;}for(int i=0;i<G.vexnum;i++){if(visit[i]==0){TopDFS(G,i);}}for(int i=time-1;i>=0;i--){VisitNode(finish[i]);}puts("");}//判断图是否有环(对每个点DFS,能找到自己则有环)//或者拓扑排序void LoopDFS(AlGraph G,int u,int& flag){visit[u]=-1;ArcNode*p=G.vertices[u].firstarc;for(;p;p=p->nextarc){if(visit[p->adjvex]==0){LoopDFS(G,p->adjvex,flag);}else if(visit[p->adjvex]==-1)//在返回之前又遇到访问过的节点{flag=1;}}visit[u]=1;}int IsLoop(AlGraph G)//利用LoopDFS判断是否有环{int flag=0,u=0;for(int i=0;i<G.vexnum;i++){visit[i]=0;}for(int i=0;i<G.vexnum;i++){if(visit[i]==0){LoopDFS(G,i,flag);}}return flag;}//最小生成树primint Prim(AlGraph G,int u){int cost=0;for(int i=0;i<G.vexnum;i++){lowCost[i]=MAX;visit[i]=0;}lowCost[u]=0;for(int i=0;i<G.vexnum;i++){int min=MAX;for(int j=0;j<G.vexnum;j++){if(visit[j]==0&&min>lowCost[j]){min=lowCost[j];u=j;}}visit[u]=1;VisitNode(u);cost+=lowCost[u];ArcNode*p=G.vertices[u].firstarc;for(;p;p=p->nextarc){int w=p->adjvex;if(visit[w]==0&&lowCost[w]>p->value){lowCost[w]=p->value;}}}return cost;}//单源最短路Dijkstra(不含负权)//u--->vint Dijkstra(AlGraph G,int u,int v){//int cost=0;for(int i=0;i<G.vexnum;i++){lowCost[i]=MAX;visit[i]=0;}lowCost[u]=0;for(int i=0;i<G.vexnum;i++){int min=MAX;for(int j=0;j<G.vexnum;j++){if(visit[j]==0&&min>lowCost[j]){min=lowCost[j];u=j;}}visit[u]=1;//cost+=lowCost[u];ArcNode*p=G.vertices[u].firstarc;for(;p;p=p->nextarc){int w=p->adjvex;//与prim算法不同之处对lowCost修改if(visit[w]==0&&lowCost[w]>lowCost[u]+p->value){lowCost[w]=lowCost[u]+p->value;}}}return lowCost[v];}//任意顶点间最短路//Floyd(不含负权)void Floyd(AlGraph G){ArcNode *p;//初始化visit与dist矩阵for(int i=0;i<G.vexnum;i++){visit[i]=0;for(int j=0;j<G.vexnum;j++){dist[i][j]=MAX;}p=G.vertices[i].firstarc;for(;p;p=p->nextarc){if(dist[i][p->adjvex]>p->value){dist[i][p->adjvex]=p->value;}}}for(int k=0;k<G.vexnum;k++)//i->j经过k{for(int i=0;i<G.vexnum;i++){for(int j=0;j<G.vexnum;j++){if(i!=j&&i!=k&&j!=k&&dist[i][j]>dist[i][k]+dist[k][j]){dist[i][j]=dist[i][k]+dist[k][j];}}}//输出dist矩阵for(int i=0;i<G.vexnum;i++){for(int j=0;j<G.vexnum;j++){printf("%10d\t",dist[i][j]);}puts("");}puts("");}}int main(){AlGraph G;CreateGraph3(G);VisitGraph(G);//int len=0;//FindPath(G,'a','c',len);//printf("TopSort=%d\n",TopSort(G));//TopSort2(G);//printf("IsLoop=%d\n",IsLoop(G));int u=1;printf("Prim=%d\n",Prim(G,u));printf("Dijkstra=%d\n",Dijkstra(G,u,3));Floyd(G);CrashAlGraph(G);return 0;}


0 0
原创粉丝点击