《数据结构与算法》实验:图结构的建立与搜索

2023-11-02

《数据结构与算法》实验和课程Github资源 

《数据结构与算法》实验:线性结构及其应用——算术表达式求值

《数据结构与算法》实验:树型结构的建立与遍历

《数据结构与算法》实验:图结构的建立与搜索

《数据结构与算法》实验:查找结构的实验比较——二叉查找树BST & 二分(折半)查找

《数据结构与算法》实验:排序算法实验比较——选择排序 & 堆排序

《数据结构与算法》实验报告

学生姓名

郭茁宁

院(系)

计算机科学与技术

  

1183710109

 

软件工程

实验时间

2019年12月6日(周五)

实验地点

格物213室

实验项目

实验3/5图型结构的建立与搜索(3学时)

实验目的:将课程的基本原理、技术和方法与实际应用相结合,训练和提高学生组织、存储和处理信息的能力,以及复杂问题的数据结构设计能力和程序设计能力,培养软件设计与开发所需要的实践能力。

实验要求:灵活运用基本的数据结构和算法知识,对实际问题进行分析和抽象;结合程序设计的一般过程和方法为实际问题设计数据结构和有效算法;用高级语言对数据结构和算法进行编程实现、调试,测试其正确性和有效性。

实验内容:

      图的搜索(遍历)算法是图型结构相关算法的基础,本实验要求编写程序演示两种典型存储结构的建立和搜索(遍历)过程。

  1. 分别实现图的邻接矩阵、邻接表存储结构的建立算法,分析和比较各建立算法的时间复杂度以及存储结构的空间占用情况;
  2. 实现图的邻接矩阵、邻接表两种存储结构的相互转换算法;
  3. 在上述两种存储结构上,分别实现图的深度优先搜索(递归和非递归)和广度优先搜索算法。并以适当的方式存储和显示相应的搜索结果(深度优先或广度优先生成森林(或生成树)、深度优先或广度优先序列和编号);
  4. 分析搜索算法的时间复杂度;
  5. 以文件形式输入图的顶点和边,并显示相应的结果。要求顶点不少于10个,边不少于13个;
  6. 软件功能结构安排合理,界面友好,便于使用。

数据结构定义:

class Point : 邻接表的点

class Point::Edge : 邻接表点所连的边

class Node : 邻接表点的链表元

class Queue : 队列(点)

class Stack : 栈(点)

算法设计与分析(要求画出核心内容的程序流程图):

  1. 邻接表的存储:

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

存储空间为O(N+M),即边和点的总数

  1. 邻接表à邻接矩阵

scanf("%d%d%d",&l,&r,&v);

matrix[l][r]/*=matrix[r][l]*/=v;    // 邻接表-->邻接矩阵

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

  1. 深度优先搜索遍历

复杂度:邻接表-深搜-递归    O(n+2×m)

        邻接矩阵-深搜-递归  O(n²)

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

  1. 深度优先搜索(非递归)遍历

复杂度:邻接表-深搜-非递归    O(n+2×m)

        邻接矩阵-深搜-非递归  O(n²)

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

  1. 广度优先搜索遍历

复杂度:邻接表-广搜    O(n+2×m)

        邻接矩阵-广搜  O(n²)

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

实验测试结果及结果分析:

Adjacency_Matrix :

. 1 . . . . . . 1 . . .

. . 1 . . 1 . . . . . .

. . . 1 . . . . . . . .

. . . . 1 . . . . . . .

. . . . . . . 1 . . . 1

. . . . . . . . 1 . . .

. . 1 . . 1 . . . . . .

. . . 1 . . 1 . . . . .

. 1 . . . . . . . . . .

. . . . . 1 . . 1 . . .

. . . . . . 1 . . 1 . .

. . . . . . . 1 . . 1 .

Adjacency_List :

a : ( a --> c ) ( a --> b )

b : ( b --> d ) ( b --> e )

e : ( e --> g )

g : ( g --> i )

i : ( i --> j ) ( i --> k )

d : ( d --> c )

f : ( f --> d ) ( f --> e )

k : ( k --> f ) ( k --> g )

c : ( c --> b )

l : ( l --> c ) ( l --> d )

h : ( h --> l ) ( h --> f )

j : ( j --> k ) ( j --> h )

 

List :

 

DFS_recur      a c b d e g i j k f h l

DFS_non_recur  a b e g i k f j h l d c

BFS            a c b d e g i j k h f l

 

Matrix :

 

