數據結構之圖的應用


/*圖的鄰接矩陣和鄰接表的轉換,圖的遍歷,最小生成樹等*/

#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);}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM