西南交通大学【算法分析与设计实验1】

news2024/10/7 20:29:03

实验1.4 有向图拓扑排序

实验目的

(1)掌握算法的自然语言描述法,流程图绘制方法以及伪代码描述方法。

(2)理解算法的执行过程。

(3)掌握算法的编程实现方法、调试方法及测试方法。

实验任务

按照实验教程上图1-6的伪代码,实现基于深度优先(DFS)的有向图拓扑排序算法。具体要求如下:

(1)阅读并理解该伪代码。

(2)根据测试用例,分析该算法的执行过程。

(3)用C++语言实现该算法,并针对测试用例,将程序运行结果和手工分析结果进行对比验证。

(4)撰写实验报告,实验报告内容包括实验目的、实验任务、实验环境、实验步骤、实验结果和实验总结等部分。

实验步骤及结果

 实验预习

根据测试用例分析算法的执行过程

(1)测试用例1

从顶点1开始,按照字典序进行DFS,给出每一步TS-Visit的中间结果。

初始状态

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

False

False

False

False

False

Visited

False

False

False

False

False

δ

0

0

0

0

0

第1次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

False

False

False

False

False

Visited

False

False

False

False

False

δ

0

0

0

0

0

第2次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

True

False

False

False

False

Visited

False

False

False

False

False

δ

0

0

0

0

0

第3次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

True

True

False

False

False

Visited

False

False

False

False

False

δ

0

0

0

0

0

第4次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

True

True

False

True

False

Visited

False

False

False

False

False

δ

0

0

0

0

0

返回第4次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

True

True

False

True

False

Visited

False

False

False

False

True

δ

0

0

0

0

5

返回第3次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

True

True

False

False

False

Visited

False

False

False

True

True

δ

0

0

0

4

5

第5次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

True

True

False

False

False

Visited

False

False

False

True

True

δ

0

0

0

4

5

返回第5次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

True

True

False

False

False

Visited

False

False

False

True

True

δ

0

0

0

4

5

返回第2次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

True

False

False

False

False

Visited

False

True

False

True

True

δ

0

3

0

4

5

返回第1次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

False

False

False

False

False

Visited

True

True

False

True

True

δ

2

3

0

4

5

第6次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

False

False

False

False

False

Visited

True

True

False

True

True

δ

2

3

0

4

5

第7次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

False

False

True

False

False

Visited

True

True

False

True

True

δ

2

3

0

4

5

返回第7次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

False

False

True

False

False

Visited

True

True

False

True

True

δ

2

3

0

4

5

返回第6次调用TS-Visit

顶点1

顶点2

顶点3

顶点4

顶点5

Stacked

False

False

False

False

False

Visited

True

True

True

True

True

δ

2

3

1

4

5

最终的拓扑排序结果:

3 1 2 4 5

(2)测试用例2

最终的拓扑排序结果:

6 1 4 3 5 2

伪代码中 if v is marked stacked 如果为真,表示什么意思?

答:正常程序不会出现if v is marked stacked为真的情况,伪代码中 if v is marked stacked 如果为真表示此图中出现了环。

用C/C++语言实现该算法

算法要求的输入格式为:

第一行是两个整数 n m,分别表示图的顶点数和边数,顶点从 1 到 n编号;其后有 m 行,每行两个整数,分别表示每条有向边的起始顶点和结束顶点。

例:测试用例 1 对应的输入如下:

5 5

1 2

2 4

2 5

3 4

4 5

算法要求的输出格式为:

按照拓扑排序排好的顶点编号,编号之间用一个空格分割。

源代码:

