图论算法总结

一、判断无向图是否是一颗树

利用树的特性n个顶点n-1条边,对图进行dfs求出所有的顶点数和边数进行判断

注意:无向图有2n条边,最后要将边数除以2*

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define maxn 100

typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v: ");
		scanf("%d%d",&u,&v);
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 printf("结点: \n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--->",p->adjvex);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 


void DFS(Graph  *G,int v,int  &verNum,int &nodeNum,int vis[]){
	  vis[v]=1;
	  ArcNode *p=G->adjlist[v].firstarc;
	  nodeNum++;
	  while(p!=NULL){
	  	 verNum++;
		   if(!vis[p->adjvex]){
		   	  DFS(G,p->adjvex,verNum,nodeNum,vis);
		   } 
		   p=p->next; 
	  } 
} 


bool IsTree(Graph *G){
	int vis[maxn];
	for(int i=0;i<G->n;i++){
		vis[i]=0; 
	} 
	int verNum=0,nodeNum=0;
	DFS(G,0,verNum,nodeNum,vis);
	if(nodeNum==G->n&&nodeNum-1==verNum/2)return true;
	
	return false; 
} 

int main()
{   


     Graph *G=(Graph*)malloc(sizeof(Graph));
	 Create(G);
	 Print(G); 
	 if(IsTree(G))printf("是一颗树");
	 else printf("不是一颗树"); 
     


    return 0;
}



二、判断有向图是否有环

注意是有向图,不然无法用深搜
无向图利用并查集配合拓扑排序

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define maxn 100

typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v: ");
		scanf("%d%d",&u,&v);
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 printf("结点: \n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--->",p->adjvex);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 


int DFS(Graph  *G,int v,int vis[]){
	  vis[v]=1;
	  ArcNode *p=G->adjlist[v].firstarc;
	  int flag=0; 
	  while(p!=NULL){
		   if(vis[p->adjvex]==1)return 1; //有环 
		   else  flag=DFS(G,p->adjvex,vis);
		   if(flag==1)return 1; 
		   p=p->next; 
	  } 
	  return 0;
} 




int main()
{   


     Graph *G=(Graph*)malloc(sizeof(Graph));
	 Create(G);
	 Print(G); 
	 int vis[maxn];
	 for(int i=0;i<G->n;i++)vis[i]=0; 
	 printf("当前有向图是否有环: %d",DFS(G,0,vis)); 


    return 0;
}



三、利用邻接表进行拓扑排序(卡恩算法)

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define maxn 100

typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v: ");
		scanf("%d%d",&u,&v);
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 printf("结点: \n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--->",p->adjvex);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 


void  TopSort(Graph *G){
	 int q[maxn]; //队列 
	 int rear=-1,front=-1;
	 int chu[maxn],ru[maxn];
	 for(int i=0;i<G->n;i++){
	 	chu[i]=0,ru[i]=0; 
	 } 
	 //统计出度和入度 
	  for(int i=0;i<G->n;i++){
	  	  ArcNode *p=G->adjlist[i].firstarc;
		  while(p){
		  	 chu[i]++;
			 ru[p->adjvex]++; 
			 p=p->next; 
		  }  
	  }
	  
	//  for(int i=0;i<G->n;i++)printf("%d的入度为%d\n",i,ru[i]);
	//  for(int i=0;i<G->n;i++)printf("%d的出度为%d\n",i,chu[i]);
	  for(int i=0;i<G->n;i++){
	  	if(ru[i]==0)q[++rear]=i;//找出所有入读为0的顶点 
	  }
	  while(front<rear){
	  	  int u=q[++front];
	  	  printf("%d--->",u); 
		  ArcNode *p=G->adjlist[u].firstarc;
		  while(p){
		  	 chu[u]--;
			 ru[p->adjvex]--;
			 if(ru[p->adjvex]==0)q[++rear]=p->adjvex;//入度为0则入队 
			 p=p->next; 
		  } 
	  } 
} 




int main()
{   


     Graph *G=(Graph*)malloc(sizeof(Graph));
	 Create(G);
	 Print(G); 
	 
	 printf("利用卡恩算法拓扑排序如下:\n");
	 TopSort(G); 


    return 0;
}



