邻接矩阵图的应用c++

注:若有错误或要改善的地方请告之,谢谢,新手上路,有些函数还是很冗余的,慢慢改进。

头文件:

#define MAXSIZE 100
typedef enum
{
    NN,
    NY,
    YN,
    YY
}MGragh_type;

/*************结构体************/
/*邻接矩阵*/
typedef struct
{
    char vex[MAXSIZE]; //顶点表
    int edge[MAXSIZE][MAXSIZE];   //边表
    int vexnum,arcnum;
    int MGragh_type;
}MGragh;
/*************图的操作****************/
/*初始化图*/
MGragh *init_MGragh()
{
    MGragh *m;
    m=(MGragh*)malloc(sizeof(MGragh));
    m->arcnum=m->vexnum=0;
    printf("请输入选择的图的类型 1、无向图 2、无向网 3、有向图 4、有向网:");
    scanf("%d",&m->MGragh_type);
    memset(m->edge,0,sizeof(m->edge));
    memset(m->vex,'#',sizeof(m->vex));
    return m;
}
/*返回结点在结点表的编号*/
int return_vexno(MGragh m,char e)
{
    int i;
    for(i=0;i<m.vexnum;i++)
    {
        if(m.vex[i]==e)
        {
            return i;
        }
    }
    return -1;
}
/*返回结点的出度*/
int return_vex_out(MGragh m,char a)
{
    int an=return_vexno(m,a);
    int i,num=0;
    for(i=0;i<m.vexnum;i++)
    {
        if(m.edge[an][i]>0)
        {
            num++;
        }
    }
    return num;
}
/*判断结点是否在结点表中*/
bool if_vex_in(MGragh m,char e)
{
    int i;
    for(i=0;i<m.vexnum;i++)
    {
        if(m.vex[i]==e)
        {
            return true;
        }
    }

    return false;
}
/*判断边是否已经存在*/
bool if_arc_in(MGragh m,int xn,int yn)  //xn,yn是结点在结点表的编号
{
    if(m.edge[xn][yn]>0)
    {
        return true;
    }
    return false;
}
/*创建无向图*/
void create_MGragh_NN(MGragh *m)
{
    int V,E,i,xn,yn;
    char x,y;
    printf("创造无向图\n请输入结点数与边数:");
    scanf("%d%d",&V,&E);
    printf("请依次输入头尾结点:\n");
    for(i=0;i<E;i++)
    {
        fflush(stdin);
        scanf("%c %c",&x,&y);
        fflush(stdin);
        if(!if_vex_in(*m,x))
        {
            m->vex[m->vexnum++]=x;
        }
        if(!if_vex_in(*m,y))
        {
            m->vex[m->vexnum++]=y;
        }
        xn=return_vexno(*m,x);
        yn=return_vexno(*m,y);
        if(if_arc_in(*m,xn,yn)||if_arc_in(*m,yn,xn))
        {
            continue;
        }
        m->edge[xn][yn]=m->edge[yn][xn]=1;
        m->arcnum++;
    }
}
/*创建无向网*/
void create_MGragh_NY(MGragh *m)
{
    int V,E,i,xn,yn,c;
    char x,y;
    printf("创造无向网\n请输入结点数与边数:");
    scanf("%d%d",&V,&E);
    printf("请依次输入头尾结点与权值:\n");
    for(i=0;i<E;i++)
    {
        fflush(stdin);
        scanf("%c %c %d",&x,&y,&c);
        fflush(stdin);
        if(!if_vex_in(*m,x))
        {
            m->vex[m->vexnum++]=x;
        }
        if(!if_vex_in(*m,y))
        {
            m->vex[m->vexnum++]=y;
        }
        xn=return_vexno(*m,x);
        yn=return_vexno(*m,y);
        if(if_arc_in(*m,xn,yn)||if_arc_in(*m,yn,xn))
        {
            continue;
        }
        m->edge[xn][yn]=m->edge[yn][xn]=c;
        m->arcnum++;
    }
}
/*创建有向图*/
void create_MGragh_YN(MGragh *m)
{
    int V,E,i,xn,yn;
    char x,y;
    printf("创造有向图\n请输入结点数与边数:");
    scanf("%d%d",&V,&E);
    printf("请依次输入头尾结点:\n");
    for(i=0;i<E;i++)
    {
        fflush(stdin);
        scanf("%c %c",&x,&y);
        fflush(stdin);
        if(!if_vex_in(*m,x))
        {
            m->vex[m->vexnum++]=x;
        }
        if(!if_vex_in(*m,y))
        {
            m->vex[m->vexnum++]=y;
        }
        xn=return_vexno(*m,x);
        yn=return_vexno(*m,y);
        if(if_arc_in(*m,xn,yn))
        {
            continue;
        }
        m->edge[xn][yn]=1;
        m->arcnum++;
    }
}
/*创建有向网*/
void create_MGragh_YY(MGragh *m)
{
    int V,E,i,xn,yn,c;
    char x,y;
    printf("创造有向网\n请输入结点数与边数:");
    scanf("%d%d",&V,&E);
    printf("请依次输入头尾结点与权值:\n");
    for(i=0;i<E;i++)
    {
        fflush(stdin);
        scanf("%c %c %d",&x,&y,&c);
        fflush(stdin);
        if(!if_vex_in(*m,x))
        {
            m->vex[m->vexnum++]=x;
        }
        if(!if_vex_in(*m,y))
        {
            m->vex[m->vexnum++]=y;
        }
        xn=return_vexno(*m,x);
        yn=return_vexno(*m,y);
        if(if_arc_in(*m,xn,yn))
        {
            continue;
        }
        m->edge[xn][yn]=c;
        m->arcnum++;
    }
}
/*创造图*/
void create_MGragh(MGragh *m)
{
    switch(m->MGragh_type)
    {
        case 1:create_MGragh_NN(m);break;
        case 2:create_MGragh_NY(m);break;
        case 3:create_MGragh_YN(m);break;
        case 4:create_MGragh_YY(m);break;
    }
}
/*输出图*/
void print_MGragh(MGragh m)
{
    int i,j;
    printf("该图的邻接矩阵为:\n");
    for(i=0;i<m.vexnum;i++)
    {
        for(j=0;j<m.vexnum;j++)
        {
            printf("|%d|",m.edge[i][j]);
        }
        printf("\n");
    }
    printf("该图的顶点表为:");
    for(i=0;i<m.vexnum;i++)
    {
        printf("%c",m.vex[i]);
    }
    printf("\n");
    printf("该图的顶点数为%d,边数为%d\n",m.vexnum,m.arcnum);
}
图的应用:

