數據結構 實驗五1) 采用鄰接矩陣/鄰接表建立圖(無向圖,有向圖,無向網絡,有向網絡); 2) 采用深度優先/廣度優先搜索方式遍歷圖;


實驗目的:

      1. 掌握圖的鄰接矩陣和鄰接表的存儲結構;

      2. 驗證圖在不同存儲結構下遍歷操作的實現。

      3. 掌握圖的實際應用

實驗內容:

采用鄰接矩陣/鄰接表建立圖無向圖,有向圖,無向網絡,有向網絡);   

采用深度優先/廣度優先搜索方式遍歷圖

 

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <LIMITS.H>

using namespace std;

#define Status int
#define VRType int
#define InfoType char
#define VertexType char

#define ERROR 0
#define OK 1
#define TRUE 1
#define FALSE 0

#define INFINITY 0 //最大值
#define MAX_VERTEX_NUM 20 //最大頂點個數


bool visited[MAX_VERTEX_NUM];//訪問標志數組

typedef struct ArcCell//鄰接矩陣(元素)類型
{
    VRType adj; //頂點關系(邊或弧),圖用1\0表示是否相鄰,網為權值
    InfoType *info; //邊或弧的相關信息指針
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct//圖的鄰接矩陣類型
{
    VertexType vexs[MAX_VERTEX_NUM]; //頂點向量
    AdjMatrix arcs; //鄰接矩陣
    int vexnum,arcnum; //圖的頂點數和邊或弧數
} Mgraph;

void (*VisitFunc)(Mgraph G,int v);//函數變量

void Input(InfoType *info)//錄入弧
{
    info=(char*)malloc(sizeof(char));
    scanf("%c",&*info);
}

Status LocateVex(Mgraph &G,VertexType u)//若G中存在點u,則返回該點在圖中的位置
{
    int Loc;
    for(Loc=0; Loc<G.vexnum; Loc++)
    {
        if(G.vexs[Loc]==u)
        {
            return Loc;
        }
    }
    return -1;
}

Status CreateDG(Mgraph &G)//采用鄰接矩陣表示法,構造有向圖G
{
    int IncInfo,i,j,k;
    char v1,v2;
    printf("請輸入圖的頂點數(1~20):\n");
    scanf("%d",&G.vexnum);
    getchar();
    printf("請輸入圖的弧數:\n");
    scanf("%d",&G.arcnum);
    getchar();
    printf("各弧是否含有其他信息(1(有),0(沒有)):\n");
    scanf("%d",&IncInfo);
    getchar();
    for(i=0; i<G.vexnum; i++)
    {
        printf("請輸入第%d個頂點:\n",i+1);
        scanf("%c",&G.vexs[i]);
        getchar();
    }
    for(i=0; i<G.vexnum; i++)
    {
        for(j=0; j<G.vexnum; j++)
        {
            G.arcs[i][j].adj=INFINITY;
            G.arcs[i][j].info=NULL;
        }
    }
    for(k=0; k<G.arcnum; k++)
    {
        printf("請輸入一條弧連接的頂點:\n");
        printf("弧尾頂點:\n");//輸入一條弧依附的頂點
        scanf("%c",&v1);
        getchar();
        printf("弧頭頂點:\n");
        scanf("%c",&v2);
        getchar();
        i=LocateVex(G,v1);
        j=LocateVex(G,v2);//確定v1和v2在G中的位置
        G.arcs[i][j].adj=1;//v1和v2的連接關系
        if(IncInfo)
        {
            Input(G.arcs[i][j].info);//若弧含有相關信息,則輸入
        }
    }
    return OK;
}//CreateDG

Status CreateDN(Mgraph &G)//采用鄰接矩陣表示法,構造有向網G
{
    int IncInfo,i,j,k,w;
    char v1,v2;
    printf("請輸入圖的頂點數(1~20):\n");
    scanf("%d",&G.vexnum);
    getchar();
    printf("請輸入圖的弧數:\n");
    scanf("%d",&G.arcnum);
    getchar();
    printf("各弧是否含有其他信息(1(有),0(沒有))\n");
    scanf("%d",&IncInfo);
    getchar();
    for(i=0; i<G.vexnum; ++i) //構造頂點向量
    {
        printf("請輸入第%d個頂點:",i+1);
        scanf("%c",&G.vexs[i]);
        getchar();
    }
    for(i=0; i<G.vexnum; ++i) //初始化鄰接矩陣
    {
        for(j=0; j<G.vexnum; ++j)
        {
            G.arcs[i][j].adj=INFINITY;
            G.arcs[i][j].info=NULL;
        }
    }
    for(k=0; k<G.arcnum; ++k) //構造鄰接矩陣
    {
        printf("請輸入一條弧連接的頂點及權值\n");
        printf("弧尾頂點:\n");//輸入一條弧連接的頂點及權值
        scanf("%c",&v1);
        getchar();
        printf("弧頭頂點:\n");
        scanf("%c",&v2);
        getchar();
        printf("權值:\n");
        scanf("%d",&w);
        getchar();
        i=LocateVex(G,v1);
        j=LocateVex(G,v2);//確定v1和v2在G中的位置
        G.arcs[i][j].adj=w;//弧<v1,v2>的權值
        if(IncInfo)
        {
            Input(G.arcs[i][j].info);//若弧含有相關信息,則輸入
        }
    }
    return OK;
}//CreateDN

Status CreateUDG(Mgraph &G)//采用鄰接矩陣表示法,構造無向圖G
{
    int IncInfo,i,j,k;
    char v1,v2;
    printf("請輸入圖的頂點數(1~20):\n");
    scanf("%d",&G.vexnum);
    getchar();
    printf("請輸入圖的弧數:\n");
    scanf("%d",&G.arcnum);
    getchar();
    printf("各弧是否含有其他信息(1(有),0(沒有))\n");
    scanf("%d",&IncInfo);
    getchar();
    for(i=0; i<G.vexnum; ++i) //構造頂點向量
    {
        printf("請輸入第%d個頂點:",i+1);
        scanf("%c",&G.vexs[i]);
        getchar();
    }
    for(i=0; i<G.vexnum; ++i) //初始化鄰接矩陣
    {
        for(j=0; j<G.vexnum; ++j)
        {
            G.arcs[i][j].adj=INFINITY;
            G.arcs[i][j].info=NULL;
        }
    }
    for(k=0; k<G.arcnum; ++k) //構造鄰接矩陣
    {
        printf("請輸入一條弧連接的頂點\n");
        printf("弧尾頂點:\n");//輸入一條弧依附的頂點
        scanf("%c",&v1);
        getchar();
        printf("弧頭頂點:\n");
        scanf("%c",&v2);
        getchar();
        i=LocateVex(G,v1);
        j=LocateVex(G,v2);//確定v1和v2在G中的位置
        G.arcs[i][j].adj=1;//v1和v2的連接關系
        if(IncInfo)
        {
            Input(G.arcs[i][j].info);//若弧含有相關信息,則輸入
        }
        G.arcs[j][i]=G.arcs[i][j];//置<v1,v2>的對稱弧<v2,v1>
    }
    return OK;
}//CreateUDG

Status CreateUDN(Mgraph &G)//采用鄰接矩陣表示法,構造無向網G
{
    int IncInfo,i,j,k,w;
    char v1,v2;
    printf("請輸入圖的頂點數(1~20):\n");
    scanf("%d",&G.vexnum);
    getchar();
    printf("請輸入圖的弧數:\n");
    scanf("%d",&G.arcnum);
    getchar();
    printf("各弧是否含有其他信息(1(有),0(沒有)):\n");
    scanf("%d",&IncInfo);
    getchar();
    for(i=0; i<G.vexnum; ++i)
    {
        printf("請輸入第%d個頂點:",i+1);
        scanf("%c",&G.vexs[i]);
        getchar();
    }//構造頂點向量
    for(i=0; i<G.vexnum; ++i)
    {
        for(j=0; j<G.vexnum; ++j)
        {
            G.arcs[i][j].adj=INFINITY;
            G.arcs[i][j].info=NULL;
        }
    }//初始化鄰接矩陣
    for(k=0; k<G.arcnum; ++k) //構造鄰接矩陣
    {
        printf("請輸入一條弧連接的頂點及權值\n");
        printf("弧尾頂點:\n");//輸入一條弧連接的頂點及權值
        scanf("%c",&v1);
        getchar();
        printf("弧頭頂點:\n");
        scanf("%c",&v2);
        getchar();
        printf("權值:\n");
        scanf("%d",&w);
        getchar();
        i=LocateVex(G,v1);
        j=LocateVex(G,v2);//確定v1和v2在G中的位置
        G.arcs[i][j].adj=w;//弧<v1,v2>的權值
        if(IncInfo)
        {
            Input(G.arcs[i][j].info);//若弧含有相關信息,則輸入
        }
        G.arcs[j][i]=G.arcs[i][j];//置<v1,v2>的對稱弧<v2,v1>
    }
    return OK;
}//CreateUDN


Status FirstAdjVex(Mgraph G,int v)//返回v的第一個鄰接頂點
{
    int i;
    if(v>=0&&v<G.vexnum)
    {
        for(i=0; i<G.vexnum; i++)
        {
            if(G.arcs[v][i].adj)
            {
                return i;
            }
        }
    }
    return -1;
}//FirstAdjVex

Status NextAdjVex(Mgraph G,int v,int w)//返回v的(相對於w的)下一個鄰接頂點
{
    int i;
    if(v>=0 && v<G.vexnum)
    {
        if(w>=0 && w<G.vexnum)
        {
            for(i=w+1; i<G.vexnum; i++)
            {
                if(G.arcs[v][i].adj)
                {
                    return i;
                }
            }
        }
    }
    return -1;
}//NextAdjVex

void Print_JZ(Mgraph G)//打印矩陣
{
    int i,j;
    for(i=0; i<G.vexnum; i++)
    {
        for(j=0; j<G.vexnum; j++)
        {
            printf("%d ",G.arcs[i][j].adj);
        }
        printf("\n");
    }
}

void Print(Mgraph G,int v)
{
    printf("%c",G.vexs[v]);
}

void DFS(Mgraph G,int v)
{
    //從第v個頂點出發遞歸地深度優先遍歷圖G
    int w;
    visited[v]=TRUE;
    VisitFunc(G,v);//訪問第v個頂點
    for(w=FirstAdjVex(G,v); w>0; w=NextAdjVex(G,v,w))
    {
        if(!visited[w])
        {
            DFS(G,w);//對v的尚未訪問的鄰接頂點w遞歸調用DFS
        }
    }
}//DFS

void DFSTraverse(Mgraph G,void (*Print)(Mgraph G,int v))
{
    //對圖G做深度優先遍歷
    int v;
    VisitFunc=Print;//使用全局變量VisitFunc,使DFS不必設函數指針參數
    for(v=0; v<G.vexnum; ++v)
    {
        visited[v]=FALSE;//訪問標志數組初始化
    }
    for(v=0; v<G.vexnum; ++v)
    {
        if(!visited[v])
        {
            DFS(G,v);//對尚未訪問的頂點調用DFS
        }
    }
}//DFSTraverse

int main()
{
    char Ch;
    Mgraph G;
    while(1)
    {
        system("cls");
        printf("請選擇操作:\n");
        printf("1.構造有向圖\n2.構造有向網\n3.構造無向圖\n4.構造無向網\n5.退出\n");
        scanf("%c",&Ch);
        getchar();
        switch(Ch)
        {
        case '1':
            CreateDG(G);//構造有向圖G
            printf("有向圖G的鄰接矩陣為:\n");
            Print_JZ(G);
            printf("有向圖G的深度優先遍歷:\n");
            DFSTraverse(G,Print);
            getchar();
            system("pause");
            break;
        case '2':
            CreateDN(G);//構造有向網G
            printf("有向網G的鄰接矩陣為:\n");
            Print_JZ(G);
            printf("有向網G的深度優先遍歷:\n");
            DFSTraverse(G,Print);
            getchar();
            system("pause");
            break;
        case '3':
            CreateUDG(G);//構造無向圖G
            printf("無向圖G的鄰接矩陣為:\n");
            Print_JZ(G);
            printf("無向圖G的深度優先遍歷:\n");
            DFSTraverse(G,Print);
            getchar();
            system("pause");
            break;
        case '4':
            CreateUDN(G);//構造無向網G
            printf("無向網G的鄰接矩陣為:\n");
            Print_JZ(G);
            printf("無向網G的深度優先遍歷:\n");
            DFSTraverse(G,Print);
            getchar();
            system("pause");
            break;
        case '5':
            exit(0);
            break;
        default:
            printf("選擇錯誤!\n");
            system("pause");
        }
        return 0;
    }
}


運行效果如圖:

使用了鄰接矩陣和深度優先算法


免責聲明!

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



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