数据结构实验8.1:图的基本操作

#王者杯·14天创作挑战营·第1期#


一,实验目的

1.掌握图的邻接矩阵、邻接表的表示方法及建立算法;
2.掌握图的深度优先遍历、广度优先遍历等基本操作的算法;
3.掌握图的最小生成树、关键路径等应用问题的求解算法;
4.进一步加深对图的几种基本应用算法的理解,逐步培养解决实际问题的编程能力。

二,实验内容

已知无向连通图G如下图所示。完成图的下列基本操作:
(1)建立图的邻接矩阵,输出邻接矩阵;
(2)建立图的邻接表,输出邻接表;
(3)求邻接表表示的图的深度优先遍历序列;
(4)求邻接矩阵表示的图的深度优先遍历序列;
(5)求邻接表表示的图的广度优先遍历序列;
(6)求邻接矩阵表示的图的广度优先遍历序列。
在这里插入图片描述

三,实验要求

(1)建立头文件graph.h,其中定义了图的邻接矩阵和邻接表表示的存储结构,本实验的其它实验题目也可共享使用,其代码如下:

#define MAXV 30      			// 最大顶点数
typedef int InfoType;
//以下定义图的邻接矩阵数据结构
typedef struct {					//定义图的顶点结构
	int no;						//顶点编号
	InfoType info;					//顶点其它信息,可用于
} VertexType;
typedef struct {					//定义图邻接矩阵
	VertexType vexs[MAXV];		//顶点向量
	int arcs[MAXV][MAXV];		//邻接矩阵
	int vexnum, arcnum;			//图的当前顶点数和边数
} MGraph;
//以下定义图的邻接表数据结构
typedef struct ArcNode {			//定义表结点类型
	int  adjvex;					//顶点序号
	int  weight;					//边或弧的权值
	struct ArcNode *nextarc;		//指向下一个表结点的指针
} ArcNode;
typedef struct VNode {				//定义头结点类型
	VertexType data;
	ArcNode *firstarc;
} VNode
//typedef  VNode  AdjList[MAXV];	//定义头结点数组
typedef struct {					//定义图的邻接表类型
	VNode  vertices[MAXV];
	int  vexnum, arcnum;
} LGraph;

(2)完善参考程序,在程序中的下划线处填写适当的语句。
(3)设计测试数据,调试、测试完善后的参考程序,保存和打印测试结果,对结果进行分析。

四,算法分析

(1)深度优先搜索遍历算法
从图中某顶点v出发:
① 访问顶点v;
② 依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
③ 若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

(2)广度优先搜索遍历算法
从图中某顶点vi出发:
① 访问顶点vi ;
② 访问vi 的所有未被访问的邻接点w1 ,w2 , …wk ;
③ 依次从这些邻接点(在步骤②中访问的顶点)出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问;
④ 若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行广度优先搜索遍历,直到图中所有顶点均被访问过为止。
为实现③,需要保存在步骤②中访问的顶点,而且访问这些顶点的邻接点的顺序为:先保存的顶点,其邻接点先被访问。

五,示例代码

8-1.cpp源码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include "graph.h"

// 访问标志数组
int visited[MAXV];
// 广度优先遍历存储队列
int queue[MAXV];

// 建立图的邻接矩阵
void CreatMG(MGraph& mg) {
    int i, j;
    int A[7][7];
    mg.vexnum = 7;
    mg.arcnum = 9;
    for (i = 0; i < mg.vexnum; i++) {
        for (j = 0; j < mg.vexnum; j++) {
            A[i][j] = 0;
        }
    }
    A[0][1] = A[0][2] = A[0][6] = 1;
    A[1][3] = 1;
    A[2][3] = A[2][5] = A[2][6] = 1;
    A[3][4] = 1;
    A[5][6] = 1;
    for (i = 1; i < mg.vexnum; i++) {
        for (j = 0; j < i; j++) {
            A[i][j] = A[j][i];
        }
    }
    for (i = 0; i < mg.vexnum; i++) {
        for (j = 0; j < mg.vexnum; j++) {
            mg.arcs[i][j] = A[i][j];
        }
    }
}

// 由图的邻接矩阵创建图的邻接表
void CreatLG(LGraph*& lg, MGraph mg) {
    int i, j;
    ArcNode* p;
    lg = (LGraph*)malloc(sizeof(LGraph));
    for (i = 0; i < mg.vexnum; i++) {
        lg->vertices[i].firstarc = NULL;
    }
    for (i = 0; i < mg.vexnum; i++) {
        for (j = mg.vexnum - 1; j >= 0; j--) {
            if (mg.arcs[i][j] != 0) {
                p = (ArcNode*)malloc(sizeof(ArcNode));
                p->adjvex = j;
                p->weight = mg.arcs[i][j];
                p->nextarc = lg->vertices[i].firstarc;
                lg->vertices[i].firstarc = p;
            }
        }
    }
    lg->vexnum = mg.vexnum;
    lg->arcnum = mg.arcnum;
}

// 输出图的邻接矩阵
void OutputMG(MGraph mg) {
    int i, j;
    for (i = 0; i < mg.vexnum; i++) {
        for (j = 0; j < mg.vexnum; j++) {
            printf("%3d", mg.arcs[i][j]);
        }
        printf("\n");
    }
}

