《数据结构与算法设计》实验报告书之图的遍历操作

《数据结构与算法设计》实验报告书之图的遍历操作

实验项目
图的遍历操作

实验目的
掌握有向图和无向图的概念;掌握邻接矩阵和邻接链表建立图的存储结构;掌握DFS及BFS对图的遍历操作;了解图结构在人工智能、工程等领域的广泛应用。

实验内容
采用邻接矩阵和邻接链表其中一种作为图的存储结构,完成有向图和无向图的DFS和BFS操作。

算法设计分析

(一)数据结构的定义
图遍历又称图的遍历,属于数据结构中的内容。指的是从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次。图的遍历操作和树的遍历操作功能相似。图的遍历是图的一种基本操作,图的许多其它操作都是建立在遍历操作的基础之上。
由于图结构本身的复杂性,所以图的遍历操作也较复杂,主要表现在以下四个方面:
① 在图结构中,没有一个“自然”的首结点,图中任意一个顶点都可作为第一个被访问的结点。
② 在非连通图中,从一个顶点出发,只能够访问它所在的连通分量上的所有顶点,因此,还需考虑如何选取下一个出发点以访问图中其余的连通分量。
③ 在图结构中,如果有回路存在,那么一个顶点被访问之后,有可能沿回路又回到该顶点。
④ 在图结构中,一个顶点可以和其它多个顶点相连,当这样的顶点访问过后,存在如何选取下一个要访问的顶点的问题。
图的存储结构定义为邻接矩阵:

/*定义图存储结构*/
#define maxn 500        // 图中顶点数
#define maxe 1000       // 图中边数
typedef struct{
    int v[maxn+1];            // 存放顶点信息
    int arcs[maxn+1][maxn+1];    // 邻接矩阵
}graph;

(二)总体设计

实验总共包括六个函数:主函数,无向图的建立函数,有向图的建立函数,DFS遍历函数,BFS遍历算法函数,打印邻接矩阵函数。
主函数:统筹调用各个函数以实现相应功能
Int main()
void execute()
无向图的建立函数:建立无向图的邻接矩阵
void creatadi(graph &g,int n,int e)
有向图的建立函数:建立有向图的邻接矩阵
void creatadj(graph &g,int n,int e)
DFS遍历函数:利用深度优先遍历图的方法遍历图
void DFS1(int cur,graph &g,int n)
BFS遍历函数:利用广度优先遍历图的方法遍历图
void BFS1(graph &g,int n)
打印邻接矩阵函数:利用遍历邻接矩阵的方法打印图
void printArr(graph &g,int n,int e)

(三)各函数的详细设计:

主函数main()
主要就是进行功能的实现。

无向图的建立函数void creatadi(graph &g,int n,int e):
建立无向图的邻接矩阵,由于无向图是对称的,所以邻接矩阵是对称的。

有向图的建立函数void creatadj(graph &g,int n,int e):
建立有向图的邻接矩阵,由于有向图是单边的,所以邻接矩阵是不对称的。

DFS遍历函数void DFS1(int cur,graph &g,int n) :
利用深度优先遍历图的方法遍历图,主要是通过递归来一个一个顶点找过去,走过的标记一下,没路了在回去找。

BFS遍历函数void BFS1(graph &g,int n):
利用广度优先遍历图的方法遍历图,主要运用了队列的结构,将与该顶点有联系的都放进队列,之后再把队列里面的值打印出来。

打印邻接矩阵函数void printArr(graph &g,int n,int e):
利用遍历邻接矩阵的方法打印图

实验测试结果
无向图建立以及结果:

《《数据结构与算法设计》实验报告书之图的遍历操作》
《《数据结构与算法设计》实验报告书之图的遍历操作》
有限图创建以及结果:
《《数据结构与算法设计》实验报告书之图的遍历操作》
《《数据结构与算法设计》实验报告书之图的遍历操作》
实验总结:(100字到200字)

此部分附上主要程序代码和相关的注释说明、调试数据及过程、问题及解决办法。 (最重要)
(1)调试过程中主要遇到哪些问题?是如何解决的?
答:在建立图的存储结构的时候还是遇见过一些问题的,数组开的太大,导致程序无法运行,还有就是图的遍历这一块地方,BFS这个通过队列来放数据时,出现过一点小问题,不过问题不是很大,能够自己解决。
(2)经验和体会
答:还是那句老话,多敲代码自己练习,有时间把多复习多上网查查资料,增加自己对图的遍历的理解。

