【数据结构实验】图(三)图的深度优先搜索(DFS)生成树

news2025/2/24 0:27:43

文章目录

  • 1. 引言
  • 2. 深度优先搜索生成树
  • 3. 实验内容
    • 3.1 实验题目
      • (一)输入要求
      • (二)输出要求
    • 3.2 算法实现
      • 1. 数据结构
      • 2. 队列操作函数
      • 3. 广度优先搜索遍历
      • 4. 创建图
      • 5. 深度优先搜索算法
      • 6. 主函数及DFS主函数
      • 7. 输出生成树信息
    • 3.3 代码整合
  • 4. 实验结果

1. 引言

  深度优先搜索(DFS)是图算法中的一种重要的遍历方法,它通过深度遍历图的顶点来构建生成树。生成树是一个无回路的连通子图,包含了原图的所有顶点,但是边数最少。

本实验将通过C语言实现深度优先搜索生成树。

2. 深度优先搜索生成树

  深度优先搜索是一种递归的图遍历算法,其主要思想是从起始顶点开始,尽可能深入图中的每一个分支,直到不能再深入为止,然后回溯到上一个分支。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 实验内容

3.1 实验题目

   以顶点 0 为起始顶点,求图 G 的深度优先搜索生成树(即深度优先遍历过程形成的树)。

(一)输入要求

{0,1,1,1,1,0,0},
{0,0,1,1,0,0,0},
{1,0,0,0,0,0,0},
{0,0,1,0,0,0,0},
{0,0,0,0,0,1,1},
{0,0,0,0,0,0,1},
{0,0,0,0,0,0,0}

使用前文得到的邻接表做为输入数据

(二)输出要求

输出树中所有结点。结点输出格式如下:(顶点,顶点的父亲,顶点所在的层数)比如,对下面这棵树,有以下输出。
在这里插入图片描述

3.2 算法实现

1. 数据结构

typedef struct P {
    int VerAdj;
    struct P *link;
} P;

typedef struct Q {
    int VerName;
    P *Adjacent;
    int Visited;
} Q;

typedef struct {
    Q Head[20];
} Graph;

typedef struct Tree {
    Q data;
    struct Tree *FirstChild;
    struct Tree *NextBrother;
} Tree;

typedef struct q {
    Tree *data;
    struct q *next;
} Queue;
  • P结构体: 用于表示图中的邻接点,VerAdj表示邻接顶点,link指向下一个邻接点。

  • Q结构体: 用于表示图中的顶点,VerName表示顶点名称,Adjacent指向邻接点链表,Visited表示是否被访问过。

  • Graph结构体: 表示整个图,包含一个数组Head,每个元素表示一个顶点。

  • Tree结构体: 表示生成树中的节点,包含一个数据域data,表示顶点,以及FirstChildNextBrother分别指向第一个孩子和下一个兄弟节点。

  • Queue结构体: 用于实现队列,存储生成树的节点。

注:自编代码,比较丑陋,请忽略细节

2. 队列操作函数

void QInsert(Tree *item);
void QDelete();
  • QInsert: 将生成树节点插入队列。

  • QDelete: 从队列中删除节点。

3. 广度优先搜索遍历

void LevelOrder(Tree *t);
  • LevelOrder: 广度优先搜索遍历生成树,输出节点信息,包括顶点、父亲和层数。

4. 创建图

void Create(Graph *g);
  • Create: 根据邻接矩阵A创建图,构建邻接表。

5. 深度优先搜索算法

void DepthForceSearch(Graph *g, int i, Tree *t);
  • DepthForceSearch: 递归实现深度优先搜索,构建生成树。

6. 主函数及DFS主函数

int main();
void DFS_Main(Graph *g, Tree *t);
  • main函数: 创建图,调用DFS_Main进行深度优先搜索,输出生成树的节点信息。

  • DFS_Main: 遍历所有未访问的顶点,以每个未访问的顶点为根进行深度优先搜索。

7. 输出生成树信息

