【无标题】

第二题

#include<stdio.h>
#include<stdlib.h>
#define MAX_VER_NUM 50
#define MAX_ARC_NUM 50
#define INF 9999 //表示不可达,权值无限大 
 
typedef char VertexType;

int visited[MAX_VER_NUM];

typedef struct{  
    VertexType adjvex; //候选最短边的邻接点
    int lowcost; //候选最短边的权值 
}ShortEdge; //最短路径数组结构体(候选最短边)

typedef struct{
    VertexType vexs[MAX_VER_NUM]; //顶点向量
    int arcs[MAX_VER_NUM][MAX_VER_NUM]; //邻接矩阵,arcs[1][2]就代表城市1和城市2间的距离 
    int vexnum,arcnum; //图的当前顶点数和边数
}MGraph; //图数组元素类型 

typedef struct{
    VertexType start; //边的起点
    VertexType end;  //边的终点
    int weight; //边的权值 
}Edge; //边数组元素类型 

int getIndexOfVexs(char vex,MGraph *MG){
    int i;
    for(i=0;i<MG->vexnum;i++){
        if(MG->vexs[i]==vex)
            return i;
    }
    return 0;
}

//直接插入排序;对E数组按权值递增排序 
void SortEdge(Edge E[],int e){
    int i,j,k=0;
    Edge temp;
    for(i=1;i<e;i++){
        temp=E[i];
        j=i-1; //从右向左在有序区E[0..i-1]中找E[i]的插入位置 
        while(j>=0&&temp.weight<E[j].weight)
        {
            E[j+1]=E[j]; //将权值大于E[j].weight的记录后移 
            j--;
        }
            E[j+1]=temp; //在j+1处插入E[i]
    } 
}

//创建邻接矩阵、创建边集、输入城市信息 
void create_MG(MGraph *MG,Edge E[]){
    int i,j,k,distance;
    int v1,v2,type;
    char c1,c2; 
    printf("请输入城市(顶点)数:");
    scanf("%d",&MG->vexnum);
	// 吸收缓冲区的值 
    getchar();
    printf("请输入路径(边)数:");
    scanf("%d",&MG->arcnum);
    getchar();
    for(i=0;i<MG->vexnum;i++){
        printf("请输入第%d个城市:",i+1);         
        scanf("%c",&MG->vexs[i]);
        getchar();
    }
    //初始化邻接矩阵
    for(i=0;i<MG->vexnum;i++){
        for (j=0;j<MG->vexnum;j++)
            MG->arcs[i][j]=9999;
    }
    //输入边的信息,建立邻接矩阵
    for(int k=0;k<MG->arcnum;k++){
        printf("请输入第%d条边的信息 v(char) v(char) distance(int):",k+1);
        scanf("%c %c %d",&c1,&c2,&distance);
        getchar();
        v1=getIndexOfVexs(c1,MG);
        v2=getIndexOfVexs(c2,MG); 
        E[k].start=v1; // 起点 
        E[k].end=v2;  // 终点 
        // 两个城市间的距离 
        MG->arcs[v1][v2]=MG->arcs[v2][v1]=distance;
        // 边的权值=距离 
        E[k].weight=distance;
    }
}

//打印城市信息和城市之间的直接可达距离  
void print_MG(MGraph MG){
    int i,j;
    printf("城市的列表如下,共有5个城市:\n");
    for(i=0;i<MG.vexnum;i++){ 
        printf("(%d)%c\t",i+1,MG.vexs[i]);
    }
    printf("\n");
    // 遍历图中每两个顶点间的信息 
    for(i=0;i<MG.vexnum;i++){ 
        for(j=0;j<MG.vexnum;j++){
            if(i==j) break;
            else if(MG.arcs[i][j]==9999){
            	// 距离为9999 默认两个城市间不可达 
                printf("%c城市到%c城市不能直接到达\n",MG.vexs[i],MG.vexs[j]);
            }
            else{
                printf("%c城市到%c城市距离%d万里\n",MG.vexs[i],MG.vexs[j],MG.arcs[i][j]);
            }       
        }
    }
}

//邻接矩阵的深度优先递归算法
void DFS(MGraph *MG,  int i){
    int j;
    printf("%c",MG->vexs[i]);
    visited[i] = 1;
    for (j=0;j<MG->vexnum;j++){
        if (MG->arcs[i][j] != 9999 && visited[j]==0){
            DFS(MG,j); 
        }            
    }         
}
//邻接矩阵的深度遍历操作
void DFSTraverse(MGraph *MG){
    int i,count=0;
    for (i=0;i<MG->vexnum;i++){
//  保存数组是否遍历 
        visited[i] = 0;
    }     
    for (i=0;i<MG->vexnum;i++){
        if (visited[i]==0){
            DFS(MG, i); 
            count++;
        }       
    }
    printf("%d",count);       
}   

