通信网中的算法问题 实验四—深入优先算法和广度优先算法(节点遍历)

实验四 通信网中的算法问题—深入优先算法和广度优先算法(节点遍历)

一. 引言

在通信网络中,节点遍历是一项重要的任务,它有助于理解网络的拓扑结构、识别潜在问题和进行各种分析。深度优先搜索算法和广度优先搜索算法是两种常用的图遍历方法,它们可以帮助我们了解网络中的节点之间的连接关系。

二. 系统设计要求

实验要求:

1、以任意节点为起点,利用深度优先搜索算法,计算附图的遍历顺序并打印输出(是否可以用2种不同的实现方法);

2、以任意节点为起点,利用广度优先搜索算法,计算附图的遍历顺序并打印输出(是否可以用2种不同的实现方法);

注意:

1、请转换附件的图形为输入数据格式(附在实验报告上);

2、请打印的时候把节点编号、节点名称按照遍历的顺序打印.

具体显示内容:

1、节点数**

2、节点编号及名称**

3、边数**

4、深度优先搜索结果:****(例如:1、重庆;4、上海。。。。。。。)

5、广度优先搜搜结果:****

6、是连通图,所有节点都遍历;

不是连通图,**节点无法遍历;

在这里插入图片描述

三. 设计思路与方案

1.程序流程图设计

在这里插入图片描述

2.全局变量及结构体

#define CITY_NUM 10
#define connect 1
#define unconnect 0 // 表示无连接

int graph[CITY_NUM][CITY_NUM]; // 城市之间的距离
int p[CITY_NUM]; // 前驱节点数组,存储最短路径的前驱节点
int S[CITY_NUM]; // 标记已访问的顶点
char cities[CITY_NUM][20] =
{
    "重庆",
    "北京",
    "成都",
    "上海",
    "深圳",
    "杭州",
    "广州",
    "武汉",
    "天津",
    "南京",
};

3.算法设计

3.1整体代码
#include <stdio.h>

#define CITY_NUM 10
#define connect 1
#define unconnect 0 // 表示无连接

int graph[CITY_NUM][CITY_NUM]; // 城市之间的距离
int p[CITY_NUM]; // 前驱节点数组,存储最短路径的前驱节点
int S[CITY_NUM]; // 标记已访问的顶点
char cities[CITY_NUM][20] =
{
    "重庆",
    "北京",
    "成都",
    "上海",
    "深圳",
    "杭州",
    "广州",
    "武汉",
    "天津",
    "南京",
};

void fileop(void)
{
    FILE *fp;
    int i, j;
    int from, to;
    if ((fp = fopen("input1.txt", "r")) == NULL)
    {
        printf("文件打开失败");
    }
    else
    {
        // 初始化图,将每个节点之间权值设为0表示为未连接
        for (i = 0; i < CITY_NUM; i++)
        {
            for (j = 0; j < CITY_NUM; j++)
            {
                graph[i][j] = unconnect;
            }
        }
        // 读取文件节点之间的权值并赋值
        while (fscanf(fp, "%d %d", &from, &to) == 2)
        {
            graph[from - 1][to - 1] = connect;
            graph[to - 1][from - 1] = connect;
        }
        fclose(fp);
    }
}

void printCities()
{
    printf("节点的编号及名称:\n");
    for (int i = 0; i < CITY_NUM; i++)
    {
        printf("节点%d:%s;\n", i + 1, cities[i]);
    }
    printf("\n");
}

void printEdges()
{
    int nodes = 0;
    printf("所有边的信息:\n");
    for (int i = 0; i < CITY_NUM; i++)
    {
        for (int j = i + 1; j < CITY_NUM; j++)
        {
            if (graph[i][j] != unconnect)
            {
                printf("节点%d 到 节点%d \n", i + 1, j + 1);
                nodes++;
            }
        }
    }
    printf("边数:%d", nodes);
    printf("\n");
}

void DFS(int node)//递归实现深度遍历
{
    S[node] = 1; // 标记节点为已访问
    printf("节点%d:%s\n", node + 1, cities[node]);

    for (int i = 0; i < CITY_NUM; i++)
    {
        if (graph[node][i] == connect && S[i] == 0)
        {
            DFS(i);
        }
    }
}

void BFS(int startNode)//队列实现广度遍历
{
    // 重置S数组
    for (int i = 0; i < CITY_NUM; i++)
    {
        S[i] = 0;
    }
    int queue[CITY_NUM];
    int front = 0, rear = 0;

    queue[rear++] = startNode;
    S[startNode] = 1; // 标记节点为已访问

    while (front < rear)
    {
        int currentNode = queue[front++];
        printf("节点%d:%s\n", currentNode + 1, cities[currentNode]);

        for (int i = 0; i < CITY_NUM; i++)
        {
            if (graph[currentNode][i] == connect && S[i] == 0)
            {
                queue[rear++] = i;
                S[i] = 1; // 标记节点为已访问
            }
        }
    }
}

int isConnectedGraph()
{
    int temp=0;
    int flag=-1;//返回对应不连通的节点(返回-1表示全连通)
    for (int i = 0; i < CITY_NUM; i++)
    {
        for(int j = 0; j<CITY_NUM; j++){
            if (graph[i][j] == unconnect)
            {
                temp++;
            }
        }
        if(temp > CITY_NUM-1)//若与每个节点的距离均为unconnect则不连通
        {
            flag = i;
        }
        temp=0;
    }
    return flag;
}

