/*在程序设计中更多的是注重程序的逻辑性,因此在设计验证实验程序中,更多的是考虑程序完整性,
也就是在设计程序时有一个清晰地思路,经过认真的研究,对面向对象的程序设计语言的前提下,
对抽象数据类型的了解显得更为重要,在做实验之前更多的是要知道程序的功能,以便设计更为人性化
程序
*/
/*该实验采用邻接矩阵作为存储结构
首先建立以邻接矩阵为存储结构的图的抽象数据类型
方法的实现:对建立的无向图,进行深度及广度优先遍历,因此该实验主要是设计抽象数据类型,
并做好算法的实现与调用。
*/
/*生成树的求解:
生成树可以在图的遍历中得到:
在一个连通无向图G=(V,E)中,如果从任一个顶点开始进行深度优先遍历,必定将边集E分成两个集合T和B,其中T是遍历过程中经历的边的集合,
B是剩余的边的集合。显然,边集T和图G所有顶点一起构成连通图G的一棵生成树。因此,修改深度优先遍历算法,输出遍历所经过的边。
*/
#include<iostream.h>
const int MaxSize=10;
template<class T>
class MGraph
{
public:
MGraph(T a[],int n,int e); //构造函数
~MGraph() {} //析构函数
void DFSTraverse(int v); //深度优先遍历
void DFSTraverse1(int v); //深度优先非递归算法 ,这里的v代表数组元素的下标
void DFSTraverse2(int v);
void DFSTraverseSCH(int v); //生成树求解,利用深度优先遍历算法改进即可
void BFSTraverse(int v); //广度优先遍历
private:
T vertex[MaxSize]; //存放图中顶点的数组
int arc[MaxSize][MaxSize]; //存放图中边的数组,邻接存储的核心部分,其取值就是两个顶点之间有没有边相连
int vertexNum,arcNum;
int visited[MaxSize];
};
//构造函数
template<class T>
MGraph<T>::MGraph(T a[],int n,int e)
{
vertexNum=n; arcNum=e;
for(int i=0;i<vertexNum;i++)
vertex[i]=a[i]; //初始化定点数组,将定点数组赋值
for(i=0;i<MaxSize;i++)
visited[i]=0;
for(i=0;i<vertexNum;i++) //初始化邻接矩阵
for(int j=0;j<vertexNum;j++)
arc[i][j]=0;
for(int k=0;k<arcNum;k++) //程序在此处跳转的原因是,arcNum赋给的初值为零
{
int i,j;
cout<<"请输入两位正整数:"<<endl;
cin>>i>>j;
arc[i][j]=1;
arc[j][i]=1; //由于其为无向图邻接矩阵,矩阵关于对角线对称
}
}
template<class T>
void MGraph<T>::DFSTraverse(int v) //深度优先遍历递归算法
{
//int visited[MaxSize]; //visited[数组一定要初始化】,初始化问题是一个相当重要的问题,在下面的判断语句中,其显得尤为重要,不然的话程序将跳出循环,不向下执行
/*for(int i=0;i<MaxSize;i++)
visited1[i]=0;*/
cout<<vertex[v]<<" "; //visited 数组不能再这里进行初始化,递归调用将使数组不断地初始化,陷入死循环
visited[v]=1;
for(int j=0;j<vertexNum;j++)
{ if(arc[v][j]==1&&visited[j]==0)
DFSTraverse(j);
}
}
template<class T>
void MGraph<T>::DFSTraverse1(int v)
{
int s[MaxSize];
int visited1[MaxSize];
for(int i=0;i<MaxSize;i++)
visited1[i]=0;
int top=-1;
cout<<vertex[v]<<" ";
visited1[v]=1;
s[++top]=v; //利用栈的思想
while(top!=-1)
{
v=s[top]; //初步调试是栈顶元素无法取出,v没有进栈
for(int j=0;j<vertexNum;j++)
if(arc[v][j]==1&&visited1[j]==0)
{
cout<<vertex[j]<<" ";
visited1[j]=1; //这里的visited1该函数中的visited独立与主函数中的visited数组
s[++top]=j;
//break;
}
if(j==vertexNum) top--;
}
}
/*在这个算法中我们需要注意的是:visited1数组的记录问题,由于在类中已经定义了一个visited数组,一定要区别两者,在编写程序运行无误后,并不等于我们就已经成功,我
要做的还要验证程序是否符合运算的结果,在调试程序的过程中,寻找到这种方法,我们才能在编写程序中寻找到乐趣。在非递归算法中一定要理解栈的概念,它能帮助你理解程序的逻辑性
在调试程序总起着至关重要的作用*/
template<class T>
void MGraph<T>::DFSTraverse2(int v)
{
int s[MaxSize];
int visited1[MaxSize];
for(int i=0;i<MaxSize;i++)
visited1[i]=0;
int top=-1;
cout<<vertex[v]<<" ";
visited1[v]=1; //这里的visited1为正确,在以后的程序中其没有任何变化
s[++top]=v; //利用栈的思想
while(top!=-1)
{
v=s[top]; //初步调试是栈顶元素无法取出,v没有进栈; 问题的关键是让最开始的顶点出栈
for(int j=0;j<vertexNum;j++)
{ if(arc[v][j]==1&&visited1[j]==0)
{
//cout<<vertex[j]<<" ";
cout<<"("<<v<<j<<")"<<" ";
visited1[j]=1; //这里的visited1该函数中的visited独立与主函数中的visited数组
s[++top]=j;
//break;
}
//if(j==vertexNum) top--;
}
if(top>0) //此函数设计是让栈顶元素无法出栈
{
cout<<vertex[s[top]]<<" ";
top--;
}
if(top==0)
top--;
}
}
template<class T>
void MGraph<T>::DFSTraverseSCH(int v) //由于此算法采用的visited数组同深度优先遍历算法是一样的,为避免发生两者的冲突,建立一一验证
{
visited[v]=1;
for(int j=0;j<vertexNum;j++)
if(arc[v][j]==1&&visited[j]==0)
{
cout<<"("<<v<<j<<")"<<" ";
DFSTraverseSCH(j);
}
}
/*
1,visited2数组初始化
2,重复下面的操作直到front==rear
队头元素后移;
以v存在未被访问的结点
访问标志置1;
队尾数组下标后移
*/
template<class T>
void MGraph<T>::BFSTraverse(int v)
{
int front,rear;
int visited2[MaxSize],q[MaxSize];
for(int i=0;i<MaxSize;i++)
visited2[i]=0;
front=rear=-1;
cout<<vertex[v]<<" ";
visited2[v]=1;
q[++rear]=v;
while(front!=rear)
{
v=q[++front]; //此种方法模拟出队,就是头数组下标后移
for(int j=0;j<vertexNum;j++)
if(arc[v][j]==1&&visited2[j]==0)
{
cout<<vertex[j]<<" ";
visited2[j]=1;
q[++rear]=j;
}
}
}
void main()
{
//char a[4]={"we","are","good","!"}; 定义一个数组,其存储的是图中的结点元素,对于整数元素不需要将双引号,因为编译器会认为其为字符,引起编译错误
int a[4]={1,3,4,5};
int b[5]={1,2,3,4,5};
MGraph<int> g(a,4,4); //对象的初始化,采用对象调用定义的构造函数,根据函数的重载,其会自动匹配定义的构造函数,而不是默认的构造函数,注意图的逻辑性,
//int a[5]={1,2,3,4,5,};
//MGraph<int> g(a,5,5);
//cout<<"深度优先遍历递归算法的结果为:";
//g.DFSTraverse(0);cout<<endl;
cout<<"深度优先非递归算法的结果为:";
g.DFSTraverse2(0); cout<<endl;
cout<<"深度优先算法2的结果为:";
g.DFSTraverse1(0);cout<<endl;
cout<<"广度优先遍历非递归算法:";
g.BFSTraverse(0); cout<<endl;
cout<<"深度优先遍历生成树为:";
g.DFSTraverseSCH(0);
MGraph<int> G(b,5,5);
cout<<"深度优先遍历递归算法的结果为:";
G.DFSTraverse(0);cout<<endl;
G.DFSTraverse2(0);cout<<endl; //示例数据组合
}
分享到:
相关推荐
《清新简约图片应用商务PPT模板深度解析》 在当今快节奏的商业环境中,一份设计精良、内容清晰的PPT已经成为商务展示不可或缺的工具。"清新简约图片应用商务PPT模板"以其独特的设计理念和实用的功能,为商务人士...
1. **现象分析**:2013年以来,多款社交图片应用如疯狂猜图、百度魔图和魔漫相机等在国内市场迅速崛起,凭借社交媒体平台如微博和微信的朋友圈实现了病毒式的快速传播。然而,这些应用的生命周期普遍较短,火爆之后...
它利用了卫星图像、地形图和街景图等多种数据源,为用户提供精准的地理坐标信息。用户可以通过缩放、平移操作查看不同区域的地图,同时应用支持自定义地图标记和路线规划,使用户能够快速找到目标位置。 其次,公交...
11 图片应用和编排技巧(请柬-折页)素材
Python项目源码实例053使用openCV-Python批量为图片应用灰度滤镜.zip
Python项目源码实例054使用OpenCV-python批量为图片应用写生素描滤镜.zip
Python项目源码实例055使用OpenCV-python批量为图片应用卡通动漫滤镜.zip
该Vue组件库是一个基于Openlayers的地图应用解决方案,包含62个文件,涵盖35个PNG图片、9个JavaScript脚本、3个SVG图标、2个HTML模板、2个JSON数据文件、2个Vue组件文件以及必要的配置文件。它支持百度、高德、天...
国产MCU华大半导体HC32L17x系列单片机软硬件设计SDK资料包参考设计原理图应用笔记等资料: HC32L176_L170系列数据手册Rev1.3.pdf HC32L17X_L19X管脚功能查询及配置.xlsx HC32L17_L19_F17_F19系列勘误手册.pdf HC32L17...
在Android设备上,Gallery通常指的是系统内置的图片应用,允许用户浏览、组织、编辑和分享手机或存储卡上的照片。以下是关于Gallery图片浏览器的一些可能涵盖的知识点: 1. 图片浏览:应用的核心功能是浏览图片,这...
在Android平台上,开发一款本地图片查看应用是一项常见的任务,它能帮助用户轻松浏览手机上的照片。这个名为"android本地图片查看...通过学习和实践这个项目,开发者可以提升在Android平台上构建高效图片应用的能力。
计算机E-R图应用题.doc
用图像创造场景感,增强用户的真实体验,近些年来,图片作为背景填充整个屏幕的设计越来越广泛,曾经只有时尚...上图是google云盘官网banner背景为一张在飞机向外看的图片,不难发现用这种比拟手法来表现云盘的口号“随
总结来说,"MFC应用CStatic派生带滚动条的图片控件类"是一个高级的UI组件,它结合了`CStatic`的简单性与滚动条的交互性,为显示大图提供了便利。实现这个控件涉及对MFC框架、Windows消息处理和图形绘制的深入理解。...
电子设计电路图应用电子继电线路设计论文资料提取方式是百度网盘分享地址
这不仅有助于提升个人技能,还能为开发自己的图片应用提供灵感和实践基础。 总的来说,ScePhotoViewer是一款集成了多种功能的图片浏览应用,它的成功在于充分利用了WPF的强大特性,实现了流畅、便捷的图片查看体验...
"全球生成式AI应用全景图:AI应用进入大爆发时代" 以下是生成式AI应用的知识点: 1. 算法及模型的快速进步:Transformer 模型和 ChatGPT 的发布标志着生成式 AI 在文本领域的重大飞跃,未来将推动 AI 应用的持续...
10. **资源文件**:应用的图片、音频、字符串等资源文件位于`res`目录下,根据类型分在不同子目录。 11. **Gradle构建脚本**:`build.gradle`文件定义了项目的构建配置,包括依赖库、编译选项等。 12. **第三方库*...