图结构实验

一、实验目的

图是最复杂的一种数据结构,同时也是表达能力最强的一种数据结构,其应用十分广泛,很多问题都可以用图来表示。本章的实验内容针对基于邻接矩阵和邻接表存储的图及其基本操作的实现展开,并结合图的具体应用,培养在实际问题中应用图结构的能力。

(1)掌握图的逻辑结构。

(2)掌握图的邻接矩阵存储结构。

(3)掌握图在邻接矩阵存储结构上遍历算法的实现。

(4)掌握图的邻接表存储结构。

(5)掌握图的邻接表存储结构上遍历算法的实现。

(6)理解图的最小生成树求解算法。

(7)理解拓扑排序算法。

(8)理解关键路径问题算法。

(9)理解图的最短路径求解算法。

二、实验环境(实验设备)

硬件:  微型计算机P4

软件:  Windows 7 + Microsoft Visual Studio2019

三、实验内容(包括题目和要求、源码、运行结果截图等)

题目1. 统计有向图各顶点的度

实验要求:

  1. 实现一个模板函数StatDegree统计有向图各顶点的度;
  2. 利用编程模板中提供的主函数,测试算法正确性。

源码:

for (int v = 0; v < g.GetVexNum(); v++)

    {

         Degree[v] = 0;



    }

    for (int v1 = 0; v1 < g.GetVexNum(); v1++)

    {



         for (int v2 = g.FirstAdjVex(v1); v2 != -1; v2 = g.NextAdjVex(v1, v2))

         {

             Degree[v2]++;

             Degree[v1]++;

         }

    }

运行结果截图:

题目2. 非递归深度优先遍历

实验要求:

(1)给无向图的邻接表类模板AdjListUndirGraph添加实现一个模板函数NonRecurDFS实现从一个顶点开始对无向图进行深度优先遍历,不使用递归。

(2)利用编程模板中提供的主函数,测试算法正确性。

源码:

template <class ElemType>

void AdjListUndirGraph<ElemType>::NonRecurDFS(int v, void (*visit)(const ElemType& e)) const

// 初始条件:存在图

// 操作结果:从顶点v出发对图进行深度优先遍历

{

    SetTag(v, true);

    ElemType e;

    GetElem(v, e);

    (*visit)(e);

    for (int w = FirstAdjVex(v); w >= 0; w = NextAdjVex(v, w))

    {

         if (!GetTag(w)) NonRecurDFS(w, visit);

    }

}



template <class ElemType>

void AdjListUndirGraph<ElemType>::NonRecurDFSTraverse(void (*visit)(const ElemType& e)) const

// 初始条件:存在图

// 操作结果:对图进行深度优先遍历

{

    int v;

    for (v = 0; v < GetVexNum(); v++)

    {   // 对每个顶点设置访问标志

         SetTag(v, false);

    }



    for (v = 0; v < GetVexNum(); v++)

    {   // 对尚未访问的顶点按DFS进行深度优先搜索

         if (!GetTag(v))   NonRecurDFS(v, visit);

    }

}

运行结果截图:

题目3:距离最远的顶点

实验要求:

  1. 实现一个模板函数FathestVex返回距离索引为v的顶点最远的顶点索引;
  2. 利用编程模板中提供的主函数,测试算法正确性。

源码:

template <class ElemType>

int FarthestVex(const AdjListUndirGraph<ElemType>& g, int v)

// 操作结果:返回距离索引为v的顶点最远的顶点索引

{



    int nums[100];

    int n = int(g.GetVexNum());

    for (int i = 0; i < n; i++) {

        nums[i] = 0;

    }

    int Max = 0;

    g.SetTag(v, true);

    LinkQueue<int> queue;

    queue.InQueue(v);

    while (!queue.Empty())

    {

         int u, w;

         queue.OutQueue(u);

         for (w = g.FirstAdjVex(u); w >= 0; w = g.NextAdjVex(u, w))

         {

             if (!g.GetTag(w))

             {

                  nums[w] = nums[u] + 1;

                  Max = max(Max, nums[w]);

                  g.SetTag(w, true);

                  queue.InQueue(w);

             }

         }

    }

    for (int i = 0; i < n; i++) {

         g.SetTag(i, false);

         if (nums[i] == Max) {

             return i;

         }

    }

    return v;

}

