数据结构——图的存储及遍历

图的存储及遍历

  • 目的
  1. 了解图的存储方式中的邻接矩阵
  2. 理解深度优先遍历算法的原理和实验方法

  • 要求
  1. 实现图的存储,采用邻接矩阵进行存储
  2. 实现深度优先遍历算法
  3. 测试并验证算法的正确性

  • 原理

邻接矩阵(Adjacency Matrix)是一种表示图的方法,用矩阵来描述图中各个顶点之间的连接关系。对于一个有n个顶点的图,邻接矩阵是一个n×n的矩阵。如果图中的顶点vi和vj之间存在边,则对应的矩阵元素a[i][j]或a[j][i]为1;否则为0。对于无向图而言,邻接矩阵是对称的。邻接矩阵的优点是可以快速地判断两个顶点之间是否存在边,但当图边的数量很大时,邻接矩阵会占用较多的存储空间。

图1.图的邻接图示

图2.无向图的邻接矩阵

深度优先遍历(Depth-First Search,DFS)是一种用于遍历或搜索图或树的算法。它从图的某个顶点开始,沿着一条路径一直走到底,然后回溯到上一个顶点,继续探索其他路径,直到所有的节点都被访问过。在深度优先遍历过程中,每个顶点只能被访问一次,且保证所有的连通节点都被访问到。

  • 步骤和结果

1. 结构体定义部分:

   - 定义了一个结构体 Graph,用来表示图结构。其中包括存储顶点信息的数组 vertex,存储边信息的二维数组 edge,顶点数 vertex_num,边数 edge_num。

   - 定义了一个全局数组 visited,用来记录顶点是否被访问过。

2. 初始化图部分:

   - init_graph 函数用来初始化图,将顶点数和边数置为0,并将相关数组初始化为空或0。

3. 添加顶点和边部分:

   - add_vertex 函数用来向图中添加顶点,将顶点信息存储到 vertex 数组中。

   - add_edge 函数用来向图中添加边,通过修改 edge 数组来表示顶点之间的连接关系,并增加边数。

4. 深度优先遍历部分:

   - dfs 函数是实现深度优先搜索的核心部分。它接受一个图结构指针和一个顶点编号作为参数,递归地访问与当前顶点相邻的未被访问过的顶点,并标记为已访问。在递归过程中输出顶点信息,实现深度优先遍历。

  

5. 主函数部分:

   - 在主函数中,首先初始化一个图结构 g,并向其中添加顶点和边。

   - 然后输出邻接矩阵,显示顶点之间的连接关系。

   - 最后进行深度优先遍历,从顶点0开始进行深度优先搜索,并输出遍历结果。

图3.实验结果

  • 实验中出现的问题及解决方法

在实现深度优先遍历算法时,遇到了递归调用的问题,导致程序进入死循环,经过分析发现是没有正确编辑已经访问过的结点,导致重复访问。

解决方法是在遍历过程中标记已经访问过的结点,并在递归调用前进行判断避免重复访问。

  • 实验总结及体会

    通过本次实验,我学会了图的邻接矩阵存储方式和深度优先遍历算法的实现方式。同时,也意识到在编程中需要严格注意边界条件和状态标记,避免程序出现死循环的问题。

  • 代码部分
  • #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_VERTEX_NUM 6 // 顶点数的最大值
    
    typedef struct {
        char vertex[MAX_VERTEX_NUM]; // 存储顶点信息
        int edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 存储边信息
        int vertex_num; // 顶点数
        int edge_num; // 边数
    } Graph;
    
    int visited[MAX_VERTEX_NUM]; // 记录顶点是否被访问过
    
    // 初始化图
    void init_graph(Graph *g) {
        int i, j;
        g->vertex_num = 0;
        g->edge_num = 0;
        for (i = 0; i < MAX_VERTEX_NUM; i++) {
            g->vertex[i] = '\0';
            for (j = 0; j < MAX_VERTEX_NUM; j++) {
                g->edge[i][j] = 0;
            }
        }
    }
    
    // 添加顶点
    void add_vertex(Graph *g, char v) {
        g->vertex[g->vertex_num++] = v;
    }
    
    // 添加边
    void add_edge(Graph *g, int v1, int v2) {
        g->edge[v1][v2] = 1;
        g->edge[v2][v1] = 1;
        g->edge_num++;
    }
    
    // 深度优先遍历
    void dfs(Graph *g, int v) {
        int i;
        visited[v] = 1;
        printf("%c ", g->vertex[v]);
        for (i = 0; i < g->vertex_num; i++) {
            if (g->edge[v][i] == 1 && visited[i] == 0) {
                dfs(g, i);
            }
        }
    }
    
    int main() {
        Graph g;
        int i, j, v1, v2;
        
        init_graph(&g);
        
        // 添加顶点
        for (i = 0; i < MAX_VERTEX_NUM; i++) {
            add_vertex(&g, 'A' + i);
        }
        
        // 添加边
        add_edge(&g, 0, 1);
        add_edge(&g, 1, 5);
        add_edge(&g, 1, 2);
        add_edge(&g, 2, 5);
        add_edge(&g, 5, 3);
        add_edge(&g, 5, 4);
        add_edge(&g, 3, 4);
        add_edge(&g, 4, 0);
        
        // 输出邻接矩阵
        printf("邻接矩阵:\n");
        for (i = 0; i < g.vertex_num; i++) {
            for (j = 0; j < g.vertex_num; j++) {
                printf("%d ", g.edge[i][j]);
            }
            printf("\n");
        }
        
        // 深度优先遍历
        printf("深度优先遍历:\n");
        for (i = 0; i < g.vertex_num; i++) {
            visited[i] = 0;
        }
        dfs(&g, 0);
        printf("\n");
        
        return 0;
    }