DFS_recur      a b e g i k f d c j h l

DFS_non_recur  a c b d e g i j h l f k

BFS            a b c e d g i k j f h l

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

测试结果良好,显示界面排版清晰有条理,答案正确

 

问题及解决方法:

  1. 类的互相调用:点Point和边Edge类的成员变量都含有另一个的类,在不使用头文件的形况下无法调用,所以只能用类的嵌套,在调用Edge时使用Point::Edge;
  2. 在搜索的过程中,要在入队/压栈/递归前就标记访问,若在出队/压栈/递归前时才标记,则会出现某些点多次遍历的情况;
  3. 问题目标程序中许多的重复/相似操作,通过面向对象的操作可以将功能进行封装处理,节约代码量,提高主程序可读性;

源程序名称:lab3.cpp

注意:正文文字为宋体小4号,图中文字为宋体5号。行距为多倍行距1.25。

      源程序与此报告打包提交,压缩包采用学号命名。

       
       
       
   
 
 
 
 
 
 
 

注意:正文文字为宋体小4号,图中文字为宋体5号。行距为多倍行距1.25。

      源程序与此报告打包提交,压缩包采用学号命名。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
class Point
{
public:
    class Edge
    {
    public:
        int val;
        Edge *next_edge;
        Point *origin, *terminal;
        Edge(){next_edge=NULL;origin=terminal=NULL;}
        void adjacency(Point *ori, int edge_val, Point *term)
        {
            val=edge_val;
            origin=ori;
            terminal=term;
            next_edge=ori->last_edge;
            ori->last_edge=this;
        }
    };
    int num;
    bool vis;
    Edge *last_edge;
    Point *next_point;
    Point(){last_edge=NULL;next_point=NULL;}
    void add_point(int number,Point **head)
    {
        num=number;
        if (*head==NULL) *head=this;
    	else
        {
            Point *back=*head;
            for (;back->next_point!=NULL;back=back->next_point);
            back->next_point=this;
        }
    }
    void add_edge(int edge_val, int term_num, Point *head)
    {
        Edge *new_edge=new Edge();
        Point *term;
        for (term=head;term!=NULL;term=term->next_point) if (term->num==term_num) break;
        if (term==NULL) printf("Error");
        new_edge->adjacency(this, edge_val, term);
    }
};
class Node
{
public:
	Point *data;
	Node *next;
	Node(){next=NULL;}
    void add(Point *p, Node **last)
    {
        data=p;
		if ((*last)!=NULL) (*last)->next=this;
        (*last)=this;
    }
};
class Queue//head<x<=tail
{
public:
	Node *head,*tail;
	Queue()
	{
		head=new Node();
		head->next=NULL;
		tail=head;
	}
	bool empty(){return head==tail;}
	void push(Point *member)
	{
		Node *x=new Node();
		x->data=member;
		tail->next=x;
		x->next=NULL;
		tail=x;
	}
	Point *pop()
	{
		if (empty()) return NULL;
		Point *pop_obj=front();
		Node *last=head;
		head=head->next;
		delete last;
		return pop_obj;
	}
	Point *front(){return head->next->data;}
};
class Stack
{
public:
	Node *top;
    Stack(){top=new Node();}
	bool empty(){return top->next==NULL;}
	void push(Point *member)
	{
		Node *x=new Node();
		x->data=member;
		x->next=top;
		top=x;
	}
	Point *pop()
	{
		if (empty()) return NULL;
		Point *pop_obj=get_top();
		Node *last=top;
		top=top->next;
		delete last;
		return pop_obj;
	}
	Point *get_top()
	{
		if (empty()) return NULL;
		return top->data;
	}
};

char str[28] = ".abegidfkclhj";