//寻找最短路径的顶点 
int min(MGraph *MG,ShortEdge *shortedge){
    int i,j;
    int min,loc;
    
    min=9999;
    for(i=1;i<MG->vexnum;i++)
    {
        if(min>shortedge[i].lowcost&&shortedge[i].lowcost!=0)
        {
            min=shortedge[i].lowcost;
            loc=i;
        }
    }
    return loc;
}

//并查集部分
int father[MAX_VER_NUM];//并查集数组
int findFather(int x){ // 查找x的父节点 
    int a=x;	// 让a去查找 
    while(x != father[x]){	// 如果x的父节点不是它自己,也就是x不是根节点 
      x=father[x]; 			// 继续查找 
    }
    //路径压缩 
    while(a!=father[a]){	
        int z=a;
        a=father[a];
        father[z]=x;		
    }
    return x; 	// 返回根节点 
} 

//使用Prim算法,返回最小生成树边权之和 
void Prim(MGraph *MG,VertexType start){ 
    int i,j,k,count=0;
    ShortEdge shortedge[MAX_VER_NUM];
    //1.处理起始点start 
    k=getIndexOfVexs(start,MG);
    for(i=0;i<MG->vexnum;i++)
    {
        shortedge[i].adjvex=start;
        shortedge[i].lowcost=MG->arcs[k][i];
    }
    shortedge[k].lowcost=0;//lowcost为0表示该顶点属于U集合 
    
    //2.处理后续结点 
    for(i=0;i<MG->vexnum-1;i++)//对集合U,去找最短路径的顶点 
    {
        k=min(MG,shortedge);//找最短路径的顶点 
        printf("构成最小代价生成树的边集为:");
        printf("%c->%c,%d\n",shortedge[k].adjvex,MG->vexs[k],shortedge[k].lowcost);
        count+=shortedge[k].lowcost;
        shortedge[k].lowcost=0;//将找到的最短路径顶点加入集合U中 
        
        for(j=0;j<MG->vexnum;j++)//U中加入了新节点,可能出现新的最短路径,故更新shortedge数组 
        {
            if(MG->arcs[k][j]<shortedge[j].lowcost)//有更短路径出现时,将其替换进shortedge数组 
            {
                shortedge[j].lowcost=MG->arcs[k][j];
                shortedge[j].adjvex=MG->vexs[k];
            }
        }
    } 
    printf("用Prim生成最小生成树权值之和为:%d\n",count);  
}

//使用Kruskal算法,返回最小生成树边权之和 
void Kruskal(MGraph *MG,Edge E[]){//输出求得的最小生成树的所有边 
    int i,j,k,start1,end1,sn1,sn2,count=0;
    int vset[MAX_VER_NUM];//建立数组vset 
    for(int i=0;i<MG->vexnum;i++){//顶点范围是[0,n-1]
        father[i]=i;//并查集初始化 
    } 
     
    SortEdge(E,MG->arcnum);//k为上边累加计算所得 ,采用直接插入排序对E数组按权值递增排序
    for(i=0;i<MG->vexnum;i++) vset[i]=i; //初始化辅助数组 
    k=1;//k表示当前构造生成树的第几条边,初值为1
    j=0;//j为E数组下标,初值为0
    
    while(k<MG->vexnum)//生成边数小于顶点数时循环
    {
        start1=E[j].start; 
        end1=E[j].end;
        sn1=vset[start1];  
        sn2=vset[end1];//分别得到两个顶点所属的集合编号
        
        if(sn1!=sn2){
            printf("构成最小代价生成树的边集为:");
            printf("边(%d,%d),权值为%d\n",start1,end1,E[j].weight); // E数组存放着边的权值 
            count+=E[j].weight;
            k++;
            for(i=0;i<MG->vexnum;i++){
                if(vset[i]==sn2){//所有和sn2相等的辅助数值对应索引 通过遍历被找出 
                    vset[i]=sn1;
                }
            }   
        }   
        j++;//扫描下一条边        
    } 
    printf("用Krusal生成最小生成树权值之和为:%d\n",count);    
}

// 用于prim算法,从一个点开始出发
char in_point()
{
    char start;
    printf("请输入起始点:");
    scanf("%c",&start);
    return start;
} 