四、利用DFS进行拓扑排序

先搜到的后记录

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define maxn 100

typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v: ");
		scanf("%d%d",&u,&v);
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 printf("结点: \n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--->",p->adjvex);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 



void  DFS(Graph *G,int v,int vis[],int ts[],int &time){
	   vis[v]=1;
	   ArcNode* p=G->adjlist[v].firstarc;
	   
	   while(p){
	   	 if(!vis[p->adjvex]){
	   	 	  DFS(G,p->adjvex,vis,ts,time);
			}
			p=p->next; 
	   } 
	   ts[++time]=v; //最先到达,实际上是拓扑序列中最后的节点 
} 

void TopSort(Graph *G){
	int vis[maxn], ts[maxn];
	for(int i=0;i<G->n;i++){
		vis[i]=0,ts[i]=0; 
	} 
	int time=0; 
	for(int i=0;i<G->n;i++){
		if(!vis[i])DFS(G,i,vis,ts,time);
	} 
    for(int i=G->n;i>=1;i--){ // 倒叙遍历即为拓扑序列 
    	 printf("%d-->",ts[i]);
	}
} 


int main()
{   


     Graph *G=(Graph*)malloc(sizeof(Graph));
	 Create(G);
	 Print(G); 
	 
	 printf("利用DFS算法拓扑排序如下:\n");
	 TopSort(G); 


    return 0;
}



五、打印任意u到v的所有路径

利用path数组记录dfs经过的节点信息,如果u==v则打印当前路径,如果求所有路径必须进行回溯

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define maxn 100

typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v: ");
		scanf("%d%d",&u,&v);
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--->",p->adjvex);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 


void  DFS(Graph *G,int u,int v,int vis[],int path[],int d){
	 vis[u]=1;
	 path[++d]=u; 
	 vis[u]=1;
	 if(u==v){
	 	for(int i=1;i<=d;i++){
	 		printf("%d--->",path[i]); 
		 } 
		 printf("\n"); 
	 } 
	 ArcNode *p=G->adjlist[u].firstarc;
	 while(p){
	 	 if(!vis[p->adjvex]){
	 	 	  DFS(G,p->adjvex,v,vis,path,d);
		  } 
		  p=p->next; 
	 } 
	 vis[u]=0;//回溯找出所有路径 
	  
} 


void FindAllPath(Graph* G,int u,int v){
	 int vis[maxn],path[maxn];
	 
	 for(int i=0;i<G->n;i++){
	 	vis[i]=0,path[i]=0;
	 } 
	 DFS(G,u,v,vis,path,0);
	 
} 




int main()
{   


     Graph *G=(Graph*)malloc(sizeof(Graph));
	 Create(G);
	 Print(G); 
	 int u,v;
	 printf("请输入u v: "); 
	 scanf("%d%d",&u,&v);
	 printf("所有路径如下:\n");
	 FindAllPath(G,u,v);
	

    return 0;
}



六、Dijkstr迪杰斯特拉(邻接表实现)

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define INF 0X7f7f7f7f 

#define maxn 100


typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v,info;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v 以及结点权值:");
		scanf("%d%d%d",&u,&v,&info);
		
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		p->info=info; 
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			q->info=info; 
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--权值%d-->",p->adjvex,p->info);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 

int  getVal(Graph *G,int u,int v){
	 ArcNode *p=G->adjlist[u].firstarc;
	 while(p!=NULL){
	 	 if(p->adjvex==v)return p->info;
		  p=p->next; 
	 } 
	 
	 return INF;//没有边相连接 
} 

void  DijKstra(Graph *G,int d[],int path[],int st){
	   int  vis[maxn];
	   //初始化 
	   for(int i=0;i<G->n;i++){
	   	   vis[i]=0;
		   path[i]=-1;
		   d[i]=INF; 
	   } 
	   
	   path[st]=-1;
	   d[st]=0; //从u出发
	   
	   for(int i=0;i<G->n-1;i++){ //找到路径和最小的结点 
	   	  int minVal=INF;
		  int u=G->n; 
		  for(int j=0;j<G->n;j++){
		  	 if(!vis[j]&&d[j]<minVal){
		  	 	   minVal=d[j]; 
				   u=j; 
			   } 
		  }
		  vis[u]=1; 
		  
		  for(int j=0;j<G->n;j++){ //更新其他结点 
		  	   int dis=getVal(G,u,j);
			   if(!vis[j]&&d[u]+dis<d[j]){
			   	  d[j]=d[u]+dis;
				  path[j]=u; 
			   } 
		  } 
	   } 
	   
} 