void Output(Tree *t);
  • Output: 输出生成树的节点信息。

3.3 代码整合

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

#define N 7
int A[N][N] = {
    {0, 1, 1, 1, 1, 0, 0},
    {0, 0, 1, 1, 0, 0, 0},
    {1, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 1, 1},
    {0, 0, 0, 0, 0, 0, 1},
    {0, 0, 0, 0, 0, 0, 0}
};

typedef struct P {
    int VerAdj;
    struct P *link;
} P;

typedef struct Q {
    int VerName;
    P *Adjacent;
    int Visited;
} Q;

typedef struct {
    Q Head[20];
} Graph;

typedef struct Tree {
    Q data;
    struct Tree *FirstChild;
    struct Tree *NextBrother;
} Tree;

typedef struct q {
    Tree *data;
    struct q *next;
} Queue;

Queue *front = NULL, *rear = NULL, *pos = NULL;

void QInsert(Tree *item);
void QDelete();
void LevelOrder(Tree *t);
void Create(Graph *g);
void DepthFirstSearch(Graph *g, int i, Tree *t);
void DFS_Main(Graph *g, Tree *t);
void Output(Tree *t);

int main() {
    Graph g;
    Tree t;
    Create(&g);
    printf("深度遍历:\n");
    DFS_Main(&g, &t);
    printf("生成树结点信息:\n");
    Output(&t);
    return 0;
}

void QInsert(Tree *item) {
    Queue *s = (Queue *)malloc(sizeof(Queue));
    s->data = item;
    s->next = NULL;
    if (front == NULL)
        front = s;
    else
        rear->next = s;
    rear = s;
}

void QDelete() {
    if (front == NULL) {
        printf("队列为空");
        return;
    }
    Queue *p = front;
    front = p->next;
    free(p);
    if (front == NULL)
        rear = NULL;
}

void LevelOrder(Tree *t) {
    if (t != NULL)
        QInsert(t);
    while (front != NULL) {
        Tree *p = front->data;
        printf("(%d, %d, %d) ", p->data.VerName, t->data.VerName, p->data.VerName);
        while (p != NULL) {
            if (p->FirstChild != NULL) {
                QInsert(p->FirstChild);
            }
            p = p->NextBrother;
        }
        QDelete();
    }
}

void Create(Graph *g) {
    int i, j, n, t;
    for (i = 0; i < N; i++) {
        g->Head[i].VerName = i;
        g->Head[i].Adjacent = NULL;
        P *p = (P *)malloc(sizeof(P));
        t = 0;
        for (j = 0; j < N; j++) {
            if (A[i][j]) {
                if (t == 0) {
                    g->Head[i].Adjacent = p;
                    p->VerAdj = j;
                    p->link = NULL;
                    t = 1;
                } else {
                    P *q = (P *)malloc(sizeof(P));
                    q->VerAdj = j;
                    q->link = NULL;
                    p->link = q;
                    p = q;
                }
            }
        }
    }
}

void Output(Tree *t) {
    if (t != NULL)
        LevelOrder(t);
}



void DepthForceSearch(Graph *g, int i, Tree *t) {
    P *p;
    g->Head[i].Visited = 1;
    p = g->Head[i].Adjacent;
    t->data = g->Head[i];
    while (p != NULL) {
        if (!g->Head[p->VerAdj].Visited) {
            Tree *child = (Tree *)malloc(sizeof(Tree));
            child->NextBrother = NULL;
            child->FirstChild = NULL;
            DepthForceSearch(g, p->VerAdj, child);
            Tree *temp = t->FirstChild;
            if (temp == NULL) {
                t->FirstChild = child;
            } else {
                while (temp->NextBrother != NULL) {
                    temp = temp->NextBrother;
                }
                temp->NextBrother = child;
            }
        }
        p = p->link;
    }
}