int main()
{
    int startNode;// 获取用户输入的起始节点
    fileop();
    printCities();
    printEdges();

    printf("请输入起始节点编号 (1-%d): ", CITY_NUM);
    scanf("%d", &startNode);

    if (startNode < 1 || startNode > CITY_NUM)
    {
        printf("无效的输入。\n");
        return 1;
    }

    startNode=startNode-1; // 数组序号对应节点编号减去1

    // 执行深度优先搜索
    printf("深度优先搜索结果:\n");
    DFS(startNode);

    // 执行广度优先搜索
    printf("广度优先搜索结果:\n");
    BFS(startNode);

    if (isConnectedGraph()==-1)
    {
        printf("是连通图,所有节点都遍历。\n");
    }
    else
    {
        printf("不是连通图,节点%d无法遍历。\n",isConnectedGraph()+1);
    }

    return 0;
}

3.2 文件读取及图的构建

将图形转化为输入数据格式并保存在input1.txt文件中。完成读取input1.txt文件,构建图结构
在这里插入图片描述

1 2
1 3
1 4
2 3
2 5
3 4
3 5
3 6
4 6
4 7
4 9
5 6
5 8
6 3
6 7
6 8
7 8
7 10

void fileop(void)
{
    FILE *fp;
    int i, j;
    int from, to;
    if ((fp = fopen("input1.txt", "r")) == NULL)
    {
        printf("文件打开失败");
    }
    else
    {
        // 初始化图,将每个节点之间权值设为0表示为未连接
        for (i = 0; i < CITY_NUM; i++)
        {
            for (j = 0; j < CITY_NUM; j++)
            {
                graph[i][j] = unconnect;
            }
        }
        // 读取文件节点之间的权值并赋值
        while (fscanf(fp, "%d %d", &from, &to) == 2)
        {
            graph[from - 1][to - 1] = connect;
            graph[to - 1][from - 1] = connect;
        }
        fclose(fp);
    }
}
3.3 打印显示信息
void printCities()
{
    printf("节点的编号及名称:\n");
    for (int i = 0; i < CITY_NUM; i++)
    {
        printf("节点%d:%s;\n", i + 1, cities[i]);
    }
    printf("\n");
}

void printEdges()
{
    int nodes = 0;
    printf("所有边的信息:\n");
    for (int i = 0; i < CITY_NUM; i++)
    {
        for (int j = i + 1; j < CITY_NUM; j++)
        {
            if (graph[i][j] != unconnect)
            {
                printf("节点%d 到 节点%d \n", i + 1, j + 1);
                nodes++;
            }
        }
    }
    printf("边数:%d", nodes);
    printf("\n");
}
3.4深度遍历算法(DFS)和广度遍历算法(BFS)
void DFS(int node)//递归实现深度遍历
{
    S[node] = 1; // 标记节点为已访问
    printf("节点%d:%s\n", node + 1, cities[node]);

    for (int i = 0; i < CITY_NUM; i++)
    {
        if (graph[node][i] == connect && S[i] == 0)
        {
            DFS(i);
        }
    }
}

void BFS(int startNode)//队列实现广度遍历
{
    // 重置S数组
    for (int i = 0; i < CITY_NUM; i++)
    {
        S[i] = 0;
    }
    int queue[CITY_NUM];
    int front = 0, rear = 0;

    queue[rear++] = startNode;
    S[startNode] = 1; // 标记节点为已访问

    while (front < rear)
    {
        int currentNode = queue[front++];
        printf("节点%d:%s\n", currentNode + 1, cities[currentNode]);

        for (int i = 0; i < CITY_NUM; i++)
        {
            if (graph[currentNode][i] == connect && S[i] == 0)
            {
                queue[rear++] = i;
                S[i] = 1; // 标记节点为已访问
            }
        }
    }
}
3.5 判断是否为连通图
int isConnectedGraph()
{
    int temp=0;
    int flag=-1;//返回对应不连通的节点(返回-1表示全连通)
    for (int i = 0; i < CITY_NUM; i++)
    {
        for(int j = 0; j<CITY_NUM; j++){
            if (graph[i][j] == unconnect)
            {
                temp++;
            }
        }
        if(temp>CITY_NUM-1)//若与每个节点的距离均为unconnect则不连通
        {
            flag = i;
        }
        temp=0;
    }
    return flag;
}

3.6 主函数
int main()
{
    int startNode;// 获取用户输入的起始节点
    fileop();
    printCities();
    printEdges();

    printf("请输入起始节点编号 (1-%d): ", CITY_NUM);
    scanf("%d", &startNode);

    if (startNode < 1 || startNode > CITY_NUM)
    {
        printf("无效的输入。\n");
        return 1;
    }

    startNode=startNode-1; // 数组序号对应节点编号减去1

    // 执行深度优先搜索
    printf("深度优先搜索结果:\n");
    DFS(startNode);

    // 执行广度优先搜索
    printf("广度优先搜索结果:\n");
    BFS(startNode);

    if (isConnectedGraph()==-1)
    {
        printf("是连通图,所有节点都遍历。\n");
    }
    else
    {
        printf("不是连通图,节点%d无法遍历。\n",isConnectedGraph()+1);
    }

    return 0;
}

四.调试

五.心得体会

在编写isconnectedGraph()函数时,代码总是无法实现返回非连通的相应节点,即便确认逻辑没有问题,反复的修改调试也让人心烦意乱,怀疑这么做是否行得通。但往往就是一些微小的错误导致了运行结果的不一致,例如用来记录各个节点是否连通的temp没有及时清零。所以说,调试代码不光要对自己有信心,更需要细心和扎实的基础。

六.意见

七.附录

结果展示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值