算法与数据结构:图的建立遍历及其应用

Posted 咳咳n

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法与数据结构:图的建立遍历及其应用相关的知识,希望对你有一定的参考价值。

设图结点的元素类型为char,建立一个不少于8个顶点的带权无向图G,实现以下图的各种基本操作的程序:
① 用邻接矩阵作为储结构存储图G并输出该邻接矩阵;
② 用邻接链表作为储结构存储图G并输出该邻接链表;
③ 按DFS算法输出图G中顶点的遍历序列;
④ 按BFS算法输出图G中顶点的遍历序列;
⑤ 用Prime算法从某个指定的顶点出发(或者Kruskal算法)输出图G的最小生成树;(要求把最小生成树的各条边输出成A-B,B-C或者(A,B,weight)的形式)
⑥ 求从有向图的某个节点出发到其余各顶点的最短路径和最短路径值;(带权有向图)
⑦ 用狄克斯特拉(Dijkastra)算法或者Floyd算法求每对顶点之间的最短路径;(带权有向图,选做)
⑧ 主函数通过函数调用实现以上各项操作。

//GraphLab.cpp

#pragma once
#include <stdio.h>
#include <stdlib.h>
typedef char GDataType;
#include "MatrixGraphCreate.h"
#include "MGraphTraverse.h"
#include "TableGraphCreate.h"
#include "Prime.h"

void printMatrix(MGraph G);//打印邻接矩阵
void printLTable(LGraph G);//打印邻接表

int main() 
    int n = 0, e = 0, i = 0;
    //从文件读取数据
    FILE *fp = fopen("data.txt", "r");
    if (!fp) 
        printf("文件打开失败\\n");
        exit(0);
    

    fscanf(fp, "%d %d ", &n, &e); //n是顶点个数,e是边数
    GDataType mv[n], lv[n];
    for (i = 0; i < n; i++) 
        fscanf(fp, "%c", &mv[i]);
        lv[i] = mv[i];
    
    i = 0;
    MRowColWeight mRCW[e];//定义边
    LRowColWeight lRCM[e];//定义边
    while (i < e) 
        fscanf(fp, "%d %d %d", &mRCW[i].row, &mRCW[i].col, &mRCW[i].weight);
        lRCM[i].row = mRCW[i].row;
        lRCM[i].col = mRCW[i].col;
        lRCM[i].weight = mRCW[i].weight;
        i++;
    
    fclose(fp);

    MGraph G1;
    LGraph G2;
    //邻接矩阵创建无向图,并输出邻接矩阵
    CreatGraph(&G1, mv, n, mRCW, e);
    printMatrix(G1);

    //邻接表创建无向图,并输出邻接表
    CreateDbLGraph(&G2, lv, n, lRCM, e);
    printLTable(G2);

    //按DFS算法输出图G中顶点的遍历序列
    printf("\\n按DFS算法输出图G中顶点的遍历序列:\\n");
    int visitDFS[MaxVer];
    DFS(G1, 0, visitDFS);

    //按BFS算法输出图G中顶点的遍历序列
    printf("\\n按BFS算法输出图G中顶点的遍历序列:\\n");
    int visitBFS[MaxVer];
    BFS(G1, 0, visitBFS);

    //Prime生成最小生成树
    printf("\\n\\n用Prime算法从顶点A出发生成最小生成树:\\n");
    Prim(G1, 0);
    return 0;


//打印邻接矩阵
void printMatrix(MGraph G) 
    int i, j;
    printf("顶点集合为:\\n");
    for (i = 0; i < G.Vertices.size; i++)
        printf("%c  ", G.Vertices.list[i]);
    printf("\\n");
    printf("\\n输出邻接矩阵:\\n");
    for (i = 0; i < G.Vertices.size; i++) 
        for (j = 0; j < G.Vertices.size; j++)
            printf("%5d   ", G.edge[i][j]);
        printf("\\n");
    