void DFS_Main(Graph *g, Tree *t) {
    int i;
    for (i = 0; i < N; i++)
        g->Head[i].Visited = 0;
    for (i = 0; i < N; i++) {
        if (!g->Head[i].Visited) {
            Tree *root = (Tree *)malloc(sizeof(Tree));
            root->NextBrother = NULL;
            root->FirstChild = NULL;
            DepthForceSearch(g, i, root);
            *t = *root;
        }
    }
}

4. 实验结果

在这里插入图片描述

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

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

相关文章

第一百八十回 介绍两种阴影效果

文章目录 1. 概念介绍2. 实现方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"自定义SlideImageSwitch组件"相关的内容&#xff0c;本章回中将介绍两种阴影效果.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

【服务器能干什么】二十分钟搭建一个属于自己的 RSS 服务

如果大家不想自己捣鼓,只是想尝尝鲜,可以在下面留言,我后台帮大家开几个账号玩一玩。 哔哩哔哩【高清版本可以点击去吐槽到 B 站观看】:【VPS服务器到底能干啥】信息爆炸的年代,如何甄别出优质的内容?你可能需要自建一个RSS服务!_哔哩哔哩_bilibili 前言 RSS 服务 市…

面试:双线程交替打印奇偶数

代码如下&#xff1a; package practice1;/*** 0-100的奇数偶数打印* 1、通过对象的wait和notify进行线程阻塞* 2、通过对num%2的结果进行奇数偶数的判断输出**/ public class JiOuOne {private static volatile int num 0;private static final int max 100;public static …

#define例题

我们已经学了#define的所有知识&#xff0c;让我们来看这道题&#xff0c;可不要又陷入陷阱 题目要求&#xff1a; #define N 4 #define Y(n) ((N2)*n) int main() {int z 2 * (N Y(5 1));printf("z%d\n", z);return 0; } 求这个z的值是多少&#xff1f; 我们直接…

Stable-Diffusion——Windows部署教程

Windows 参考文章&#xff1a;从零开始&#xff0c;手把手教你本地部署Stable Diffusion Webui AI绘画(非最新版) 一键脚本安装 默认环境安装在项目路径的venv下 conda create -n df_env python3.10安装pytorch&#xff1a;&#xff08;正常用国内网就行&#xff09; python -…

Sublime Text 3 安装离线插件 anaconda

1 下载 Sublime Text 3 免安装版 Download - Sublime Text 2 下载 Package Control&#xff0c;放到 Sublime Text Build 3211\Data\Installed Packages 目录下。 Installation - Package Control 3 页面搜索 anaconda anaconda - Search - Package Control Anaconda - Pac…

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体)

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都…

自建私有化证书颁发机构(Certificate Authority,CA)实战之 《0x02 Nginx 配置 https双向认证》

自建CA实战之 《0x02 Nginx 配置 https双向认证》 上一章节我们已经实现了Nginx上配置https单向认证&#xff0c;主要场景为客户端验证服务端的身份&#xff0c;但是服务端不验证客户端的身份。 本章节我们将实现Nginx上配置https双向认证&#xff0c;主要场景为客户端验证服…

Day41力扣打卡

打卡记录 第 N 位数字&#xff08;找规律&#xff09; 链接 class Solution:def findNthDigit(self, n: int) -> int:count, digit, start 9, 1, 1while n > count:n - countdigit 1start * 10count start * 9 * digitnum start (n - 1) // digitreturn int(str(n…

详解#define

我们要知道&#xff0c;#define后面定义的标识符只进行替换而不进行计算&#xff0c;我们不能根据惯性自动给它计算了&#xff0c;这样可能会出错。 目录 1.关于#define 1.1#define定义标识符 1.2#define定义宏 1.3#define的替换规则 2.#和## 1.# 2.## 3.带副作用的宏参…

1.4 8位加法器

1.半加器 2.全加器 半加器: 完整模拟1位加法 1.A,B 接受端,接受1或0 , 2个电信号 2.异或门 做为结果: 1^10, 0^00, 1^01, 0^11 与编程中的: 异或一致 3.与门 做为进位: 1&11,1&00,0&10, 0&01 与编程中的: 与一致 4.半加器实现1位的加法运算,比如:A端: …