//  邻接表
Point *Find_Point(int point_num,Point *head){for (Point *x=head;x!=NULL;x=x->next_point) if (x->num==point_num) return x;return NULL;}
void Setclear(Point *head){for (Point *x=head;x!=NULL;x=x->next_point) x->vis=false;}
void Print_List(Node *first){for (Node *x=first;x!=NULL;x=x->next) printf(" %c",str[x->data->num]);printf("\n");}
void DFS_points(Point *p, Node **first, Node **last, Point *start)
{
    Node *x=new Node();
    if (p==start) *first=x;
    x->add(p,last);
    for (Point::Edge *e=p->last_edge;e!=NULL;e=e->next_edge) if (!e->terminal->vis)
    {
        e->terminal->vis=true;
        DFS_points(e->terminal, first, last, start);
    }
}
void DFS_recur(Point *head, Point *start)//邻接表-深搜-递归
{
    Setclear(head);
    Node *first=NULL, *last=NULL;
    start->vis=true;
    DFS_points(start, &first, &last, start);
    Print_List(first);
}
void DFS_non_recur(Point *head, Point *start)//邻接表-深搜-非递归
{
    Setclear(head);
    Stack sta;
    sta.push(start);
    start->vis=true;
    Node *x,*first,*last=NULL;
    while (!sta.empty())
    {
        x=new Node();
        if (sta.get_top()==start) first=x;
        x->add(sta.pop(),&last);
        for (Point::Edge *e=x->data->last_edge;e!=NULL;e=e->next_edge)
        if (e->terminal->vis==false)
        {
            e->terminal->vis=true;
            sta.push(e->terminal);
        }
    }
    Print_List(first);
}
void BFS(Point *head, Point *start)//邻接表-广搜
{
    Setclear(head);
    Queue qu;
    qu.push(start);
    Node *x,*first,*last=NULL;
    start->vis=true;
    while (!qu.empty())
    {
        x=new Node();
        if (qu.front()==start) first=x;
        x->add(qu.pop(),&last);
        for (Point::Edge *e=x->data->last_edge;e!=NULL;e=e->next_edge)
            if (e->terminal->vis==false) 
			{
                e->terminal->vis=true;
            	qu.push(e->terminal);
			}
    }
    Print_List(first);
}
void Print_Adjacency_List(Point *head)//输出邻接表
{
    for (Point *p=head;p!=NULL;p=p->next_point)
    {
        printf("%c :",str[p->num]);
        for (Point::Edge *e=p->last_edge;e!=NULL;e=e->next_edge)
            printf(" ( %c --> %c )",str[e->origin->num],str[e->terminal->num]);
        cout<<endl;
    }
}

//邻接矩阵
void Print_Adjacency_Matrix(int n, int ***matrix)//输出邻接矩阵
{
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
            if ((*matrix)[i][j]!=0) cout<<(*matrix)[i][j]<<' ';
            else cout<<'.'<<' ';
        printf("\n");
    }
}
void Shift_From_Matrix_To_List(Point **head, int n, int ***matrix)//邻接矩阵-->邻接表
{
    Point *x;
    for (int i=1;i<=n;i++)
	{
		x=new Point();
        x->add_point(i,head);
	}
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++) if ((*matrix)[i][j]>0)
        {
            Find_Point(i,*head)->add_edge((*matrix)[i][j],j,*head);
            Find_Point(j,*head)->add_edge((*matrix)[i][j],i,*head);
        }
    }
}
#define N 100
bool v[N+10];
int trave_order[N+10],trave_num;
void Print_List_Matrix(){for (int i=1;i<=trave_num;i++) printf(" %c",str[trave_order[i]]);printf("\n");}
void DFS_points_Matrix(int p, int n, int ***matrix)//邻接矩阵-深搜-递归
{
    trave_order[++trave_num]=p;
    for (int i=1;i<=n;i++) if ((*matrix)[p][i]&&!v[i])
    {
        v[i]=true;
        DFS_points_Matrix(i,n,matrix);
    }
}
void DFS_recur_Matrix(int start, int n, int ***matrix)//邻接矩阵-深搜-递归
{
    memset(v,0,sizeof(v));
    trave_num=0;
    v[start]=true;
    DFS_points_Matrix(start, n, matrix);
    Print_List_Matrix();
}
void DFS_non_recur_Matrix(int start, int n, int ***matrix)//邻接矩阵-深搜-非递归
{
    memset(v,0,sizeof(v));
    stack<int> sta;
    trave_num=0;
    sta.push(start);
    v[start]=true;
    while (!sta.empty())
    {
        trave_order[++trave_num]=sta.top();
        sta.pop();
        for (int i=1;i<=n;i++) if ((*matrix)[trave_order[trave_num]][i]&&!v[i])
        {
            v[i]=true;
            sta.push(i);
        }
    }
    Print_List_Matrix();
}
void BFS_Matrix(int start, int n, int ***matrix)//邻接矩阵-广搜
{
    memset(v,0,sizeof(v));
    queue<int> qu;
    trave_num=0;
    v[start]=true;
    qu.push(start);
    while (!qu.empty())
    {
        trave_order[++trave_num]=qu.front();
        qu.pop();
        for (int i=1;i<=n;i++) if ((*matrix)[trave_order[trave_num]][i]&&!v[i])
        {
            v[i]=true;
            qu.push(i);
        }
    }
    Print_List_Matrix();
}