//主函数
int main(void){
    int i,j;int a; 
    MGraph MG;
    Edge E[MAX_VER_NUM]; 

    while(1){
        printf("\n功能列表\n");
        printf("--------------------\n");                  
        printf("1.输入城市信息;\n");
        printf("2.打印城市信息和城市之间的直接可达距离;\n");
        printf("3.DFS遍历;\n");
        printf("4.Prime算法实现最小生成树;\n");
        printf("5.Kruskal算法实现最小生成树;\n");
        printf("6.退出;\n");
        printf("--------------------\n");
        printf(">>>");               
        scanf("%d",&a);      
        switch(a){                        
            case 1: create_MG(&MG,E);break;        
            case 2: print_MG(MG);break;                  
            case 3: DFSTraverse(&MG);break;                             
            case 4: in_point();Prim(&MG,in_point());break; 
            case 5: Kruskal(&MG,E);break;
            case 6: return 0;                           
            default:printf("选择错误,请重新选择!\n");             
        }             
    }  
    return 0;
}

第三题

#include <stdio.h>  
#include <time.h>  
#include <string.h>  
   
#define MaxNum 20           //图的最大顶点数  
#define MaxValue 9999      //权值的最大值小于 MaxValue  
#define Disconnect  9999    //设置不可达   
#define MAX_VERTEX_NUM 20   
#define INFINITE 9999   
  
#define USED 0;             //已选用顶点  
#define NoL -1              //非邻接顶点  
   
typedef struct{  
    char Vertex[MaxNum];            //保存顶点信息(序号或字母)  
    int VertexNum;                  //顶点的数量  
    int EdgeNum;                    //边的数量  
    int EdgeWeight[MaxNum][MaxNum]; //保存边的权  
    int isTrav[MaxNum];             //定义邻接矩阵图结构  
}GraphMatrix;  
  
typedef struct  {   
    int vertexNum;   // 顶点的数量 
    char vertex[MAX_VERTEX_NUM];   // 顶点的名称 
    int arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM];   // 保存顶点信息 
}Graph,*PGraph;   
   
typedef struct {   
    int distance;   // 两个城市间的距离,也就是边的权值 
    int path[MAX_VERTEX_NUM];   // 存入数据 
}ArrayNode;   
  
  // 生成图 
void CreateGraph(GraphMatrix *GM){  
    int i,j,k;  // 用i,j来具体表示顶点的位置,k边的个数 
    int weight;  
    char EstartV,EendV;    
    printf("输入图中各顶点信息\n");  
    for (i = 0; i<GM->VertexNum; i++){  
        getchar();  
        printf("第%d个顶点:",i+1);  
        scanf("%c",&(GM->Vertex[i]));  
    }  
    printf("输入构成各边的顶点及权值:\n");  
    for (k = 0; k <GM->EdgeNum; k++){  
        getchar();  
        printf("第%d条边:",k+1);  
        scanf("%c %c %d",&EstartV,&EendV,&weight);  // 开始节点,结束节点,边的权值 
        for ( i= 0; EstartV != GM->Vertex[i]; i++);  // 在已有的节点中查找起点	 
        for ( j= 0; EendV != GM->Vertex[j]; j++);   // 在已有的节点中查找终点 
        GM->EdgeWeight[i][j] = weight;  
        GM->EdgeWeight[j][i] = weight;  
          
    }  
}  
// 把图初始化,每个顶点直接不连通 
void ClearGraph(GraphMatrix *GM){  
    int i,j;  
    for (i=0; i<GM->VertexNum; i++){  
        for (j=0; j<GM->VertexNum; j++){  
        // 设置每条边的权值9999 不可达 
            GM->EdgeWeight[i][j] = MaxValue;  
        }  
    }  
}  
// 输出图的信息 
void OutGraph(GraphMatrix *GM){  
    int i,j;  
    for (j=0; j<GM->VertexNum; j++);  
    printf("\n");     
    printf("\n城市的列表如下,共有%d个城市:\n",j);  
    for (j=0; j<GM->VertexNum; j++){  
        printf("\t%c",GM->Vertex[j]);  
    }  
    printf("\n");  
    for ( i=0; i<GM->VertexNum; i++){  
        for (j=0; j<GM->VertexNum; j++){  
            if (GM->EdgeWeight[i][j] == MaxValue){  
                if(i==j)continue;  
                printf("%c到%c不能直接到达\n",GM->Vertex[i],GM->Vertex[j]);  
            }  
            else{  
                printf("%c到%c距离%d",GM->Vertex[i],GM->Vertex[j],GM->EdgeWeight[i][j]);  //输出边的权值  
                printf("\n");  
            }  
        }  
    }  
      
}  
  
GraphMatrix iocity(GraphMatrix GM){  
    printf("\n生成无向图!\n");   
    printf("输入图的顶点数量:");  
    scanf("%d",&GM.VertexNum);  
    printf("输入图的边数量:");  
    scanf("%d",&GM.EdgeNum);  
    ClearGraph(&GM);  
    CreateGraph(&GM);  
    return GM;  
}  
  