#include <iostream>
#define MAX_VERTEX_N 20 // 最大节点数+1
using namespace std;
// 判断是否有环
int flag = 0;
// 图的类型
typedef enum
{
    DG, // 有向图
    DN, // 有向网
    UDG, // 无向图
    UDN // 无向网
}GraphKind;
// 边节点
typedef struct ArcNode
{
    int adjvex; // 数据域
    struct ArcNode *nextarc; // 下一个邻接点
}ArcNode;
// 节点
typedef struct
{
    int data; // 数据域
    ArcNode *firstarc; // 第一个邻接点
}VNode, AdjList[MAX_VERTEX_N];
// 图
typedef struct
{
    AdjList vexs; // 节点数组
    int vex_num; // 节点数
    int arc_num; // 弧数
    GraphKind kind; // 图类型
} ALGraph;
// 输入数据创建邻接表
void CreateUDN(ALGraph &G)
{
    // 节点个数 弧个数
    int v_num, a_num;
    cin>>v_num>>a_num;
    G.vex_num = v_num;
    G.arc_num = a_num;
    // 初始化图的邻接表的点数组
    for(int i = 1;i <= v_num;++i){
        G.vexs[i].data = i;
        G.vexs[i].firstarc = NULL;
    }
    for(int i = 0;i < a_num;++i){
        // 起始节点 终止节点
        int v1, v2;
        // 定位点邻接的最后一个点节点
        ArcNode *end;
        cin>>v1>>v2;
        ArcNode *temp = new ArcNode;
        temp->adjvex = v2;
        temp->nextarc = NULL;
        end = G.vexs[v1].firstarc;
        // 如果v1还没有邻接点
        if(!end){
            G.vexs[v1].firstarc = temp;
        }else{// 在最后继续邻接
            while (end->nextarc)
            {
                end = end->nextarc;
            }
            end->nextarc = temp;
        }
    }
}
// 访问各个节点
void visit(ALGraph G, int index, int *judge, int *res, int &i){
    // 如果是状态1,则返回
    if(judge[index] == 1){
        flag = 1;
        return;
    }
    // 如果是状态0即未访问
    if(judge[index] == 0){
        judge[index] = 1;
        ArcNode *temp = G.vexs[index].firstarc;
        // 深度搜索
        while (temp)
        {
            visit(G, temp->adjvex, judge, res, i);
            temp = temp->nextarc;
        }
        // 改为已访问状态
        judge[index] = 2;
        // 将节点下标存储在结果数组res中
        res[i] = index;
        i--;
    }
}
// 拓扑排序
void TopologicalSort(ALGraph G){
    int i = G.vex_num;
    int *judge = new int[G.vex_num+1];
    int *res = new int[G.vex_num+1];
    // 初始化判断数组
    for(int j = 1;j <= G.vex_num;++j){
        judge[j] = 0;
    }
    // 从一个未访问节点出发
    for(int j = 1;j <= G.vex_num;++j){
        if(judge[j] == 0){
            visit(G, j, judge, res, i);
        }
    }
    // 输出结果
    if(flag){
        cout<<"此图有环,没有拓扑排序"<<endl;
    }else{
        for(int j = 1;j <= G.vex_num;++j){
            cout<<G.vexs[res[j]].data<<" ";
        }
    }
    delete judge;
    delete res;
}
// 释放创建图时动态申请的内存
void des(ALGraph &G)
{
    for (int i = 1; i <= G.vex_num; ++i)
    {
        ArcNode *p = G.vexs[i].firstarc;
        ArcNode *q = NULL;
        while (p)
        {
            q = p->nextarc;
            delete p;
            p = q;
        }
    }
}
int main(void)
{
    ALGraph G;
    // 创建图
    CreateUDN(G);
    // 进行拓扑排序
    TopologicalSort(G);
    cout<<endl;
    // 释放内存
    des(G);
    system("pause");
    return 0;
}

上机实验

测试用例1

测试用例输入:

9 9

1 2

1 8

2 3

2 8

3 4

5 3

5 6

6 4

7 8

测试用例示意图:

手工计算结果:

9 7 5 6 1 2 8 3 4

程序运行结果:

测试用例2

测试用例输入:

10 12

1 3

1 6

2 4

3 4

3 5

4 7

5 8

6 5

6 8

7 9

8 9

9 10

测试用例示意图:

手工计算结果:

2 1 6 3 5 8 4 7 9 10

程序运行结果:

单步调试截图

实验总结

通过本次实验,掌握了如何去阅读和理解算法的伪代码表示方法以及基于算法的伪代码实现算法程序。熟悉了程序的调试过程,并学会了如何分析算法的执行过程以及验证算法及程序的正确性。为后续算法的学习以及应用奠定了一定的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1886838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JSON JOLT常用示例整理