#include<stdlib.h>
#include<stdio.h>
#include<string>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<ctype.h>
#include"../../头文件/image_seq.h"
using namespace std;

int tohead[MAXSIZE];    //祖先数组,tohead[x]=y,编号为y的字符是编号为x的字符的祖先
bool visited[MAXSIZE][MAXSIZE]; //visited[][]为边访问标记
bool visited_node[MAXSIZE]; //为结点的标记
/******************公共函数********************/
/*初始化visited_node[]*/
void init_visited_node(MGragh m)
{
    int i;
    for(i=0;i<m.vexnum;i++)
    {
        visited_node[i]=false;
    }
}
/*判断图是否还有未被访问的与其连接的下一结点*/
/*若存在,则返回权值最小权值的头尾结点的编号(xn,yn)与权值min_*/
bool if_exist_next_node(MGragh m,int &xn,int &yn,int &min_)
{
    int i,j;
    min_=INT_MAX;
    for(i=0;i<m.vexnum;i++)
    {
        for(j=0;j<m.vexnum;j++)
        {
            if(m.edge[i][j]>0&&m.edge[i][j]<min_&&!visited_node[j]&&visited_node[i])    //j要未访问过,i要访问过
            {
                min_=m.edge[i][j];
                xn=i;
                yn=j;
            }
        }
    }
    if(min_!=INT_MAX)
    {
        return true;
    }
    else
    {
        xn=yn=min_=0;
        return false;
    }
}
/*初始化visited[][]*/
void init_visited()
{
    memset(visited,false,sizeof(visited));  //false为未访问
}
/*寻找权值最小且未访问的结点的编号*/
void min_edge(MGragh m,int &xn,int &yn) //需预先初始化visited[][]
{
    int i,j,min_=INT_MAX;
    for(i=0;i<m.vexnum;i++)
    {
        for(j=0;j<m.vexnum;j++)
        {
            if(m.edge[i][j]<min_&&!visited[i][j]&&m.edge[i][j]>0)
            {
                xn=i;
                yn=j;
                min_=m.edge[i][j];
            }
        }
    }
    visited[xn][yn]=true;
}
/*输出访问标记边*/
void print_visited(MGragh m)
{
    int i,j;
    printf("该图的访问标记为:\n");
    for(i=0;i<m.vexnum;i++)
    {
        for(j=0;j<m.vexnum;j++)
        {
            printf("|%d|",visited[i][j]);
        }
        printf("\n");
    }
}
/******************并查集*******************/
/*初始化tohead[]*/
/*初始化设置各个结点的祖先为自己*/
void init_tohead()
{
    int i;
    for(i=0;i<MAXSIZE;i++)
    {
        tohead[i]=i;
    }
}
/*找出结点的祖先*/
int find_(int x) //x为结点的编号
{
    if(tohead[x]==x)
    {
        return x;
    }
    else
    {
        return tohead[x]=find_(tohead[x]);
    }
}
/*将两结点的祖先合并*/
void union_(int x,int y)
{
    x=find_(x);
    y=find_(y);
    tohead[x]=y;
}
/********************最小生成树(MST)**********************/
/*Kruskal*/
/*选边*/
int Kruskal(MGragh m)   //使用并查集
{
    init_tohead();
    init_visited(); //为min_edge()设定的
    int xn,yn,i,vil=0;
    for(i=0;i<m.arcnum;i++)
    {
        min_edge(m,xn,yn);
        if(find_(xn)!=find_(yn))
        {
            vil+=m.edge[xn][yn];
            union_(xn,yn);
        }
    }
    printf("(kruskal)该图的最小生成树的权值为%d\n",vil);
    print_visited(m);
    return vil;
}
/*prim*/
/*选点*/
int prim(MGragh m)  //不使用并查集
{
    init_visited_node(m);
    int vexnum=1,headnum=0,i,j,xn,yn,vilue,num=0,min_=INT_MAX;
    for(headnum=0;headnum<m.vexnum;headnum++)
    {
            visited_node[headnum]=true;
            while(vexnum<m.vexnum)
            {
                if(!if_exist_next_node(m,xn,yn,vilue))
                {
                    break;
                }
                num+=vilue;
                visited_node[yn]=true;
                vexnum++;
            }
            if(vexnum>=m.vexnum)
            {
                min_=min(min_,num);
            }
            num=0;
            vexnum=1;
            init_visited_node(m);
    }
    printf("(prim)该图的最小生成树权值为%d\n",min_);
    return min_;
}
/***********************最短路径***************************/
/*dijkstra*/
/*单源最短路径*/
void dijkstra(MGragh m,char x)  //x为头结点
{
    printf("(dijkstra)该图从%c到其余各点的最短路径为:\n",x);
    int xn=return_vexno(m,x);
    int i,j;
    for(i=0;i<m.vexnum;i++)
    {
        for(j=0;j<m.vexnum;j++)
        {
            if(m.edge[xn][j]>(m.edge[xn][i]+m.edge[i][j])&&m.edge[xn][j]>0&&m.edge[xn][i]>0&&m.edge[i][j]>0)
            {
                m.edge[xn][j]=m.edge[xn][i]+m.edge[i][j];
            }
        }
    }
    print_MGragh(m);
}
/*floryd*/
/*多源最短路径*/
void floryd(MGragh m) //不改变图
{
    printf("(floryd)该图的最短路径为:\n");
    int i,j,k;  //k为插入的结点
    for(k=0;k<m.vexnum;k++)
    {
        for(i=0;i<m.vexnum;i++)
        {
            for(j=0;j<m.vexnum;j++)
            {
                if(m.edge[i][j]>(m.edge[i][k]+m.edge[k][j])&&m.edge[i][j]>0&&m.edge[i][k]>0&&m.edge[k][j]>0)
                {
                    m.edge[i][j]=m.edge[i][k]+m.edge[k][j];
                }
            }
        }
    }
    print_MGragh(m);
}
int main()
{
    MGragh *m;
    m=init_MGragh();
    create_MGragh(m);
    print_MGragh(*m);
    prim(*m);
    return 0;
}
/*
a c 3
a d 8
a b 5
c d 10
d a 7
d b 20
a c
a d
a b
c d
d a
d b
*/



评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值