第十二週 項目1 -圖基本算法庫

/*   
* Copyright (c)2015,煙臺大學計算機與控制工程學院   
* All rights reserved.   
* 文件名稱:12周項目1.cpp   
* 作    者:臧新曉 
* 完成日期:2016年11月12日   
* 版 本 號:v1.0     
* 問題描述:  定義圖的鄰接矩陣和鄰接表存儲結構,實現其基本運算,並完成測試。    
要求:   
1、頭文件graph.h中定義相關的數據結構並聲明用於完成基本運算的函數。對應基本運算的函數包括:   
    void ArrayToMat(int *Arr, int n, MGraph &g); //用普通數組構造圖的鄰接矩陣  
    void ArrayToList(int *Arr, int n, ALGraph *&); //用普通數組構造圖的鄰接表  
    void MatToList(MGraph g,ALGraph *&G);//將鄰接矩陣g轉換成鄰接表G  
    void ListToMat(ALGraph *G,MGraph &g);//將鄰接表G轉換成鄰接矩陣g  
    void DispMat(MGraph g);//輸出鄰接矩陣g  
    void DispAdj(ALGraph *G);//輸出鄰接表G      
2、在graph.cpp中實現這些函數  
3、用main.cpp中的main函數中完成測試。     
* 輸入描述: 無   
* 程序輸出: 測試數據   
*/  

//graph.h的代碼
#ifndef GRAPH_H_INCLUDED    
#define GRAPH_H_INCLUDED    
#include <stdio.h>    
#include <malloc.h>    
#define MAXV 100                //最大頂點個數    
#define INF 32767       //INF表示∞    
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;                //頂點信息    
    int count;                  //存放頂點入度,只在拓撲排序中用    
    ArcNode *firstarc;          //指向第一條弧    
} VNode;    
typedef VNode AdjList[MAXV];    //AdjList是鄰接表類型    
typedef struct    
{    
    AdjList adjlist;            //鄰接表    
    int n,e;                    //圖中頂點數n和邊數e    
} ALGraph;                      //圖的鄰接表類型    
//功能:由一個反映圖中頂點鄰接關係的二維數組,構造出用鄰接矩陣存儲的圖    
//參數:Arr - 數組名,由於形式參數爲二維數組時必須給出每行的元素個數,在此將參數Arr聲明爲一維數組名(指向int的指針)    
//      n - 矩陣的階數    
//      g - 要構造出來的鄰接矩陣數據結構    
void ArrayToMat(int *Arr, int n, MGraph &g); //用普通數組構造圖的鄰接矩陣    
void ArrayToList(int *Arr, int n, ALGraph *&); //用普通數組構造圖的鄰接表    
void MatToList(MGraph g,ALGraph *&G);//將鄰接矩陣g轉換成鄰接表G    
void ListToMat(ALGraph *G,MGraph &g);//將鄰接表G轉換成鄰接矩陣g    
void DispMat(MGraph g);//輸出鄰接矩陣g    
void DispAdj(ALGraph *G);//輸出鄰接表G    
#endif // GRAPH_H_INCLUDED
  
圖基本運算函數  

#include "graph.h"    
//功能:由一個反映圖中頂點鄰接關係的二維數組,構造出用鄰接矩陣存儲的圖    
//參數:Arr - 數組名,由於形式參數爲二維數組時必須給出每行的元素個數,在此將參數Arr聲明爲一維數組名(指向int的指針)    
//      n - 矩陣的階數    
//      g - 要構造出來的鄰接矩陣數據結構    
void ArrayToMat(int *Arr, int n, MGraph &g)    
{    
    int i,j,count=0;  //count用於統計邊數,即矩陣中非0元素個數    
    g.n=n;    
    for (i=0; i<g.n; i++)    
        for (j=0; j<g.n; j++)    
        {    
            g.edges[i][j]=Arr[i*n+j]; //將Arr看作n×n的二維數組,Arr[i*n+j]即是Arr[i][j],計算存儲位置的功夫在此應用    
            if(g.edges[i][j]!=0)    
                count++;    
        }    
    g.e=count;    
}    
  