JSON JOLT常用示例整理 1、什么是jolt Jolt是用Java编写的JSON到JSON转换库&#xff0c;其中指示如何转换的"specification"本身就是一个JSON文档。以下文档中&#xff0c;我统一以 Spec 代替如何转换的"specification"json文档。以LHS(left hand side)代…

【AIGC X UML 落地】从UML语句到UML图形的生成,来看Agent插件的制作

上篇我们讲到如何通过多智能体实现自然语言绘制UML图。 没有看过的,可以去看下原文:《【AIGC X UML 落地】通过多智能体实现自然语言绘制UML图》 其中有一个实现重点,就是如何将 PlantUML 语句生成 UML 图片。在这里笔者是通过自定义 Agent 插件来实现这一流程。 本文,就此…

disql使用

进入bin目录&#xff1a;cd /opt/dmdbms/bin 启动disql&#xff1a;./disql&#xff0c;然后输入用户名、密码 sh文件直接使用disql&#xff1a; 临时添加路径到PATH环境变量&#xff1a;在当前会话中临时使用disql命令而无需每次都写完整路径&#xff0c;可以在执行脚本之前…

在非 antd pro 项目中使用 umi OpenAPI

大家好&#xff0c;我是松柏。自从跟着鱼皮哥使用了ant design pro中的OpenAPI插件之后&#xff0c;我已经无法忍受自己写请求后端接口的方法了&#xff0c;所以这篇文章记录一下如何在非ant design pro项目中使用OpenAPI。 安装依赖 首先我们需要安装包umijs/openapi&#x…

02归并排序——分治递归

02_归并排序_——分治_递归_ #include <stdio.h>void merge(int arr[], int l, int m, int r) {int n1 m -l 1;int n2 r -m;//创建临时数组int L[n1], R[n2];for(int i 0; i < n1; i){L[i] arr[l i];}for(int j 0; j < n2; j){R[j] arr[m 1 j];}int i …

STM32 ADC精度提升方法

STM32 ADC精度提升方法 Fang XS.1452512966qq.com如果有错误&#xff0c;希望被指出&#xff0c;学习技术的路难免会磕磕绊绊量的积累引起质的变化 硬件方法 优化布局布线&#xff0c;尽量减小其他干扰增加电源、Vref去耦电容使用低通滤波器&#xff0c;或加磁珠使用DCDC时尽…

【驱动篇】龙芯LS2K0300之红外驱动

实验目标 编写HX1838红外接收器驱动&#xff0c;根据接收的波形脉冲解码红外按键键值 模块连接 模块连接&#xff1a;VCC接Pin 2&#xff0c;GND接Pin1&#xff0c;DATA接Pin16 驱动代码 HX1838 GPIO初始化&#xff0c;申请中断&#xff0c;注意&#xff1a;GPIO48默认是给…

Spring Boot 中 PGSQL 判断打卡点是否经过轨迹优化代码,循环查询物理表修改生成临时表,向临时表插入数据后再做ST_DWithin判断

记录一下一个业务问题&#xff0c;流程是这样的&#xff0c;我现在有一个定时任务&#xff0c;5分钟执行一次&#xff0c;更新车辆打卡的情况。现在有20俩车&#xff0c;每辆车都分配了路线&#xff0c;每条路线都有打卡点&#xff0c;每个打卡点分配了不同的时间段&#xff0c…

【动态规划 前缀和】2478. 完美分割的方案数

本文涉及知识点 划分型dp 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LeetCode 2478. 完美分割的方案数 给你一个字符串 s &#xff0c;每个字符是数字 ‘1’ 到 ‘9’ &#xff0c;再给你两个整数 k 和 minLength 。 如…

Redis---保证主从节点一致性问题 +与数据库数据保持一致性问题

保证主从节点一致性问题 Redis的同步方式默认是异步的&#xff0c;这种异步的同步方式导致了主从之间的数据存在一定的延迟&#xff0c;因此Redis默认是弱一致性的。 解决&#xff1a; 1.使用Redisson这样的工具&#xff0c;它提供了分布式锁的实现&#xff0c;确保在分布式环…