//输出路径 
void  printPath(int path[],int v){
	 if(path[v]==-1)printf("%d ",v);
	 else{
	 	printPath(path,path[v]);//不断向前寻找
	 	printf("%d ",v);
	 } 
} 



int main()
{   


     Graph *G=(Graph*)malloc(sizeof(Graph));
	 Create(G);
	 Print(G); 
	 
	 int d[maxn],path[maxn];
	 
	 printf("输入u v\n");
	 int u,v;
	 scanf("%d%d",&u,&v); 
	 DijKstra(G,d,path,u);
	 
	 printf("到各个顶点的最短路为:\n");
	 
	 for(int i=0;i<G->n;i++){
	 	 printf("%d  ",d[i]); 
	 } 
	 
	 printf("\n");
	 printf("最短路径序列为:\n");//u到v的最短路径序列
	 printPath(path,v); 
	 

    return 0;
}



七、邻接表逆转

原邻接表顶点信息,为逆邻接表边表信息

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define INF 0X7f7f7f7f 

#define maxn 100


typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v,info;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v 以及结点权值:");
		scanf("%d%d%d",&u,&v,&info);
		
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		p->info=info; 
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			q->info=info; 
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--权值%d-->",p->adjvex,p->info);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 


void  ReverseAdjlist(Graph *G,Graph *R){
	 //初始化 顶点个数、边个数 
	 R->n=G->n;
	 R->e=G->e;
	 //初始化顶点表 
	 for(int i=0;i<G->n;i++){
	 	R->adjlist[i].data=G->adjlist[i].data;
	 	R->adjlist[i].firstarc=NULL;
	 } 
	 
	 //邻接表顶点信息成为逆邻接表边表信息 
	 for(int i=0;i<G->n;i++){
	 	ArcNode *p=G->adjlist[i].firstarc;
		 while(p!=NULL){
		 	ArcNode *s=(ArcNode*)malloc(sizeof(ArcNode));
			 s->adjvex=i;
			 s->next=R->adjlist[p->adjvex].firstarc;
			 R->adjlist[p->adjvex].firstarc=s; //头插法 
			 p=p->next; 
		 } 
	 } 
} 


int main()
{   


     Graph *G=(Graph*)malloc(sizeof(Graph));
	 Create(G);
	 Print(G); 
	 Graph *R=(Graph*)malloc(sizeof(Graph));
	 ReverseAdjlist(G,R);
	 Print(R); 
	 

	 

    return 0;
}



八、在无向无权图最短路距离顶点u最短路径长度为k的所有顶点

利用bfs统计 ,如果d[i]刚好为k则输出,不然加入队列

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define INF 0X7f7f7f7f 

#define maxn 100


typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v,info;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v 以及结点权值:");
		scanf("%d%d%d",&u,&v,&info);
		
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		p->info=info; 
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			q->info=info; 
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--权值%d-->",p->adjvex,p->info);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 



void  dis_k(Graph *G,int k,int u){
	int d[G->n];
	for(int i=0;i<G->n;i++)d[i]=-1;
	
	int queue[maxn];
	int rear=-1,front=-1;
	queue[++rear]=u; 
	d[u]=0;
	while(front<rear){
		int v=queue[++front];
		ArcNode *p=G->adjlist[v].firstarc;
		while(p!=NULL){
			if(d[p->adjvex]==-1){
				d[p->adjvex]=d[v]+1;
				if(d[p->adjvex]==k)printf("%d ",p->adjvex);
				else queue[++rear]=p->adjvex; //如果没有超过k则加入队列 
			}
			p=p->next;
		}
	}
} 