// 输出图的邻接表
void OutputLG(LGraph* lg) {
    int i;
    ArcNode* p;
    for (i = 0; i < lg->vexnum; i++) {
        p = lg->vertices[i].firstarc;
        if (p) {
            printf("%3d:", i);
        }
        while (p) {
            printf("%3d", p->adjvex);
            p = p->nextarc;
        }
        printf("\n");
    }
}

// 邻接表表示的图的递归深度优先遍历
void LDFS(LGraph* lg, int i) {
    ArcNode* p;
    printf("%3d", i);
    visited[i] = 1;
    p = lg->vertices[i].firstarc;
    while (p) {
        if (visited[p->adjvex] == 0) {
            LDFS(lg, p->adjvex);
        }
        p = p->nextarc;
    }
}

// 邻接矩阵表示的图的递归深度优先遍历
void MDFS(MGraph mg, int i) {
    int j;
    printf("%3d", i);
    visited[i] = 1;
    for (j = 0; j < mg.vexnum; j++) {
        if (mg.arcs[i][j] != 0 && visited[j] == 0) {
            MDFS(mg, j);
        }
    }
}

// 邻接表表示的图的广度优先遍历
void LBFS(LGraph* lg, int s) {
    int i, v, w, front, rear;
    ArcNode* p;
    for (i = 0; i < lg->vexnum; i++) {
        visited[i] = 0;
    }
    front = rear = 0;
    printf("%3d", s);
    visited[s] = 1;
    queue[rear++] = s;
    while (front < rear) {
        v = queue[front++];
        for (p = lg->vertices[v].firstarc; p != NULL; p = p->nextarc) {
            w = p->adjvex;
            if (visited[w] == 0) {
                printf("%3d", w);
                visited[w] = 1;
                queue[rear++] = w;
            }
        }
    }
}

// 邻接矩阵表示的图的广度优先遍历
void MBFS(MGraph mg, int s) {
    int i, j, v, front, rear;
    for (i = 0; i < mg.vexnum; i++) {
        visited[i] = 0;
    }
    front = rear = 0;
    printf("%3d", s);
    visited[s] = 1;
    queue[rear++] = s;
    while (front < rear) {
        v = queue[front++];
        for (i = 0; i < mg.vexnum; i++) {
            for (j = 0; j < mg.vexnum; j++) {
                if (mg.arcs[v][j] != 0 && visited[j] == 0) {
                    printf("%3d", j);
                    visited[j] = 1;
                    queue[rear++] = j;
                }
            }
        }
    }
}

int main() {
    LGraph* lg;
    MGraph mg;
    int i;
    CreatMG(mg);
    CreatLG(lg, mg);
    printf("(1)当前图的邻接矩阵是:\n");
    OutputMG(mg);
    printf("(2)当前图的邻接表是:\n");
    OutputLG(lg);
    for (i = 0; i < mg.vexnum; i++) {
        visited[i] = 0;
    }
    getchar();
    printf("(3)邻接表表示的图的深度优先遍历序列是:");
    LDFS(lg, 0);
    getchar();
    for (i = 0; i < mg.vexnum; i++) {
        visited[i] = 0;
    }
    printf("(4)邻接矩阵表示的图的深度优先遍历序列是:");
    MDFS(mg, 0);
    getchar();
    printf("(5)邻接表表示的图的广度优先遍历序列是:");
    LBFS(lg, 0);
    getchar();
    printf("(6)邻接矩阵表示的图的广度优先遍历序列是:");
    MBFS(mg, 0);
    printf("\n");
    return 0;
}

graph.h源码

#pragma once
#ifndef GRAPH_H
#define GRAPH_H

// 定义图的最大顶点数
const int MAXV = 100;

// 定义弧节点结构体
typedef struct ArcNode {
    int adjvex;
    int weight;
    struct ArcNode* nextarc;
} ArcNode;

// 定义顶点结构体
typedef struct VNode {
    ArcNode* firstarc;
} VNode;

// 定义邻接表结构体
typedef struct {
    VNode vertices[MAXV];
    int vexnum, arcnum;
} LGraph;

// 定义邻接矩阵结构体
typedef struct {
    int arcs[MAXV][MAXV];
    int vexnum, arcnum;
} MGraph;

#endif    

六,操作步骤

1,双击Visual Studio程序快捷图标,启动程序。
在这里插入图片描述

2,之前创建过项目的话,直接打开即可,这里选择【创建新项目】。
在这里插入图片描述

3,单击选择【空项目】——单击【下一步】按钮。
在这里插入图片描述

4,编辑好项目的名称和存放路径,然后单击【创建】按钮。
在这里插入图片描述

5,创建C++程序文件,右击【源文件】——选择【添加】——【新建项】。
在这里插入图片描述
6,输入项目名称8-1.cpp,单击【添加】按钮。
在这里插入图片描述

7,输入项目名称graph.h,单击【添加】按钮,此文件要定义 MGraph、LGraph、ArcNode 等类型,同时定义 MAXV 常量。
在这里插入图片描述

8,编写代码,单击运行按钮,运行程序。
在这里插入图片描述

七,运行结果

1,实验要求的测试结构。
在这里插入图片描述

2,编写代码运行后的结果。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梁辰兴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值