python自动化运维--DNS处理模块dnspython

1.dnspython介绍 dnspython是Pyhton实现的一个DNS工具包&#xff0c;他几乎支持所有的记录类型&#xff0c;可以用于查询、传输并动态更新ZONE信息&#xff0c;同事支持TSIG&#xff08;事物签名&#xff09;验证消息和EDNS0&#xff08;扩展DNS&#xff09;。在系统管理方面&a…

京东云备案流程图_云主机快速ICP备案_京东云服务器备案问题解答

京东云ICP备案流程&#xff0c;备案包括网站和APP备案&#xff0c;以及备案问题解答FAQ&#xff0c;阿腾云以京东云网站域名备案流程为例&#xff0c;先填写主办单位信息&#xff0c;选择网站备案或APP备案&#xff0c;申请授权码并验证&#xff0c;填写并上传主办单位详细信息…

老挝语翻译成简体中文推荐用什么翻译工具?《老挝语翻译通》App满足你所有翻译需求!

如果你正在找一款支持把老挝语翻译成中文&#xff0c;或者把中文翻译成老挝语的翻译工具&#xff0c;不得不推荐你使用《老挝语翻译通》App&#xff0c;您的随身老挝语翻译官&#xff0c;带您轻松跨越语言障碍。 功能亮点&#xff1a; 实时翻译&#xff1a;中文与老挝语的无缝…

论文阅读【时间序列】DSformer

论文阅读【时间序列】DSformer arxive: DSformer: A Double Sampling Transformer for Multivariate Time Series Long-term Prediction github: MTST 分类&#xff1a;多变量时间序列&#xff08;Multivariate time series&#xff09; 核心观点 多变量时间序列3个维度信息 …

一款十六进制编辑器,你的瑞士军刀!!【送源码】

软件介绍 ImHex是一款功能强大的十六进制编辑器&#xff0c;专为逆向工程师、程序员以及夜间工作的用户设计。它不仅提供了基础的二进制数据编辑功能&#xff0c;还集成了一系列高级特性&#xff0c;使其成为分析和修改二进制文件的理想工具。 功能特点 专为逆向工程、编程和夜…

Appium adb 获取appActivity

方法一&#xff08;最简单有效的方法&#xff09; 通过cmd命令&#xff0c;前提是先打开手机中你要获取包名的APP adb devices -l 获取连接设备详细信息 adb shell dumpsys activity | grep mFocusedActivity 有时获取到的不是真实的Activity 方法二 adb shell monkey -p …

K6 性能测试教程:入门介绍,环境搭建和编写第一个 K6 测试脚本

K6 性能测试教程&#xff1a;入门介绍&#xff0c;环境搭建和编写第一个 K6 测试脚本 这篇文章将带您进入 K6 性能测试的世界。博文内容涵盖了 K6 性能测试的入门知识、环境搭建步骤&#xff0c;以及如何编写您的第一个测试脚本。无论您是初学者还是有经验的性能测试专业人员&…

剪映 v5.5 Pro Vip解锁版:使用指南与注意事项

摘要&#xff1a;本文介绍了剪映Pro VIP解锁版的使用方法&#xff0c;包括安装、测试和使用VIP素材的步骤&#xff0c;以及如何避免误报和保持解锁状态的建议。 正文&#xff1a; 剪映Pro是一款广受欢迎的视频编辑软件&#xff0c;提供了丰富的视频编辑功能和大量高质量的素材…

Python基础001

Python输出语句 print输出字符串 print("中国四大名著&#xff1a;","西游记|","三国演义|","红楼梦|","水浒传") print(6) print(1 1)Python输入语句 input函数 input() input("我的名字是&#xff1a;") p…

javaSE期末练习题

文章目录 前言一、程序控制1.顺序结构问题描述解题思路题解 2.选择结构2.1 题1问题描述解题思路题解 2.1 题2问题描述解题思路题解 3.循环结构3.1 阶乘的求取问题描述解题思路题解 3.2 水仙花数问题描述解题思路题解 二、数组三、类与对象1.类与对象1.1圆类问题描述解题思路题解…