#include <stdio.h>
#include <stdlib.h>

#define MAX_VERTEX_NUM 6 // 顶点数的最大值

typedef struct {
    char vertex[MAX_VERTEX_NUM]; // 存储顶点信息
    int edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 存储边信息
    int vertex_num; // 顶点数
    int edge_num; // 边数
} Graph;

int visited[MAX_VERTEX_NUM]; // 记录顶点是否被访问过

// 初始化图
void init_graph(Graph *g) {
    int i, j;
    g->vertex_num = 0;
    g->edge_num = 0;
    for (i = 0; i < MAX_VERTEX_NUM; i++) {
        g->vertex[i] = '\0';
        for (j = 0; j < MAX_VERTEX_NUM; j++) {
            g->edge[i][j] = 0;
        }
    }
}


// 添加顶点
void add_vertex(Graph *g, char v) {
    g->vertex[g->vertex_num++] = v;
}


// 添加边
void add_edge(Graph *g, int v1, int v2) {
    g->edge[v1][v2] = 1;
    g->edge[v2][v1] = 1;
    g->edge_num++;
}


// 深度优先遍历
void dfs(Graph *g, int v) {
    int i;
    visited[v] = 1;
    printf("%c ", g->vertex[v]);
    for (i = 0; i < g->vertex_num; i++) {
        if (g->edge[v][i] == 1 && visited[i] == 0) {
            dfs(g, i);
        }
    }
}


int main() {
    Graph g;
    int i, j, v1, v2;
    
    
init_graph(&g);
    
    
// 添加顶点
    for (i = 0; i < MAX_VERTEX_NUM; i++) {
        add_vertex(&g, 'A' + i);
    }
    
    
// 添加边
    add_edge(&g, 0, 1);
    add_edge(&g, 1, 5);
    add_edge(&g, 1, 2);
    add_edge(&g, 2, 5);
    add_edge(&g, 5, 3);
    add_edge(&g, 5, 4);
    add_edge(&g, 3, 4);
    add_edge(&g, 4, 0);
    
    
// 输出邻接矩阵
    printf("邻接矩阵:\n");
    for (i = 0; i < g.vertex_num; i++) {
        for (j = 0; j < g.vertex_num; j++) {
            printf("%d ", g.edge[i][j]);
        }
        printf("\n");
    }
    
    
// 深度优先遍历
    printf("深度优先遍历:\n");
    for (i = 0; i < g.vertex_num; i++) {
        visited[i] = 0;
    }
    dfs(&g, 0);
    printf("\n");


    
    
return 0;
}

  • 27
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
深度优先遍历是一种用于遍历算法。它的基本思想是从的某个顶点开始,沿着一条路径一直走到底,然后回溯到上一个顶点,再沿着另一条路径继续探索,直到所有的顶点都被访问过为止。深度优先遍历可以用递归或者栈来实现。 在邻接矩阵存储深度优先遍历过程中,首先我们需要定义一个数组来标记哪些顶点已经被访问过。然后从起始顶点开始,将其标记为已访问,并将其加入到一个栈中。接下来,从栈中取出一个顶点,访问它的邻接顶点中尚未被访问过的顶点,并将这些顶点加入到栈中。不断重复这个过程,直到栈为空为止。通过这种方式,我们可以按照深度优先的顺序遍历整个。 需要注意的是,由于数据输入的顺序不同,建立的邻接表可能不同,因此深度优先遍历的输出结果可能不唯一。同时,你可以通过加入计数器和记录步骤的方式来获得深度优先遍历的结果和步骤。 具体的C语言编程实现可以参考以上引用中提到的代码和方法。这样,在读取数据后,你就可以使用深度优先遍历算法遍历,并得到所需的结果和步骤。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [超详细C语言版数据结构深度优先遍历(推荐收藏)](https://blog.csdn.net/lucky51222/article/details/118224395)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [数据结构——的DFS(深度优先遍历)- C语言代码实现](https://blog.csdn.net/weixin_45954730/article/details/123402628)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值