//打印邻接表
void printLTable(LGraph G) 
    int i, j;
    printf("\\n顶点集合为:\\n");
    for (i = 0; i < G.numOfVer; i++)
        printf("%c  ", G.a[i].data);
    printf("\\n\\n输出邻接表:\\n");
    i = 0;
    while (i < G.numOfVer) 
        Edge *p = G.a[i].adj;
        while (p) 
            printf(" %c--%d--%c ", G.a[i].data, p->weight, G.a[p->dest].data);
            p = p->next->next;
        
        printf("\\n");
        i++;
    


//DirectedGraph.cpp

#pragma once
#include <stdio.h>
#include <stdlib.h>
typedef char GDataType;
#include "MatrixGraphCreate.h"
#include "ShortestPathDjk.h"

//求从有向图的某个节点出发到其余各顶点的最短路径和最短路径值
void ShortestToOtherVer(MGraph G, int v0);
void printMatrix(MGraph G);//打印出邻接矩阵

int main() 
    int n = 0, e = 0, i = 0;

    FILE *fp = fopen("dataDirect.txt", "r");
    if (!fp) 
        printf("文件打开失败\\n");
        exit(0);
    

    fscanf(fp, "%d %d ", &n, &e); //n是顶点个数,e是边数
    GDataType mv[n];
    for (i = 0; i < n; i++) 
        fscanf(fp, "%c", &mv[i]);
    
    i = 0;
    MRowColWeight mRCW[e];//定义边
    while (i < e) 
        fscanf(fp, "%d %d %d", &mRCW[i].row, &mRCW[i].col, &mRCW[i].weight);
        i++;
    
    fclose(fp);
    MGraph G;
    CreatGraph(&G, mv, n, mRCW, e);//构造带权有向图
    printMatrix(G);//打印出邻接矩阵

    //求从有向图的某个节点出发到其余各顶点的最短路径和最短路径值
    ShortestToOtherVer(G, 0);

    return 0;


void ShortestToOtherVer(MGraph G, int v0) 
    int i, distance[MaxVer], path[MaxVer];
    ShortestPathDjk(G, v0, distance, path);
    printf("\\n从顶点%c到其他顶点的最短距离为:\\n", G.Vertices.list[v0]);
    for (i = 1; i < G.Vertices.size; i++) 
        printf("%c->%c: 最短路径值 = %-6d", G.Vertices.list[v0], G.Vertices.list[i], distance[i]);
        DisplayPath(G, v0, i, path);
        printf("%c\\n", G.Vertices.list[i]);
    


//打印邻接矩阵
void printMatrix(MGraph G) 
    int i, j;
    printf("顶点集合为:\\n");
    for (i = 0; i < G.Vertices.size; i++)
        printf("%c  ", G.Vertices.list[i]);
    printf("\\n");
    printf("\\n输出邻接矩阵:\\n");
    for (i = 0; i < G.Vertices.size; i++) 
        for (j = 0; j < G.Vertices.size; j++)
            printf("%5d   ", G.edge[i][j]);
        printf("\\n");
    


//MatrixGraphCreate.h

#include "SeqList.h"
typedef char GDataType;

#define INF 65535 //表示无穷大
#define MaxVer 100   //最大顶点
typedef struct 
    SeqList Vertices;   //存放顶点
    int edge[MaxVer][MaxVer];
    int numOfEdges;     //边数
 MGraph;

//初始化
void InitGraph(MGraph *G, int n) 
    int i, j;
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++) 
            if (i == j)G->edge[i][j] = 0;    //自己到自己权值都初始化为0
            else G->edge[i][j] = INF;        //所有顶点是断开的状态
        
    G->numOfEdges = 0;
    ListInit(&G->Vertices);         //顺序表存放顶点


//插入顶点(图中增加一个顶点)
void InsertVer(MGraph *G, GDataType vertex) 
    ListInsert(&G->Vertices, G->Vertices.size, vertex);//在表结尾插入