运行结果截图:

题目4.:判断有向图是否存在回路

实验要求:

  1. 实现一个模板函数HasCycle判断有向图g是否存在回路
  2. 利用编程模板中提供的主函数中测试算法正确性。

源码:

template <class ElemType>

bool HasCycle(const AdjListDirGraph<ElemType> g)

// 操作结果:判断有向图g是否存在回路

{

    int n = g.GetVexNum();

    int In[100];

    int Out[100];

    int visited[100];

    for (int i = 0; i < n; i++) {

         In[i] = 0;

         Out[i] = 0;

         visited[i] = 0;

    }

    for (int i = 0; i < n; i++) {

         for (int w = g.FirstAdjVex(i); w >= 0; w = g.NextAdjVex(i, w)) {

             Out[i]++;

             In[w]++;

         }

    }

    LinkQueue<int>queue;

    for (int i = 0; i < n; i++) {

         if (In[i] == 0) {

             queue.InQueue(i);

             visited[i] = 1;

         }

    }

    int idx;

    while (!queue.Empty()) {

         queue.OutQueue(idx);

         visited[idx] = 1;

         for (int w = g.FirstAdjVex(idx); w >= 0; w = g.NextAdjVex(idx, w)) {

             In[w]--;

             if (In[w] == 0) {

                  queue.InQueue(w);

             }

         }

    }

    for (int i = 0; i < n; i++) {

         if (!visited[i]) {

             return true;

         }

    }

    return false;

}

 运行结果截图:

题目5. 判断两个顶点间是否存在路径

实验要求:

(1)实现一个模板函数ExistPath判断有向图g中两个顶点i和j之间是否存在路径。

(2)利用编程模板中提供的主函数,测试算法正确性。

源码:

template <class ElemType>

bool ExistPath(const AdjListDirGraph<ElemType> g, int i, int j)

// 操作结果:判断有向图g中两个顶点i和j之间是否存在路径

{

    int n = g.GetVexNum();

    for (int i = 0; i < n; i++) {

         g.SetTag(i, false);

    }

    g.SetTag(i, true);

    LinkQueue<int> queue;

    queue.InQueue(i);

    while (!queue.Empty())

    {

         int u, w;

         queue.OutQueue(u);

         for (w = g.FirstAdjVex(u); w >= 0; w = g.NextAdjVex(u, w))

         {

             if (w == j) {

                  return true;

             }

             if (!g.GetTag(w))

             {

                  g.SetTag(w, true);

                  queue.InQueue(w);

             }

         }

    }

    return false;

}

运行结果截图:

四、实验小结(包括实验过程中遇到问题和解决方法、心得体会等)

通过做图结构实验,我们可以得到以下总结:

1. 图形的拓扑结构:对于一组给定的节点和它们之间的边,可以确定它们之间的拓扑关系,例如是否为连通图、是否存在环、是否为树状结构等。

2. 组成图形的基本元素:图形由节点和边组成。通过实验可以了解两者的性质和特点。

3. 对节点和边进行操作:在图形上,我们可以包括删除、添加、连接、断开等一系列操作,这些操作会影响整个图形的结构和性质。

4. 搜索算法:在拓扑结构中,搜索是一个非常重要的问题,因为它涉及到从起始节点遍历到目标节点的路径问题。实验可以帮助我们了解不同的搜索算法,并比较它们之间的优缺点。

5. 培养了分析问题和解决问题的思维能力:通过解决问题来分析和理解不同数据结构,训练自己独立解决实际问题的能力。

总之,通过做图结构实验,我们可以更深入地了解图形结构的本质和基本原则,这对于许多领域的理论研究和实际应用都具有重要的价值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值