实现有向带权图抽象数据类型

该程序实现了有向带权图的抽象数据类型,包括图的构造、顶点和边的操作,以及深度优先遍历、广度优先遍历。此外,还提供了单源最短路径和判断负环的功能。用户可以动态输入节点和边,进行图的各种操作和路径查找。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

图是一种使用广泛的数据结构。本次实验要求设计有向带权图的抽象数据类型,实现图的构造、顶点的增删查,边的增删改、深度优先遍历与广度优先遍历、单源最短路径、多源最短路径、判断图中是否存在负环。
在这里插入图片描述

效果

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXX 10000
#define INF 0x3fffffff
int g_1[MAXX][MAXX],g_2[MAXX][MAXX];
char point[MAXX];
int n;//n个节点,编号最大的
char v[MAXX];
int dist[MAXX];
void add_g_1(int b,int c,int d){
    point[b]=1;
    point[c]=1;
    g_1[b][c]=d;
    if(b > n) n=b;
    if(c > n) n=c;
}
void g1tog2(){
    for(int i=0;i<=n;i++){
        for(int j=0;j<=n;j++){
            if(g_1[i][j]<INF){
                g_2[i][j]=g_1[i][j];
                g_2[j][i]=g_1[i][j];
            }
        }
    }

}
void dfs(int x){
    v[x]=1;
    printf("%d ",x);
    for(int i=0;i<=n;i++){
        if(v[i]==0 && g_2[x][i]!=INF){
            dfs(i);
        }
    }
}
void bfs(int x){
    int q[MAXX];
    int p=0,o=0;
    q[o++]=x;
    v[x]=1;
    while(p<o){
        x=q[p++];
        printf("%d ",x);
        for(int i=0;i<=n;i++){
            if(v[i]==0 && g_2[x][i]!=INF){
                q[o++]=i;
                v[i]=1;
            }
        }
    }
}
void Dijkstra(int x){
    dist[x]=0;
    while(1)
	{
		int min=INF;
		int y=-1;
		for(int i=0;i<=n;i++)
		{
			if(dist[i]<min && v[i]==0)
			{
				min=dist[i];
				y=i;
			}
		}
		if(y==-1)	return;
		v[y]=1;
		for(int j=0;j<=n;j++){
            if(v[j]==0 && dist[y]+g_1[y][j]<dist[j]){
                 dist[j]=dist[y]+g_1[y][j];
            }
		}
	}
}
int bf(int x){
    for(int i=0;i<=n;i++){
        dist[i]=INF;
    }
    memset(v,0,sizeof(v));
    dist[x]=0;
    int flag;
    for (int i = 0; i <= n; i++) {
        flag=0;
        for (int j = 0; j <= n; j++) {
            for (int k = 0; k <= n; k++) {
                if (dist[k] > dist[j] + g_1[j][k]) {
                    dist[k] = dist[j] + g_1[j][k];
                    flag = 1;
                }
            }
        }
        if (!flag) return 1;
    }
    flag = 0;
    for (int j = 0; j <= n; j++) {
        for (int k = 0; k <= n; k++) {
            if (dist[k] > dist[j] + g_1[j][k]) {
                flag = 1;
            }
        }
    }
    return !flag;
}
int main()
{
    memset(point,0,sizeof(point));
    for(int i=0;i<MAXX;i++){
        for(int j=0;j<MAXX;j++){
            g_1[i][j]=INF;
            g_2[i][j]=INF;
        }
    }
    int now=0;//当前操作指令
    while(1){
        printf("请输入需求\r\n");
        printf(" 0 输入节点\r\n");
        printf(" 1 节点\r\n");
        printf(" 2 边\r\n");
        printf(" 3 无向图dfs\r\n");
        printf(" 4 无向图bfs\r\n");
        printf(" 5 单源最短路\r\n");
        printf(" 6 任意两点最短路\r\n");
        printf(" 7 判断负环\r\n");
        scanf("%d",&now);
        if(now==0){
            int a,b,c,d;
            scanf("%d %d",&n,&a);
            n-=1;
            for(int i=0;i<a;i++){
                scanf("%d %d %d",&b,&c,&d);
                add_g_1(b,c,d);
            }
        }else if(now==1){
            printf("  1增加 2删除 3查找\r\n");
            int a,b,c,d;
            scanf("%d",&a);
            if(a==1){
                scanf("%d",&b);
                point[b]=1;
            }else if(a==2){
                scanf("%d",&b);
                point[b]=0;
                if(b==n){
                    n--;
                }
            }else if(a==3){
                scanf("%d",&b);
                if(point[b]==1){
                    printf("    存再\r\n");
                }else{
                    printf("   不存再\r\n");
                }
            }
        }else if(now==2){
            printf("  1增加 2删除 3改变\r\n");
            int a,b,c,d;
            if(a==1 || a==3){
                scanf("%d %d %d",&b,&c,&d);
                add_g_1(b,c,d);
            }else if(a==2){
                scanf("%d %d" ,&b,&c);
                g_1[b][c]=INF;
            }
        }else if(now==3){
            int a;
            g1tog2();
            scanf("%d",&a);
            memset(v,0,sizeof(v));
            dfs(a);
            printf("\r\n");
        }else if(now==4){
            g1tog2();
            int a;
            scanf("%d",&a);
            memset(v,0,sizeof(v));
            bfs(a);
            printf("\r\n");
        }else if(now==5){
            for(int i=0;i<=n;i++){
                dist[i]=INF;
            }
            memset(v,0,sizeof(v));
            int a;
            scanf("%d",&a);
            Dijkstra(a);
            for(int j=0;j<=n;j++){
                if(j==a)continue;
                if(dist[j]==INF){
                    printf(" %d->%d:error ",a,j);
                }else{
                    printf(" %d->%d:%d ",a,j,dist[j]);
                }
            }
        }else if(now==6){
            for(int i=0;i<=n;i++){
                for(int i=0;i<=n;i++){
                    dist[i]=INF;
                }
                memset(v,0,sizeof(v));
                Dijkstra(i);
                for(int j=0;j<=n;j++){
                    if(j==i)continue;
                    if(dist[j]==INF){
                        printf("%d->%d:error ",i,j);
                    }else{
                        printf("%d->%d:%d ",i,j,dist[j]);
                    }
                }
                printf("\r\n");
            }
        }else if(now==7){
            int fl=1;
            for(int i=0;i<=n;i++){
                if(bf(i)==0){
                    fl=0;
                    break;
                }
            }
            if(fl){
                printf("不存在负环\r\n");
            }else{
                printf("存在负环\r\n");
            }
        }else break;
    }
    return 0;
}






































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清欢_小铭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值