int main()
{
    freopen("init.txt","r",stdin);
    //freopen("answer.txt","w",stdout);
	int n,m,start;  // n: points ; m: edges
    Point *head=NULL,*x;
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		x=new Point();
        x->add_point(i,&head);
	}
    scanf("%d",&m);
    int **matrix=new int *[n+1];
    for (int i=0;i<=n;i++) matrix[i]=new int [n+1];// Build Adjacency Matrix
    for (int i=0;i<=n;i++) for (int j=0;j<=n;j++) matrix[i][j]=0;
    for (int i=1,l,r,v;i<=m;i++)
    {
        scanf("%d%d%d",&l,&r,&v);
        matrix[l][r]/*=matrix[r][l]*/=v;    // 邻接表-->邻接矩阵
        Find_Point(l,head)->add_edge(v,r,head);
        //Find_Point(r,head)->add_edge(v,l,head); //  无向图(若为有向图则删除)
    }
    scanf("%d",&start);//   搜索起始点(默认为1)
    cout<<endl;
    // Shift_From_Matrix_To_List(&head, n, &matrix);                        //邻接矩阵-->邻接表
    cout<<"Adjacency_Matrix :"<<endl;   Print_Adjacency_Matrix(n,&matrix);  //打印邻接矩阵
    cout<<"Adjacency_List :"  <<endl;   Print_Adjacency_List(head);         //打印邻接表
    cout<<endl<<"List :"<<endl<<endl;
    cout<<"DFS_recur     ";DFS_recur    (head, Find_Point(start, head));    //邻接表-深搜-递归  O(n+2×m)
    cout<<"DFS_non_recur ";DFS_non_recur(head, Find_Point(start, head));    //邻接表-深搜-非递归O(n+2×m)
    cout<<"BFS           ";BFS          (head, Find_Point(start, head));    //邻接表-广搜      O(n+2×m)
    cout<<endl<<"Matrix :"<<endl<<endl;
    cout<<"DFS_recur     ";DFS_recur_Matrix     (start, n, &matrix);        //邻接矩阵-深搜-递归   O(n²)
    cout<<"DFS_non_recur ";DFS_non_recur_Matrix (start, n, &matrix);        //邻接矩阵-深搜-非递归 O(n²)
    cout<<"BFS           ";BFS_Matrix           (start, n, &matrix);        //邻接矩阵-广搜       O(n²)
    fclose(stdin);
    fclose(stdout);
    return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《数据结构与算法》实验:图结构的建立与搜索 的相关文章

