数据结构之图的应用

/*图的邻接矩阵和邻接表的转换,图的遍历,最小生成树等*/

#include "stdio.h"

#include "malloc.h"

#define INF 32767            //表示正无穷

#define MAXV 100             //最大顶点个数

 

int visited[MAXV];           //全局数组

//定义邻接矩阵类型

typedef int InfoType;

 

typedef struct {

       int NO;                 //顶点编号

       InfoType info;          //顶点的其他信息

}VertexType;                //顶点类型

 

typedef struct {

       int edges[MAXV][MAXV];  //邻接矩阵

       int n,e;                //顶点数、边数

       VertexType Vexs[MAXV];  //存放顶点信息

}MGraph;                    //图的邻接矩阵类型

 

//定义邻接表类型

typedef struct ANode {      //边的节点结构类型

       int adjvex;             //该边的终点位置

       struct ANode *nextarc;   //指向下一条边的指针

       InfoType info;          //该边的相关信息,这里用于存放权值

}ArcNode;

 

typedef int Vertex;

 

typedef struct VNode {      //邻接表头节点的类型

       Vertex data;            //顶点信息

       ArcNode *firstarc;      //指向第一条边

}VNode;

 

typedef VNode Adjlist[MAXV];//Adjlist是邻接表类型

 

typedef struct {

       Adjlist adjlist;         //邻接表

       int n,e;                 //图中顶点数n和边数e

}ALGraph;                    //图的邻接表类型

 

 

//不带权值的图

void MarToList(MGraph g,ALGraph *&G)         //将邻接矩阵g转化为邻接表G

{

       int i,j;

       ArcNode *p;

       G=(ALGraph *)malloc(sizeof(ALGraph));

       for(i=0;i<g.n ;i++)                     //给邻接表中所有头节点的指针域赋初值

              G->adjlist [i].firstarc =NULL;

       for(i=0;i<g.n ;i++)

              for(j=g.n -1;j>=0;j--)

                     if(g.edges [i][j]!=0)           //邻接矩阵当前元素不为0

                     {

                            p=(ArcNode *)malloc(sizeof(ArcNode));//创建一个节点*p

                            p->adjvex =j;

                            p->nextarc =G->adjlist [i].firstarc ;//将*p链到链表后

                            G->adjlist [i].firstarc =p;

                     }

                     G->n =g.n ;

                     G->e =g.e ;

}

 

void LisrToMat(ALGraph *G,MGraph &g)      //将邻接表G转换成邻接矩阵g

{

       int i,j;

       ArcNode *p;

       for(i=0;i<G->n ;i++)                 //g.edges[i][j]赋初值0

              for(j=0;j<G->n ;j++)

                     g.edges [i][j]=0;

       for(i=0;i<G->n ;i++)

       {

              p=G->adjlist[i].firstarc ;

              while(p!=NULL)

              {

                     g.edges [i][p->adjvex ]=1;

                     p=p->nextarc ;

              }

       }

       g.n =G->n ;

       g.e =G->e ;

}

 

void DispMat(MGraph g)       //输出邻接矩阵g

{

       int i,j;

       for(i=0;i<g.n ;i++)

       {

              for(j=0;j<g.n ;j++)

                     printf("%3d",g.edges [i][j]);

              printf("\n");

       }

}

 

void DispAdj(ALGraph *G)

{

       int i;

       ArcNode *p;

       for(i=0;i<G->n ;i++)

       {

              p=G->adjlist [i].firstarc ;

              printf("%3d:",i);

              while(p!=NULL)

              {

                     printf("%3d",p->adjvex ) ;

                     p=p->nextarc;

              }

              printf("\n");

       }

}

 

 

//带权值的图

void MatToList1(MGraph g,ALGraph *&G)

{

       int i,j;

       ArcNode *p;

       G=(ALGraph *)malloc(sizeof(ALGraph));

       for(i=0;i<g.n ;i++)

              G->adjlist[i].firstarc =NULL;

              for(i=0;i<g.n ;i++)

    for(j=g.n -1;j>=0;j--)

              if(g.edges [i][j]!=0&&g.edges [i][j]!=INF)         

              {

                     p=(ArcNode *)malloc(sizeof(ArcNode));//创建一个节点*p

                     p->adjvex =j;

                     p->info =g.edges [i][j];

                     p->nextarc =G->adjlist [i].firstarc ;//将*p链到链表后

                     G->adjlist [i].firstarc =p;

              }

              G->n =g.n ;

              G->e =g.e ;

}

 

void ListToMat1(ALGraph *G,MGraph &g)

{

       int i,j;

       ArcNode *p;

       for(i=0;i<G->n ;i++)                 //g.edges[i][j]赋初值0

              for(j=0;j<G->n ;j++)

                     if(i==j)

                            g.edges [i][j]=0;

                     else g.edges [i][j]=INF;

       for(i=0;i<G->n ;i++)

       {

              p=G->adjlist[i].firstarc ;

              while(p!=NULL)

              {

                     g.edges [i][p->adjvex ]=p->info  ;

                     p=p->nextarc ;

              }

       }

       g.n =G->n ;

       g.e =G->e ;

}

 

void DispMat1(MGraph g)       //输出邻接矩阵g

{

       int i,j;

       for(i=0;i<g.n ;i++)

       {

              for(j=0;j<g.n ;j++)

                     if(g.edges [i][j]==INF)

                            printf(" %3s","∞");

                     else

                            printf(" %3d",g.edges [i][j]);

              printf("\n");

       }

}

 

void DispAdj1(ALGraph *G)