int main()
{   


     Graph *G=(Graph*)malloc(sizeof(Graph));
	 Create(G);
	 Print(G); 
	 printf("请输入u和k: ");
	 int u,k;
	 scanf("%d%d",&u,&k);
	 dis_k(G,k,u); 
	 

	 

    return 0;
}



九、求支撑树,保证从v出发的广搜序列和以v为根的支撑树的层次遍历序列相同

利用bfs,只不过在遍历时存放的不是边表,而是树的结点,这样在bfs同时可以保证队列中出入顺序为层次序列顺序,这样达到了层序序列和bfs序列相同的效果

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define INF 0X7f7f7f7f 

#define maxn 100


typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 


struct TNode{
	int val,childnum;
	struct TNode* child[maxnum];
}TNode; 

void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v,info;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v 以及结点权值:");
		scanf("%d%d%d",&u,&v,&info);
		
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		p->info=info; 
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			q->info=info; 
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--权值%d-->",p->adjvex,p->info);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 


TNode* bfs(Graph *G,int v){
	int vis[G->n];
	for(int i=0;i<G->n;i++)vis[i]=0;
	
	TNode * Qu[G->n];
	int front =-1,rear=-1;
	vis[v]=1;
	TNode *root=(TNode*)malloc(sizeof(TNode));
	root->val=v;
	Qu[++rear]=root; //采用队列存放TNode结点模拟层次遍历 
	while(front<rear){ //进行bfs达到广搜和层次遍历为同一序列的效果 
		TNode *t=Qu[++front];
		t->childnum=0;
		ArcNode *p=G->adjlist[t->val].firstarc;
		while(p!=NULL){
			if(vis[p->adjvex]==0){
				TNode* s=(TNode*)malloc(sizeof(TNode));
				s->val=p->adjvex;
				t->childnum[t->childnum++]=s;
				Qu[++rear]=s;
				vis[p->adjvex]=1;
			}
			p=p->next;
		}
	}
	return root;
}





十、树的直径问题

从任意顶点出发搜索到直径一端a,再从a搜到另一端b
原理是从任意顶点出发所搜最远的距离顶点,一定是直径端点,一定顶点一定距离直径两端中一个近一个远

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>

#define INF 0X7f7f7f7f 

#define maxn 100


typedef struct ArcNode{
	 int adjvex;
	 int info;//权值
	 struct ArcNode *next; 
}ArcNode;

typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode;

typedef struct Graph{
	 VNode adjlist[maxn];
	 int n,e;
}Graph; 



void Create(Graph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v,info;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v 以及结点权值:");
		scanf("%d%d%d",&u,&v,&info);
		
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		p->info=info; 
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			q->info=info; 
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}