随机推荐

  • 虚拟机VMware的下载与安装——详细教程

    学习Linux过程中少不了要使用Linux系统 但是有的新手连 Windows 的安装都不太熟悉 更别提 Linux 的安装了 即使安装成功了 也有可能破坏现有的 Windows 系统 比如导致硬盘数据丢失 Windows 无法开机等 所以
  • 【Android】MVC,MVP,MVVM三种架构模式的区别

    MVC 传统的代码架构模式 仅仅是对代码进行了分层 其中的C代表Controller 控制的意思 将代码划分为数据层 视图层 控制层 三层之间可以任意交互 MVP MVP是在MVC基础上改进而来的一种架构 其中的P代表Presenter 主
  • 关于queue_depth的调整

    queue depth是指hdisk层面上命令队列的深度 它针对的是hdisk 如果有多路径软件的话 它针对的就是多路径的hdisk 如powerdisk dlmfdrv 那如何调整queue depth 何时调整呢 more 首先我们来讲
  • STEAM创客教育如何激发孩子的学习兴趣

    如何才能够提高孩子的学习兴趣呢 这是任何一种教育形式都应该思考的问题 在STEAM创客教育中 格物斯坦小坦克告诉你激发孩子的学习兴趣主要包括以下几个方面 数学与艺术的结合 孩子最早接触的艺术是涂色 最早接触的数学是数字 所以数学和艺术结合最
  • MarkDown标题自动添加编号

    转自 MarkDown标题自动添加编号 说明 这是一个实现给本地 Markdown 文件添加标题编号的 python 脚本 可与 Markdown文件自动生成目录 搭配使用 比如说你现在有一个 Markdown 文件 这个文件有很多级标题且
  • Linux系统中关闭看门狗的指令

    1 echo V gt dev watchdog 关掉看门狗
  • Python读取超时(Read timed out.)

    HTTPConnectionPool host XXXXXXXX port xxxx Read timed out XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Read timed out 解决方案 pip3 de
  • 编程语言python入门要电脑什么配置能带动-Python是万能的编程语言吗?这五大用途很重要!...

    这个真的不好说 因为Python可以做的事情有很多 用途也是非常广泛的 尤其是在以下领域中更具有作用 1 web开发 Python是一种解释型的脚本语言 开发效率高 所以非常适合用来做web开发 Python有上百种web开发框架 有很多成
  • 【ML on Kubernetes】第 1 章:机器学习的挑战

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • aps是什么意思_aps画幅是什么意思

    APS的原意是指 高级摄影系统 Advanced Photo System 是数码相机普及前的一种过渡产品 它仍使用胶卷 但在胶卷和暗盒上通过磁性材料和数字计划 记录了很多相关数据 还有一个特点就是APS允许用户随时在三种画幅格式切换 它们
  • 特征融合方法

    概述 基本概念 在很多工作中 融合不同尺度的特征是提高分割性能的一个重要手段 低层特征分辨率更高 包含更多位置 细节信息 但是由于经过的卷积更少 其语义性更低 噪声更多 高层特征具有更强的语义信息 但是分辨率很低 对细节的感知能力较差 如何
  • MyBatis PostgreSQL实现数组类型的操作

    我的GitHub Powerveil GitHub 我的Gitee Powercs12 powercs12 Gitee com 皮卡丘每天学Java 最近在学习数据库PostgreSQL 遇到如何实现对数组类型的数据操作 试着自己尝试学习实
  • UE5关于高亮显示物体轮廓线

    描边材质如果是透明的话 不会显示描边 材质参数勾选 允许自定义深度写入 即可 材质参考这个文章 https blog csdn net Axiang 0123 article details 121168272 ops request mi
  • 多标签分类怎么做?教你4招

    首先简单介绍下 多标签分类与多分类 多任务学习的关系 多分类学习 Multi class 分类器去划分的类别是多个的 但对于每一个样本只能有一个类别 类别间是互斥的 例如 分类器判断这只动物是猫 狗 猪 每个样本只能有一种类别 就是一个三分
  • iview表格单元格动态绑定class/style,不刷新表格本身.

    对订单表格的时间列 动态检验时间是否过期并用颜色标记 关键点是在render中的渲染函数动态绑定class style 小问题是表格数据本身是确定的不再变化 我们又需要跟随时间变化 所以首选需要一个定时器 定时器不能放在表格里会导致计时器不
  • 我的第一个小爬虫程序-python

    爬什么 爬代理服务器网站的服务器 端口 代理种类 所在地区 更新日期 今日评分 总的评分 可用 速度测评信息 这样的网页有七八个 好在网址明名很规则 具体说就是爬很多的这样的html代码里的信息 span class tbBottomLin
  • 【论文】AMC:AutoML用于移动设备上的模型压缩和加速

    摘要 模型压缩是在计算资源有限且功率预算紧张的移动设备上高效部署神经网络模型的有效技术 传统的模型压缩技术依赖于手工制作的特性 需要领域专家在模型大小 速度和精度之间进行权衡 以探索大的设计空间 这通常是次优和耗时的 在本文中 我们提出了用
  • 不想安装环境,我如何与前端工程师远程协作开发?

    最近我的一名前端工程师朋友Wendy正基于自己的想法开发一个开源项目 为了让用户了解并试用项目 她准备用Nextjs这个前端框架搭建一个用户使用手册网站 写文档的时候 她想到了我这个产品经理朋友 希望我能够帮助她一起开发这个网站 提供更好的
  • 【Qt/C++异常笔记】“QHostInfo”: 不是类或命名空间名称

    文章目录 异常描述 异常原因 解决方法 开发环境 异常描述 在读取主机名称时 需要用到 QHostInfo localHostName 但是使用了之后一直报错 QHostInfo 不是类或命名空间名称 头文件中引用 include
  • 《数据结构与算法》实验:图结构的建立与搜索

    数据结构与算法 实验和课程Github资源 数据结构与算法 实验 线性结构及其应用 算术表达式求值 数据结构与算法 实验 树型结构的建立与遍历 数据结构与算法 实验 图结构的建立与搜索 数据结构与算法 实验 查找结构的实验比较 二叉查找树B