11 月 25 日 ROS 学习笔记——3D 建模与仿真

文章目录 前言一、在 ROS 中自定义机器人的3D模型1. 在 rviz 里查看3D模型2. xacro 二、Gazebo1. urdf 集成 gazebo2. 综合应用1). 运动控制及里程计2). 雷达仿真3). 摄像头信息仿真4). kinect 深度相机仿真5). 点云 前言 本文为11 月 25 日 ROS 学习笔记——3D 建模与仿真&am…

Vue框架学习笔记——键盘事件

文章目录 前文提要键盘事件&#xff08;并不是所有按键都能绑定键盘事件&#xff09;常用的按键不同的tab和四个按键keyCode绑定键盘事件&#xff08;不推荐&#xff09;Vue.config.keyCode.自定义键名 键码 神奇的猜想div标签和click.enterbutton标签和click.enter 前文提要 …

redhat9.3配置国内yum阿里源

由于新建的Redhat9.3在未注册激活之前是没有yum源的配置文件的&#xff0c;所以需要我们自己新建一个yum源文件的配置文件 vim /etc/yum.repos.d/aliyun_yum.repo 内容如下&#xff1a; [ali_baseos] nameali_baseos baseurlhttps://mirrors.aliyun.com/centos-stream/9-str…

BART 并行成像压缩感知重建:联合重建

本文使用 variavle-density possion-disc 采样的多通道膝盖数据进行并行重建和压缩感知重建。 0 数据欠采样sampling pattern 1 计算ESPIRiT maps % A visualization of k-space dataknee = readcfl(data/knee); ksp_rss = bart(rss 8, knee);ksp_rss = squeeze(ksp_rss); figu…

河南省第五届“金盾信安杯”网络与数据安全大赛实操技能赛 部分wp(自己的一些思路和解析 )(主misc crypto )

芜湖 不评价 以下仅是自己的一些思路和解析 有什么问题或者建议随时都可以联系我 目录 题目一 来都来了 操作内容&#xff1a; flag值&#xff1a; 题目二 Honor 操作内容&#xff1a; flag值&#xff1a; 题目三 我看看谁还不会RSA 操作内容&#xff1a; flag值&a…

Three.js 3D模型爆炸分解

你是否曾想展示一些很酷的发动机的 3D 模型? 这是一种可行的方法,使用一些非常基本的数学:一个简单的分解视图。 为此,我们将使用 React-Three-Fiber,但它可以与原生 Three.js 配合使用(它与 r3f 生态系统没有深度绑定,只是对我来说迭代速度更快)。 1、准备3D模型 首…

Java 设计模式——建造者模式

目录 1.概述2.结构3.实例3.1.产品类3.2.抽象建造者类3.3.具体建造者类3.4.指挥者类3.5.测试 4.优缺点5.使用场景6.模式扩展7.创建者模式对比 1.概述 建造者模式 (Builder Pattern) 是一种创建型设计模式&#xff0c;用于创建复杂对象。它将对象的构建过程分离成独立的部分&…

在 Linux 中重命名文件和目录

目录 前言 使用 mv 命令重命名文件和目录 通过组合 mv、find 和 exec 命令重命名与某个模式匹配的多个文件 使用 rename 命令轻松重命名多个文件 总结 前言 在这篇基本命令行教程中&#xff0c;你将学习在 Linux 终端重命名文件和目录的各种方法。 如何在 Linux 终端中重命…

从前序与中序遍历序列构造二叉树(C++实现)

从前序与中序遍历序列构造二叉树 题目思路分析代码代码讲解 题目 思路分析 我们可以通过递归实现的二叉树构建函数。它根据给定的先序遍历序列和中序遍历序列构建一棵二叉树&#xff0c;并返回根节点。可以创建一个_build 函数&#xff0c;该函数负责构建二叉树的节点&#xff…