附录 实验程序代码(该部分请加注释)

/picture.h函数代码/

#define maxn 500        // 图中顶点数
#define maxe 1000       // 图中边数
typedef struct{
    int v[maxn+1];            // 存放顶点信息
    int arcs[maxn+1][maxn+1];    // 邻接矩阵
}graph;

//无向图的邻接矩阵
void  creatadi(graph &g,int n,int e)
{
    int i, j, k;
    for (i=1; i<=n;  i++ )
        for (j=1; j<=n; j++)
            g.arcs[i][j]=0;
    for (k=1; k<=e; k++)
    {
        std::cout<<"第"<<k<<"条边的位置:"<<endl;
        std::cin>>i>>j;         //输入一条边(i,j)
        g.arcs[i][j] = 1;
        g.arcs[j][i] = 1;
    }
}

//有向图的邻接矩阵
void  creatadj(graph &g,int n,int e)
{
    int i, j, k;
    for (i=1; i<=n;  i++ )
        for (j=1; j<=n; j++)
            g.arcs[i][j] = 0;
    for (k=1; k<=e; k++)
    {
        std::cout<<"第"<<k<<"条边的位置:"<<endl;
        std::cin>>i>>j;         //输入一条弧<i,j>
        g.arcs[i][j] = 1;
    }
}

void  printArr(graph &g,int n,int e){
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            cout<<g.arcs[i][j]<<" ";
        }
        cout<<endl;
    }
}

//深度优先遍历无向图
void DFS1(int cur,graph &g,int n){
    std::cout<<cur<<" ";
    sum++;
    if(sum == n){
        return ;
    }
    int i;
    for(i=1;i<=n;i++){
        if(g.arcs[cur][i] == 1 && g.v[i] == 0){
            g.v[i] = 1;
            DFS1(i,g,n);
        }
    }
}

//广度优先遍历无向图
void BFS1(graph &g,int n){
    int head = 1,tail = 1,i,cur;
    que[tail] = 1;
    tail++;
    g.v[1] = 1;
    while(head < tail && tail <= n){
        cur = que[head];
        for(i=1;i<=n;i++){
            if(g.arcs[cur][i] == 1 && g.v[i] == 0){
                que[tail] = i;
                tail++;
                g.v[i] = 1;
            }
            if(tail > n){
                break;
            }
        }
        head++;
    }
    for(i=1;i<=n;i++)
        std::cout<<que[i]<<" ";
    std::cout<<std::endl;
}

/menu.h菜单函数代码/

void menu(){
    std::cout<<"\n";
    std::cout<<" ************************图的应用************************\n";
    std::cout<<" *                                                      *\n";
    std::cout<<" *     a:创建无向图的邻接矩阵   b:创建有向图的邻接矩阵  *\n";
    std::cout<<" *     c:DFS遍历                d:BFS遍历               *\n";
	std::cout<<" *     g:退出程序                                       *\n";
    std::cout<<" *                                                      *\n";
    std::cout<<" ********************************************************\n";
}

/主函数代码/

#include <iostream>
using namespace std;

int sum = 0,que[10001];
#include "menu.h"
#include "picture.h"

int main()
{
    void execute();
	execute();
	return 0;
}
void execute()
{
	for(;;)
	{
		menu();
		graph s;
        char a;
		int n,e;
		cin>>a;
		switch(a)
		{
			case 'a':
			    cout<<"请输入顶点个数:"<<endl;
			    cin>>n;
			    cout<<"请输入边的个数:"<<endl;
			    cin>>e;
			    creatadi(s,n,e);
			    printArr(s,n,e);
				break;
            case 'b':
			    cout<<"请输入顶点个数:"<<endl;
			    cin>>n;
			    cout<<"请输入边的个数:"<<endl;
			    cin>>e;
			    creatadj(s,n,e);
			    printArr(s,n,e);
				break;
			case 'c':
			    cout<<"该图DFS遍历为:"<<endl;
			    for(int k=1;k<=n;k++)
                    s.v[k] = 0;
			    s.v[1] = 1;
			    DFS1(1,s,n);
				break;
			case 'd':
			    cout<<"该图BFS遍历为:"<<endl;
			    for(int k=1;k<=n;k++)
                    s.v[k] = 0;
			    BFS1(s,n);
				break;
			case 'e':
				cout<<" 再见!"<<endl;
				return ;
            default:
                cout<<"输入的字符有误,请重新输入!!"<<endl;
                break;
		}
	}
}
    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/qq_42967398/article/details/84970748
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