数据结构 邻接矩阵+邻接表+bfs+dfs+prim+Kruskal综合

来源:互联网 发布:ubuntu 安装到u盘 编辑:程序博客网 时间:2024/06/03 15:58



/*严格参照《数据结构(严蔚敏版)》2017.11.30by kk*/#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<queue>#include<math.h>#define infinity 0x3f3f3f3f#define maxsize 50using namespace std;typedef int VertexType;typedef int EdgeType;//下面是图的邻接矩阵的定义typedef struct{    EdgeType data;//弧的信息,比如可以用来标志这条边存不存在,权值多少    char infomation;//可以用来储存弧其他的信息} Matrix;typedef struct GraphM{    VertexType ver[maxsize];//顶点信息,如名字    Matrix arc[maxsize][maxsize];//邻接矩阵    int numVex,numEdge;//顶点个数,边的个数    int kind;//图的种类} GraphM;/*实际运用时如果弧上的信息不多(比如只有权值),其实就直接可以用用下面的方式定义typedef struct Graph{    int vertex[100];    int arc[100][100];    int num_ver,num_edge;} Mygraph;*///下面是邻接表的定义typedef struct ENode{    VertexType v;//节点的定义    int weight;//弧的权值    struct ENode *next;} ENode;typedef struct//顶点的定义{    VertexType v;    ENode *first;} VerNode;typedef struct//图的定义{    VerNode VerList[maxsize];//顶点表    int numVer,numEdge;//顶点个数,边的个数    int kind;//图的种类} GraphL;int vis[maxsize];void createGraphMatrix(GraphM &g)//邻接矩阵建图{    int i,j;    scanf("%d%d",&g.numVex,&g.numEdge);    for(i=0; i<g.numVex; i++)scanf("%d",&g.ver[i]);    for(i=0; i<g.numVex; i++)    {        for(j=0; j<g.numVex; j++)            g.arc[i][j].data=infinity;    }    int x,y,w;    for(i=0; i<g.numEdge; i++)    {        scanf("%d%d%d",&x,&y,&w);        g.arc[x][y].data=w;        g.arc[y][x].data=w;//如果是无向图就把这句加上    }    for(i=0; i<g.numVex; i++)    {        for(j=0; j<g.numVex; j++)            printf("%d ",g.arc[i][j].data);        puts("");    }}void createGraphList(GraphL &g)//邻接表建图{    int i,j;    ENode *e;    scanf("%d%d",&g.numVer,&g.numEdge);    for(i=0; i<g.numVer; i++)    {        scanf("%d",&g.VerList[i].v);        g.VerList[i].first=NULL;    }    int x,y,w;    for(i=0; i<g.numEdge; i++)    {        scanf("%d%d%d",&x,&y,&w);        e=(ENode *)malloc(sizeof(ENode));        e->v=y;        e->weight=w;        e->next=g.VerList[x].first;        g.VerList[x].first=e;//如果是无向图就把下面这段代码加上//        e=(ENode *)malloc(sizeof(ENode));//        e->v=x;//        e->weight=w;//        e->next=g.VerList[y].first;//        g.VerList[y].first=e;    }}void dfs_M(GraphM g,int x)//邻接矩阵dfs某个节点{    vis[x]=1;    printf("%d ",g.ver[x]);    for(int i=0; i<g.numVex; i++)        if(vis[i]==0&&g.arc[x][i].data!=infinity)dfs_M(g,i);}void dfs_Matrix(GraphM g)//dfs整个表(即使不是连通图也可以){    memset(vis,0,sizeof(vis));    for(int i=0; i<g.numVex; i++)        if(vis[i]==0)dfs_M(g,i);}void dfs_L(GraphL g,int x)//邻接表dfs某个节点{    vis[x]=1;    printf("%d ",g.VerList[x].v);    ENode *p;    p=g.VerList[x].first;    int tmp;    while(p)    {        tmp=p->v;        if(vis[tmp]==0)        {            dfs_L(g,tmp);        }        p=p->next;    }}void dfs_List(GraphL g)//邻接表dfs整个图{    memset(vis,0,sizeof(vis));    ENode *p;    for(int i=0; i<g.numVer; i++)    {        if(vis[i]==0)        {            dfs_L(g,i);        }    }}void bfs_M(GraphM g,int x)//邻接矩阵从x点开始广度优先遍历{    queue<int>que;    que.push(x);//入队    vis[x]=1;//vis标记入口    int i,tmp;    while(!que.empty())    {        tmp=que.front();        printf("%d ",g.ver[tmp]);        que.pop();        for(i=0; i<g.numVex; i++)        {            if(g.arc[tmp][i].data!=infinity&&vis[i]!=1)            {                que.push(i);                vis[i]=1;            }        }    }}void bfs_Matrix(GraphM g)//邻接矩阵bfs遍历整个图{    memset(vis,0,sizeof(vis));    for(int i=0; i<g.numVex; i++)        if(vis[i]==0)bfs_M(g,i);}void bfs_L(GraphL g,int x)//邻接表从x点开始bfs遍历{    queue<int>que;    ENode *p;    que.push(x);    vis[x]=1;    int i,tmp;    while(!que.empty())    {        tmp=que.front();        printf("%d ",g.VerList[tmp].v);        p=g.VerList[tmp].first;        que.pop();        while(p)        {            if(vis[p->v]==0)            {                que.push(p->v);                vis[p->v]=1;            }            p=p->next;        }    }}void bfs_List(GraphL g)//邻接表bfs整个图{    memset(vis,0,sizeof(vis));    for(int i=0; i<g.numVer; i++)        if(vis[i]==0)bfs_L(g,i);}void miniSpanTree_Prim(GraphM g,int x)//prim算法求最小生成树{    int lowcost[maxsize];    //用来储存从现在已有的点出发到达为选择点的最短路径,这个最短不是说从某个点到达另外一个点的最短路径,    //而是说就单条边的长度来说,也就是说这里面保存的值都是某条边的长度    int adjvex[maxsize];    int i,j,k;    for(i=0; i<g.numVex; i++)        if(i!=x)lowcost[i]=g.arc[x][i].data;    lowcost[x]=0;    //若lowcost[i]=0,说明i点已经被选中    for(i=0; i<g.numVex; i++)        adjvex[i]=x;//所有的点最开始都是从i出发的    for(i=1; i<g.numVex; i++)    {        int Min=infinity;        for(j=0; j<g.numVex; j++)//从lowcost数组中找出最短的边        {            if(lowcost[j]!=0&&lowcost[j]<Min)            {                Min=lowcost[j];                k=j;            }        }        printf("%d %d %d\n",adjvex[k],k,lowcost[k]);        lowcost[k]=0;        for(j=0; j<g.numVex; j++)        {            if(lowcost[j]!=0&&g.arc[k][j].data<lowcost[j])//更新lowcost数组和adjvex数组            {                lowcost[j]=g.arc[k][j].data;                adjvex[j]=k;            }        }        //lowcost数组是用来存边长度和寻找最短边的        //而adjvex是用来记录路径的(就是这棵树的边是从哪个点到哪个点)    }}int pre[maxsize];//用来记录根节点typedef struct{    int start;    int last;    int weight;} Edge;//相当于创建边集bool cmp( Edge a, Edge b){    return a.weight<b.weight;}//边集比较int Find(int x){    int r=x;    while(r!=pre[r])    {        r=pre[r];    }    return r;}//这里其实用到了并查集的思想,找x的根节点//下面的函数中也有void MiniSpanTree_Kruskal(GraphM g){    Edge s[100];    int cnt=0;    for(int i=0; i<g.numVex; i++)    {        for(int j=i; j<g.numVex; j++)        {            if(g.arc[i][j].data!=infinity)            {                s[cnt].start=i;                s[cnt].last=j;                s[cnt].weight=g.arc[i][j].data;                ++cnt;            }        }    }    int i,j;    sort(s,s+cnt,cmp);//    for(i=0; i<g.numEdge; i++)//        printf("%d %d %d\n",s[i].start,s[i].last,s[i].weight);    //以上是将邻接矩阵转换成边集,并按权值从小到大排序    //pre[]数组初始化, pre[i]=i的意思是每个节点的跟节点都是自己本身    for(i=0; i<g.numVex; i++)        pre[i]=i;    int n,m;    for(i=0; i<g.numEdge; i++)    {        n=Find(s[i].start);        m=Find(s[i].last);        //这里n,m分别是这条边两个节点的各自的根节点,如果m,n不等,那么说明        //m,n不在一个集合中,也就说明没有构成环        if(n!=m)        {            pre[n]=m;//将m节点及其孩子加入n所在的集合            printf("%d %d %d\n",s[i].start,s[i].last,s[i].weight);        }    }}int main(){//    GraphL G;//    createGraphList(G);    GraphM G;    memset(vis,0,sizeof(vis));    createGraphMatrix(G);//    dfs_Matrix(G1);//    dfs_Matrix(G);    miniSpanTree_Prim(G,0);    printf("\n");    MiniSpanTree_Kruskal(G);//    bfs_L(G,2);//     GraphL G2;  l//    createGraphList(G2);//    dfs_List(G2);    printf("\n");    return 0;}/*5 50 1 2 3 40 1 90 2 21 2 32 3 53 4 15 60 1 2 3 40 1 90 2 20 4 61 2 32 3 53 4 19 150 1 2 3 4 5 6 7 80 1 100 5 111 6 165 6 171 2 181 8 122 8 82 3 228 3 216 3 246 7 193 7 167 4 73 4 205 4 26*/


阅读全文
0 0
原创粉丝点击