图的遍历实验报告附C++源码.docx
- 文档编号:24324286
- 上传时间:2023-05-26
- 格式:DOCX
- 页数:13
- 大小:51.47KB
图的遍历实验报告附C++源码.docx
《图的遍历实验报告附C++源码.docx》由会员分享,可在线阅读,更多相关《图的遍历实验报告附C++源码.docx(13页珍藏版)》请在冰豆网上搜索。
图的遍历实验报告附C++源码
图的遍历
一、问题背景
若用有向网表示网页的链接网络,其中顶点表示某个网页,有向弧表示网页之间的链接关系。
试设计一个网络蜘蛛系统,分别以广度优先和深度优先的策略抓取网页。
二、需求分析
1)首先输入顶点的数量,然后是各顶点对应的字母,再输入各条弧(权值都置为1);
2)输出从首个顶点开始的广度优先遍历序列和深度先遍历序列;
3)为了达到任意图的遍历(结点名称不一定是数字,可以是任意可见字符),可以自定义一个数组类型,保存该结点的名称和记录是否被访问;
4)图使用相邻矩阵来实现;
5)测试数据:
输入
输入顶点数和弧数:
89
输入8个顶点.
输入顶点0:
a
输入顶点1:
b
输入顶点2:
c
输入顶点3:
d
输入顶点4:
e
输入顶点5:
f
输入顶点6:
g
输入顶点7:
h
输入9条弧.
输入弧0:
ab1
输入弧1:
bd1
输入弧2:
be1
输入弧3:
dh1
输入弧4:
eh1
输入弧5:
ac1
输入弧6:
cf1
输入弧7:
cg1
输入弧8:
fg1
输出
广度优先遍历:
abdhecfg
深度优先遍历:
abcdefgh
三、概要设计
抽象数据类型
为了遍历任意图,定义了如下数据类型,用于存储该结点的名称和记录是否被访问过。
classNode//基本抽象数据类型
{
public:
charch;//记录名称,如果将这里改成数组,结点名称可以是多个字符
intflag;//记录结点是否被访问
};
classGraph//图类,此类中,封装了图的一些成员和一些必须的成员函数
{
private:
intgetSub(char);//获取某名称的下标
Node*arrNode;//记录名称和是否访问的数组
intnumVertex,numEdge;//记录图的顶点数和边数
int**matrix;//用一个二维数组记录两点间是否相连,1相连,0断开
public:
voidsetCh(char,int);//将数组的arrNode的每一个单元设置一个结点名称
Graph(int);
~Graph();
intgetNumVertex();//获得图的顶点数
charfirst(charch);//获得相邻结点
charnext(charch1,charch2);//获得隔着ch2,但与ch2相邻的结点
voidsetEdge(char,char,intw=1);//设置两顶点的边和权重(权重默认为1)
intgetMark(char);//获取是否被访问的记录,已访问返回1,未访问返回0
voidsetMark(char);//把已访问的结点,设置标记
};
算法的基本思想
用一个自定义类型的数组,记录每个结点的信息(包括名称、是否被访问),且此数组作为图的成员变量之一;用一个类,对数组进行相应的操作,以便获得所需的信息。
深度优先采取的递归思想。
首先,将从起点,沿某条边,顺势遍历下去,直到不能继续遍历下去。
这时,又从起点的另一结点开始,遍历下去。
如此往复,知道将所有结点遍历完。
广度优先得使用队列。
首先,将起点入队,并标为已访问。
进入循环,当队列不为空时,出队,输出,并将与出队的元素相邻的且未访问的结点全部放入队列,标为已访问。
一次循环,只有一个结点出队,大于等于0个结点入队。
voidDFS(Graph*G,charch)//深度优先遍历图
{
inti=0;
cout< G->setMark(ch); for(charw=G->first(ch);i { if(G->getMark(w)==0) DFS(G,w); i++; } } voidBFS(Graph*G,charch,myQueue*q)//广度优先遍历图 { charv,w; q->enqueue(ch); G->setMark(ch); while(q->length()! =0) { q->dequeue(v); cout< inti=0; for(w=G->first(v);i { if(G->getMark(w)==0) { G->setMark(w); q->enqueue(w); } i++; } } } 程序的流程 输入顶点数、边数——>完成图的初始化——>输入顶点名称、设置边——>输入遍历起点——>深度优先遍历,输出结果——>广度优先遍历,输出结果 算法的时空分析 因为此程序追求结点的个性化(可以不按ABCD……的顺序来命名,可以用任意可见字符),使得程序的时间代价比较大。 不管是设置顶点名称,还是遍历,这都与图的顶点个数相关,包括根据结点名称获得下标的函数也是用循环实现的,时间复杂度为Θ(n)。 总之,时间开销比较大。 输入和输出的格式 输入 输入顶点数和弧数: //提示输入 等待输入 输入8个顶点.//提示 输入顶点0: //提示输入 等待输入 …… 输入9条弧.//提示 输入弧0: //提示输入 等待输入 四、运行截图 五、实验心得(可选) 这个实验,总的难度不大。 但我在追求结点名称的个性化的时候,没注意到这带来的时间开销,在写实验报告时才发现。 实验中,大量使用了循环,所以比较适合于密集图,稀疏图用此,那就是程序,那就是浪费时间了。 发现这个程序,还存在不完善的地方。 如果图不是连通的,那么将不能把所有的点遍历完。 六、附录(源码) /*********************各类定义******************************/ classNode//基本抽象数据类型 { public: charch;//记录名称,如果将这里改成数组,结点名称可以是多个字符 intflag;//记录结点是否被访问 }; classGraph//图类,此类中,封装了图的一些成员和一些必须的成员函数 { private: intgetSub(char);//获取某名称的下标 Node*arrNode;//记录名称和是否访问的数组 intnumVertex,numEdge;//记录图的顶点数和边数 int**matrix;//用一个二维数组记录两点间是否相连,1相连,0断开 public: voidsetCh(char,int);//将数组的arrNode的每一个单元设置一个结点名称 Graph(int); ~Graph(); intgetNumVertex();//获得图的顶点数 charfirst(charch);//获得相邻结点 charnext(charch1,charch2);//获得隔着ch2,但与ch2相邻的结点 voidsetEdge(char,char,intw=1);//设置两顶点的边和权重(权重默认为1) intgetMark(char);//获取是否被访问的记录,已访问返回1,未访问返回0 voidsetMark(char);//把已访问的结点,设置标记 }; /*************各函数的函数体*****************************/ Graph: : Graph(intn) { inti,j; arrNode=newNode[n]; numVertex=n; numEdge=0; for(i=0;i arrNode[i].flag=0; matrix=newint*[numVertex]; for(i=0;i matrix[i]=newint[numVertex]; for(i=0;i for(j=0;j matrix[i][j]=0; } Graph: : ~Graph() { delete[]arrNode; for(inti=0;i delete[]matrix[i]; delete[]matrix; } intGraph: : getSub(charch)//获取下标 { for(inti=0;i if(ch==arrNode[i].ch) returni; } intGraph: : getNumVertex()//获取顶点数 { returnnumVertex; } charGraph: : first(charch)//获取相邻结点 { for(inti=0;i if(matrix[getSub(ch)][i]! =0) returnarrNode[i].ch; returnch; } charGraph: : next(charch1,charch2)//获取与ch2相邻的结点 { for(inti=getSub(ch2)+1;i if(matrix[getSub(ch1)][i]! =0) returnarrNode[i].ch; returnch1; } voidGraph: : setEdge(charch1,charch2,intw)//设置边 { if(matrix[getSub(ch1)][getSub(ch2)]==0) { numEdge++; matrix[getSub(ch1)][getSub(ch2)]=1; } } intGraph: : getMark(charch)//获取访问信息 { for(inti=0;i if(ch==arrNode[i].ch) returnarrNode[i].flag; return-1; } voidGraph: : setMark(charch)//设置标记 { for(inti=0;i if(ch==arrNode[i].ch) arrNode[i].flag=1; } voidGraph: : setCh(charch,intn)//将结点名称设置在字符中 { arrNode[n].ch=ch; } /***************主函数*********************/ voidDFS(Graph*,char);//深度优先遍历函数声明 voidBFS(Graph*,char,myQueue*);//广度优先遍历函数声明 intmain() { intnumVer,numE,i; chartemp1,temp2;//temp1,temp2作临时变量,记录输入的值 myQueue*q=newmyQueue; cout<<"输入定点数和弧数: "; cin>>numVer>>numE; GraphmyGraph1(numVer); GraphmyGraph2(numVer); cout<<"请输入"< \n"; for(i=0;i { cout<<"输入顶点"< "; cin>>temp1; myGraph1.setCh(temp1,i); myGraph2.setCh(temp1,i); } cout<<"请输入"< \n"; for(i=0;i { cout<<"输入弧"< "; cin>>temp1>>temp2; myGraph1.setEdge(temp1,temp2); myGraph2.setEdge(temp1,temp2); } cout<<"深度优先结果: "; DFS(&myGraph1,'a'); cout<<"\n广度优先结果: "; BFS(&myGraph2,'a',q); cout< return0; } voidDFS(Graph*G,charch)//深度优先遍历函数体 { inti=0; cout< G->setMark(ch); for(charw=G->first(ch);i if(G->getMark(w)==0) DFS(G,w); } voidBFS(Graph*G,charch,myQueue*q)//广度优先遍历函数体 { charv,w; q->enqueue(ch); G->setMark(ch); while(q->length()! =0) { q->dequeue(v); cout< inti=0; for(w=G->first(v);i if(G->getMark(w)==0) { G->setMark(w); q->enqueue(w); } } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 遍历 实验 报告 C+ 源码