一、判断无向图是否是一颗树
利用树的特性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;
}