void createdGraph(PGraph g,GraphMatrix GM) {   
    int i,j;   
    g->vertexNum=GM.VertexNum;   
    for(i=0;i<g->vertexNum;i++)   
        g->vertex[i]='A'+i;   
    for(i=0;i<g->vertexNum;i++)   
        for(j=0;j<g->vertexNum;j++)   
            g->arc[i][j]=0;     
    for(int a=0;a<GM.VertexNum;a++){  
        for(int b=0;b<GM.VertexNum;b++){  
            if(GM.EdgeWeight[a][b]==MaxValue)continue;  
            g->arc[a][b]=GM.EdgeWeight[a][b];  
        }  
    }  
}  
  
void Dijkstra(int from,int to,PGraph g) {   
    char aa,bb;  
    aa=(char)(from+65);  
    bb=(char)(to+65);  
    int i,j,index=-1;   
    int n=1;//记录已经求出的两个点之间的最短距离的个数   
    ArrayNode shortestPath[MAX_VERTEX_NUM];   
    int flag[MAX_VERTEX_NUM]={0};//标记,为1表示到这个顶点的最短距离已求出   
    //求from到各个顶点的直接距离,即初始化shortestPath数组   
    for(i=0;i<g->vertexNum;i++){   
        if(from==i){   
            shortestPath[i].distance=0;   
            shortestPath[i].path[0]=i;   
            flag[from]=1;   
        }   
        else if(g->arc[from][i]>0){   
            shortestPath[i].path[0]=from;   
            shortestPath[i].path[1]=i;   
            shortestPath[i].distance=g->arc[from][i];   
        }else   
            shortestPath[i].distance=INFINITE;   
    }   
    //每次求一个最短路径   
    while(n<g->vertexNum){   
        //选择shortestPath中距离最小的,求出from到这个顶点的最短路径   
        index=-1;   
        for(i=0;i<g->vertexNum;i++){   
            if(i==from)   
                continue;   
            if(flag[i]==0 && index==-1 && shortestPath[i].distance!=INFINITE)   
                index=i;   
            if(flag[i]==0 && index!=-1 && shortestPath[i].distance<shortestPath[index].distance)   
                index=i;   
        }   
        flag[index]=1;   
        //修改到各个顶点的最短路径   
        for(i=0;i<g->vertexNum;i++){   
            if(i==from)   
                continue;   
            if(g->arc[index][i]>0 && g->arc[index][i]+shortestPath[index].distance<shortestPath[i].distance){   
                shortestPath[i].distance=g->arc[index][i]+shortestPath[index].distance;   
                //修改路径   
                j=0;   
                while(1){   
                    shortestPath[i].path[j]=shortestPath[index].path[j];   
                    if(shortestPath[index].path[j]==index)   
                        break;   
                    j++;   
                }   
                shortestPath[i].path[j+1]=i;   
            }   
        }   
        n++;   
    }   
    //输出from到to的最短路径及长度   
    if(shortestPath[to].distance==INFINITE){   
        printf("%c到%c没有路径\n",aa,bb);   
        return;   
    }   
    printf("%c到%c的最短路径长度是:%d\n",aa,bb,shortestPath[to].distance);   
    printf("经过的顶点:  ");   
    i=0;   
    while(1){   
        printf("%-3c",shortestPath[to].path[i]+'A');   
        if(shortestPath[to].path[i]==to)   
            break;   
        i++;   
    }   
    printf("\n");   
}   
  
void ShortPath(GraphMatrix GM) {   
    Graph g;   
    char from,to,BBB;   
    int a,b;  
    createdGraph(&g,GM);   
    printf("请输入起点终点(如AB,中间不要有空格):");   
    scanf("%c%c%c",&BBB,&from,&to);   
    a=(int)from;  
    b=(int)to;  
    Dijkstra((a-65),(b-65),&g);   
}   
  
int main(){   
    GraphMatrix GM;  
    int choose, k;  
    do{  
        printf("\n请选择要执行的模块\n\n");  
        printf("1. 输入城市信息\n");  
        printf("2. 打印城市信息和城市之间的直接可达距离\n");  
        printf("3. 计算任意两个城市之间的最短路径\n");  
        printf("4. 退出\n\n");   
        scanf("%d",&choose);  
        switch(choose){  
            case 1: GM = iocity(GM);break;  
            case 2: OutGraph(&GM);break;   
            case 3: ShortPath(GM);break;  
            case 4: return 0;  
            default: printf("选择错误,重新选择\n");  
        }  
    }while(1);  
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值