{

       int i;

       ArcNode *p;

       for(i=0;i<G->n ;i++)

       {

              p=G->adjlist [i].firstarc ;

              printf("%3d:",i);

              while(p!=NULL)

              {

                     printf("%3d(%d)",p->adjvex,p->info  ) ;

                     p=p->nextarc;

              }

              printf("\n");

       }

}

 

//非递归深度优先遍历

void DFS(ALGraph *G,int v)

{

       ArcNode *p;

       ArcNode *St[MAXV];

       int top =-1,w,i;

       for(i=0;i<G->n ;i++)

              visited[i]=0;        //顶点访问标志赋值为0

       printf("%3d",v);         //访问顶点

       visited[v]=1;            //标记访问过的顶点

       top++;

       St[top]=G->adjlist [v].firstarc ;

       while(top>-1)

       {

              p=St[top];

              top--;

              while(p!=NULL)

              {

                     w=p->adjvex ;

                     if(visited[w]==0)

                     {

                            printf("%3d",w);

                            visited[w]=1;

                            top++;             //将顶点w的第一个顶点进栈

                            St[top]=G->adjlist [w].firstarc ;

                            break;

                     }

                     p=p->nextarc ;

              }

       }

       printf("\n");

}

 

//深度优先遍历

void DFS1(ALGraph *G,int v)

{

       ArcNode *p;

       visited[v]=1;

       printf("%3d",v);

      

       p=G->adjlist [v].firstarc ;   //p指向顶点v的第一条边的边头节点

       while(p!=NULL)

       {

              if(visited[p->adjvex] ==0)    //p->adjvex顶点未访问,递归访问他

                     DFS1(G,p->adjvex );

              p=p->nextarc ;               //指向下一条边的边头节点

       }

 

}

 

//广度优先遍历

void BFS(ALGraph *G,int v)

{

       ArcNode *p;

       int queue[MAXV],front=0,rear=0;   //定义循环队列,并初始化

       int visited[MAXV];                //定义存放顶点的访问标志的数组

       int w,i;

       for(i=0;i<G->n ;i++)

              visited[i]=0;                 //初始化标志数组

       printf("%3d",v);

       visited[v]=1;

       rear=(rear+1)%MAXV;               //也可以不用循环队列的,一般都不会溢出

       queue[rear]=v;                    //v进队

       while (front!=rear)               //队列不空

       {

              front=(front+1)%MAXV;

              w=queue[front];               //出队,并赋给w

              p=G->adjlist [w].firstarc ;   //找与顶点W邻接的第一个顶点

              while(p!=NULL)

              {

                     if(visited[p->adjvex ]==0)//当前访问的顶点没有访问过

                     {

                            printf("%3d",p->adjvex );

                            visited[p->adjvex ]=1;

                            rear=(rear+1)%MAXV;

                            queue[rear]=p->adjvex ;

                     }

                     p=p->nextarc ;   //找下一个邻接顶点

              }

       }

       printf("\n\n");

}

 

 //利用普里姆算法求最小生成树

void Prim(MGraph g,int v)

{

       int lowcost[MAXV],min,n=g.n ;

       int closest[MAXV],i,j,k;

       for(i=0;i<n;i++)

       {

              lowcost[i]= (g.edges[v][i]==0?INF:g.edges[v][i]);

              closest[i]=0;

       }

       for(i=1;i<n;i++)

       {

              min=INF;

              for(j=0;j<n;j++)

                     if(lowcost[j]!=0 && lowcost[j]<min)

                     {

                            min=lowcost[j];

                            k=j;

                     }

                     printf(" 边(%d,%d)权为:%d\n",closest[k],k,min);

                     lowcost[k]=0;

                     for(j=0;j<n;j++)

                            if(g.edges [k][j]!=0 && g.edges [k][j]<lowcost[j])

                            {

                                   lowcost[j]=g.edges [k][j];

                                   closest[j]=k;

                            }

       }

}

 

void main()

{

       int i,j;

       MGraph g,g1;

       ALGraph *G;

       int A[8][8]={

              {0,4,3,0,0,0,0,0},

              {4,0,5,5,9,0,0,0},

              {3,5,0,5,0,0,0,5},

              {0,5,5,0,7,6,5,4},

              {0,9,0,7,0,3,0,0},

              {0,0,0,6,3,0,2,0},

              {0,0,0,5,0,2,0,6},

              {0,0,5,4,0,0,6,0}};

              g.n =8;g.e =14;

              for(i=0;i<g.n ;i++)

                     for(j=0;j<g.n ;j++)

                            g.edges [i][j]=A[i][j];

      

       G=(ALGraph *)malloc(sizeof(ALGraph));

 

    printf("图的邻接矩阵为:\n");

       DispMat(g) ;

 

       printf("\n无向图的邻接矩阵转换成邻接表:\n");

    MarToList(g,G);

       DispAdj(G);

 

       printf("\n带权无向图的邻接矩阵转换成邻接表:\n");

       MatToList1(g,G);

       DispAdj1(G);

 

       printf("\n无向图的邻接表换成邻接矩阵:\n");

    LisrToMat(G,g1);

       DispMat(g1);

 

       printf("\n带权无向图的邻接表换成邻接矩阵:\n");

       ListToMat1( G, g1);

       DispMat1(g1);

 

       printf("\n从顶点0开始的深度优先遍历(非递归):");

       DFS(G,0);

 

       for(i=0;i<G->n ;i++)

              visited[i]=0;

 

       printf("\n从顶点0开始的深度优先遍历(递归):");

       DFS1(G,0);

 

       printf("\n\n从顶点0开始的广度优先遍历:");

       BFS(G,0);

 

       printf("普里姆算法求解结果:\n");

       Prim( g,0);}

posted @ 2016-11-15 20:11  梦想起航2016  阅读(6034)  评论(0编辑  收藏  举报