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

实验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

程序运行结果:

单步调试截图

实验总结

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

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这是一项关于设计性代码的ad(应用开发)转换实验,由西南交通大学发起。 在这个实验中,我们将致力于开发一种更高效、更可靠的算法,以转换ad实现。广告在现代社会中扮演着重要的角色,它们通过不同的媒介向大众传达信息。然而,广告的制作成本昂贵且需要大量的人工劳动,而且它们也需要在不同的平台上进行适配和修改。 因此,我们希望通过设计性代码的开发,解决这些问题。设计性代码是一种能够自动化执行特定任务的代码。对于广告转换来说,设计性代码可以将一个广告的原始版本自动转换为不同媒介和平台所需的格式和大小。 在这个实验中,我们将采用静态和动态广告作为实验对象。静态广告是指那些不涉及动画或视频的广告,而动态广告则包括了视频和动画元素。我们将通过研究和分析不同广告媒介和平台的要求,确定所需的转换规则和代码逻辑。 我们的目标是设计出一种算法,该算法能够智能地识别广告中的各种元素,如文本、图像、音频和视频,并根据不同的媒介和平台要求进行相应的转换。这样一来,制作广告的工作量将大大减少,并且广告在不同媒介和平台上的效果也会更加统一。 我们将在西南交通大学实验室中进行进行实验,利用先进的计算机技术和算法来开发设计性代码。通过不断测试和改进,最终我们希望能够开发出一种高效、可靠且智能的广告转换解决方案,为广告行业带来更大的便利和效益。 总之,这个ad转换实验西南交通大学所发起的一个关于设计性代码开发的项目。我们的目标是通过开发智能的转换算法来解决广告制作的问题,并提供更高效、更统一的广告转换解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

还有糕手

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

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

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

打赏作者

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

抵扣说明:

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

余额充值