//插入边(插入一条有向边<v1, v2>)
void InsertEdge(MGraph *G, int v1, int v2, int weight) 
    if (v1 < 0 || v2 < 0 || v1 >= G->Vertices.size || v2 >= G->Vertices.size) 
        printf("参数出错\\n");
        return;
    
    G->edge[v1][v2] = weight;
    G->numOfEdges++;


//取第一个邻接点
int GetFirstVer(MGraph G, int v) 
    int col;
    if (v < 0 || v > G.Vertices.size) 
        printf("v越界出错\\n");
        return -1;
    
    for (col = 0; col < G.Vertices.size; col++)
        if (G.edge[v][col] > 0 && G.edge[v][col] < INF)return col;
    return -1;


//取下一个邻接顶点
int GetNextVer(MGraph G, int v1, int v2) 
    int col;
    if (v1 < 0 || v2 < 0 || v1 >= G.Vertices.size || v2 >= G.Vertices.size) 
        printf("参数越界出错\\n");
        return -1;
    
    for (col = v2 + 1; col < G.Vertices.size; col++)
        if (G.edge[v1][col] > 0 && G.edge[v1][col] < INF) return col;
    return -1;


typedef struct 
    int row;    //行下标
    int col;    //列下标
    int weight; //权值
 MRowColWeight; //边信息结构体

//创建图,在图G中插入n个顶点信息V和e条边信息E
void CreatGraph(MGraph *G, GDataType V[], int n, MRowColWeight E[], int e) 
    int i, j;
    InitGraph(G, n);
    for (i = 0; i < n; i++)
        InsertVer(G, V[i]);      //插入顶点
    for (j = 0; j < e; j++)
        InsertEdge(G, E[j].row, E[j].col, E[j].weight);    //插入边


//SeqList.h

#define Maxsize 100
typedef char LDataType;

//线性表——顺序表
typedef struct 
    LDataType list[Maxsize];
    int size;
 SeqList;

//初始化
void ListInit(SeqList *L) 
    L->size = 0;


//插入数据元素
int ListInsert(SeqList *L, int i, LDataType x) 
    int j;
    if (L->size >= Maxsize) 
        printf("顺序表已满,无法插入\\n");
        return 0;
     else 
        for (j = L->size - 1; j > i; j--)
            L->list[j] = L->list[j - 1];
        L->list[i] = x;
        L->size++;
        return 1;
    


//TableGraphCreate.h

#include <malloc.h>
#define INF 65535;
typedef char GDataType;
#define MaxVerSize 100

//邻接边结构体
typedef struct GNode 
    int dest;           //邻接边的头顶点序号
    struct GNode *next; //单链表的下一个结点指针
    int weight;         //权值
 Edge;

typedef struct 
    GDataType data;     //顶点数据
    int order;          //顶点在数组中存放的序号
    Edge *adj;          //邻接边头指针
 VHeadNode;

typedef struct 
    VHeadNode a[MaxVerSize];//邻接表数组
    int numOfVer;           //顶点个数
    int numOfEdges;         //边数
 LGraph;

//初始化
void InitLGraph(LGraph *G) 
    G->numOfEdges = 0;
    G->numOfVer = 0;
    for (int i = 0; i < MaxVerSize; i++) 
        G->a[i].order = i;  //初始化各个顶点序号
        G->a[i].adj = NULL;
    


//插入顶点
void InsertLVer(LGraph *G, int i, GDataType ver) //第i个位置插入
    if (i >= 0 && i < MaxVerSize) 
        G->a[i].data = ver;
        G->numOfVer++;
     else printf("顶点位置越界\\n");


//插入边<v1, v2>
void InsertLEdge(LGraph *G, int v1, int v2, int weight) 
    Edge 以上是关于算法与数据结构:图的建立遍历及其应用的主要内容,如果未能解决你的问题,请参考以下文章

图的表示深度广度遍历算法及其应用

图的遍历广度优先遍历(DFS)深度优先遍历(BFS)及其应用

数据结构实验报告-实验四 图的构造与遍历

算法与数据结构:树型数据结构及其应用

算法与数据结构:树型数据结构及其应用

图的各类算法实现