void ArrayToList(int *Arr, int n, ALGraph *&G)    
{    
    int i,j,count=0;  //count用於統計邊數,即矩陣中非0元素個數    
    ArcNode *p;    
    G=(ALGraph *)malloc(sizeof(ALGraph));    
    G->n=n;    
    for (i=0; i<n; i++)                 //給鄰接表中所有頭節點的指針域置初值    
        G->adjlist[i].firstarc=NULL;    
    for (i=0; i<n; i++)                 //檢查鄰接矩陣中每個元素    
        for (j=n-1; j>=0; j--)    
            if (Arr[i*n+j]!=0)      //存在一條邊,將Arr看作n×n的二維數組,Arr[i*n+j]即是Arr[i][j]    
            {    
                p=(ArcNode *)malloc(sizeof(ArcNode));   //創建一個節點*p    
                p->adjvex=j;    
                p->info=Arr[i*n+j];    
                p->nextarc=G->adjlist[i].firstarc;      //採用頭插法插入*p    
                G->adjlist[i].firstarc=p;    
            }    
    G->e=count;    
}    
  
void MatToList(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)       //存在一條邊    
            {    
                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 ListToMat(ALGraph *G,MGraph &g)    
//將鄰接表G轉換成鄰接矩陣g    
{    
    int i,j;    
    ArcNode *p;    
    for (i=0; i<g.n; i++)   //先初始化鄰接矩陣    
        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]=p->info;    
            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++)    
            if (g.edges[i][j]==INF)    
                printf("%3s","∞");    
            else    
                printf("%3d",g.edges[i][j]);    
        printf("\n");    
    }    
}    
  
  
  
  
void DispAdj(ALGraph *G)    
//輸出鄰接表G    
{    
    int i;    
    ArcNode *p;    
    for (i=0; i<G->n; i++)    
    {    
        p=G->adjlist[i].firstarc;    
        printf("%3d: ",i);    
        while (p!=NULL)    
        {    
            printf("-->%d/%d ",p->adjvex,p->info);    
            p=p->nextarc;    
        }    
        printf("\n");    
    }    
}  

//main.cpp的代碼
[cpp] view plain copy 在CODE上查看代碼片派生到我的代碼片
#include "graph.h"    
int main()    
{    
    MGraph g1,g2;    
    ALGraph *G1,*G2;    
    int A[6][6]=    
    {    
        {0,5,0,7,0,0},    
        {0,0,4,0,0,0},    
        {8,0,0,0,0,9},    
        {0,0,5,0,0,6},    
        {0,0,0,5,0,0},    
        {3,0,0,0,1,0}    
    };    
     ArrayToMat(A[0], 6, g1);  //取二維數組的起始地址作實參,用A[0],因其實質爲一維數組地址,與形參匹配    
    printf(" 有向圖g1的鄰接矩陣:\n");    
    DispMat(g1);    
    ArrayToList(A[0], 6, G1);    
    printf(" 有向圖G1的鄰接表:\n");    
    DispAdj(G1);    
    MatToList(g1,G2);    
    printf(" 圖g1的鄰接矩陣轉換成鄰接表G2:\n");    
    DispAdj(G2);    
    ListToMat(G1,g2);    
    printf(" 圖G1的鄰接錶轉換成鄰接鄰陣g2:\n");    
    DispMat(g2);    
    printf("\n");    
    return 0;    
}  

運行結果:



知識點總結

   定義圖的算法庫。
學習心得:
   圖在生活中方方面面有大的利用,比如電網、交通網、互聯網社交等等,使用鄰接矩陣實現圖的基本運算。



發佈了80 篇原創文章 · 獲贊 11 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章