void  Print(Graph *G){
	 printf("**********打印邻接表***********\n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value=%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--权值%d-->",p->adjvex,p->info);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 


int  ShortestPath(Graph *G,int v,int d[]){
	  for(int i=0;i<G->n;i++){
	      d[i]=-1;
	  }	   
	  int Qu[G->n];
	  int front=-1,rear=-1;
	   
	  d[v]=1;
	  Qu[++rear]=v;
	  
	  while(front<rear){
	  	int u=Qu[++front];
		 ArcNode *p=G->adjlist[u].firstarc;
		 while(p!=NULL){
		 	if(d[p->adjvex]==-1){
		 		 d[p->adjvex]=d[u]+1;
		 		 Qu[++rear]=p->adjvex; 
			 } 
			 p=p->next; 
		 }
	  }
	  
	  int max=0;
	  
	  for(int i=0;i<G->n;i++){
	  	 if(d[i]>d[max]) max=i; 
	  	}
	  	printf("\n"); 
	return max; 
} 

int Piameter_Tree(Graph *G){
	int d[G->n];
	int first=ShortestPath(G,0,d);
	printf("直径一端为:%d ",first);
	int last=ShortestPath(G,first,d);
	printf("另一端为: %d",last);
	
	return d[last]; 
}


int  main(){
	
	Graph* G=(Graph*)malloc(sizeof(Graph));
	Create(G);
	
	Print(G);
	 Piameter_Tree(G); 
	
	
	
	
	return 0; 
} 




十一、Dijkstra应用偏心距问题

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>
#include<math.h>
#define INF 0X7f7f7f7f 

#define maxn 100

typedef struct ArcNode{
	 int adjvex;
	 int info;
	 struct ArcNode* next; 
}ArcNode;


typedef struct VNode{
	 int data;
	 struct ArcNode *firstarc; 
}VNode; 


typedef struct AGraph{
	VNode adjlist[maxn];
	int n,e; 
}AGraph;


void Create(AGraph *G){
	 printf("有向图 1 无向图 0: ");
	 int flag=0;
	 scanf("%d",&flag);
	 
	 printf("输入顶点个数 边个数: ");
	 scanf("%d%d",&G->n,&G->e);
	 
	 for(int i=0;i<G->n;i++){
	     printf("请输入第%d个顶点元素值: ",i);
		 fflush(stdin);
		 scanf("%d",&G->adjlist[i].data);
		 G->adjlist[i].firstarc=NULL; 
	 } 
	 
	 int u,v,info;
	 
	 for(int i=0;i<G->e;i++){
	 	printf("请输入 u   v 以及结点权值:");
		scanf("%d%d%d",&u,&v,&info);
		
		ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
		p->next=G->adjlist[u].firstarc;
		p->adjvex=v;
		p->info=info; 
		G->adjlist[u].firstarc=p;
		if(flag==0){
			ArcNode *q=(ArcNode*)malloc(sizeof(ArcNode));
			q->next=G->adjlist[v].firstarc;
			q->adjvex=u;
			q->info=info; 
			G->adjlist[v].firstarc=q; 
		} 
	 } 
}


void  Print(AGraph *G){
	 printf("**********打印邻接表***********\n");
	 printf("结点: \n");
	 for(int i=0;i<G->n;i++){
	 	   printf("结点编号%d  结点value%d---",i,G->adjlist[i].data);
           ArcNode *p=G->adjlist[i].firstarc;
		   while(p){
		   	printf("%d--->",p->adjvex);
			p=p->next; 
		   } 
		   printf("\n");
	 } 
} 

void Dijkstra(AGraph *G,int v,int A[maxn][maxn]){
	//最短路迪杰斯特拉 
	int vis[G->n],d[G->n];
	for(int i=0;i<G->n;i++){
		vis[i]=0;
		d[i]=INF; 
	} 
	d[v]=0;
	for(int i=0;i<G->n-1;i++){
		
		 int minDis=INF;
		 int u=v; 
		 for(int i=0;i<G->n;i++){
		 	 if(!vis[i]&&d[i]<minDis){
		 	 	  minDis=d[i];
				  u=i; 
			  } 
		 }
		 
		 vis[u]=1;
		 ArcNode* p=G->adjlist[u].firstarc;
		 while(p){
		 	int k=p->adjvex;
			if(!vis[k]&&d[u]+p->info<d[k]){
				d[k]=d[u]+p->info;
			} 
			p=p->next; 
		 } 	
	}
	//记录在二维数组里
	for(int i=0;i<G->n;i++){
		A[v][i]=d[i];
	}
} 


void  FindCenter(AGraph *G){
	int A[maxn][maxn];
	for(int i=0;i<G->n;i++){
		Dijkstra(G,i,A);//求出各个顶点的最短路 
	}
	int ans=INF,center=0; 
	for(int i=0;i<G->n;i++){
		printf("顶点:%d   ",i);
		
		for(int j=0;j<G->n;j++){
			printf("%d ",A[i][j]);
		} 
		printf("\n");
		//求当前顶点i的偏心距
		int dis=0; 
		for(int j=0;j<G->n;j++){
			if(A[i][j]>dis){
				dis=A[i][j]; 
			} 
		} 
		if(dis<ans){
			ans=dis; 
			center=i; 
		} 
	} 
	printf("图的中心为%d,  其偏心距为%d\n",center,ans); 
}


int  main(){
	
	
	AGraph *G=(AGraph*)malloc(sizeof(AGraph));
	Create(G);
	Print(G); 
	FindCenter(G); 
	
	
	return 0; 
} 




  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值