实验无向图中求两点间的所有简单路径.docx
- 文档编号:5757247
- 上传时间:2023-01-01
- 格式:DOCX
- 页数:18
- 大小:40.31KB
实验无向图中求两点间的所有简单路径.docx
《实验无向图中求两点间的所有简单路径.docx》由会员分享,可在线阅读,更多相关《实验无向图中求两点间的所有简单路径.docx(18页珍藏版)》请在冰豆网上搜索。
实验无向图中求两点间的所有简单路径
实验6无向图中求两点间的所有简单路径
计科二班宋瑞霞20100810217
一、需求分析
1、用无向图表示高速公路网,其中顶点表示城市,边表示城市之间的高速公路。
设计一个找路程序,获取两个城市之间的所有简单路径。
2、由用户通过键盘输入:
(1)结点总数,
(2)结点的城市编号(4位长的数字,例如电话区号,长沙是0731),
(3)连接城市的高速公路(用高速公路连接的两个城市编号标记),
(4)要求取所有简单路径的两个城市编号。
不对非法输入做处理,即假设输入都是合法的。
3、输出:
将所有路径(有城市编号组成)输出到DOS界面上。
4、测试数据:
输入:
68(结点数和边数)
000100020003000400050006(结点的城市编号)
00010003(连接城市间的高速公路)
00010005
00020006
00030002
00030004
00030006
00040006
00050006
00010002(要求取所有简单路径的两个城市编号)
输出:
000100030002(两个城市间的所有简单路径)
0001000300060002
00010003000400060002
0001000500060002
00010005000600030002
000100050006000400030002
二、概要设计
抽象数据类型
根据对问题的分析,要用无向图表示高速公路网,其中顶点表示城市,边表示城市之间的高速公路。
所以要建立一个图来实现。
图的ADT设计如下:
数据元素:
包括一个顶点集合和一个边集合
数据关系:
网状关系
基本操作:
Graph(intnumvert)//构造图结构
virtualintn()=0;//获取顶点的个数
virtualintfirst(int)=0;//访问所给顶点的第一个邻居
virtualintnext(int,int)=0;//访问当前邻居的下一个邻居
virtualvoidsetedge(int,int)=0;//建立所给两顶点之间的边
virtualvoidsetmark(intv,intval)=0;//给顶点做标记
virtualintgetmark(intv)=0;//获取顶点是否已做标记
算法的基本思想
首先,根据输入的结点总数构建一个线性表,将输入的城市编号即顶点依次添加到线性表中;然后就是在图的二维数组中存入边即连接两个城市间的高速公路,这步操作首先要找到两个城市即两个顶点在线性表中的位置如m和n,然后再在二维数组相应的位置(m,n)上存入1建立该条边;最后当所有的边都存入图中后,由于深度优先的结果是沿着图的某一分支搜索直至末端,然后回溯,在沿着另一条分支搜索,依次类推,故对图进行深度优先搜索,即可得到两个城市间的简单路径。
程序的流程
程序由四个模块组成:
1、输入模块:
输入图的顶点和边;
2、构建模块:
用线性表存储顶点,用二维数组存储边,构建图结构;
3、处理模块:
对图进行深度优先搜索;
4、输出模块:
将深度优先搜索后得到的所有简单路径输出到DOS界面上。
三、详细设计
物理数据类型
该问题需要输入4位长的数字表示的城市编号,为了能够存储,采用C++语言中的字符串string来定义变量线性表中的元素类型,数组的大小为4。
根据用邻接矩阵表示法来实现图的相关知识,要先建立一个线性表来存储顶点,由于结点总数即图的顶点数已知,则线性表的长度已知,故用顺序表实现比较好,因为顺序表是预先分配一段连续的存储空间,而且没有结构性开销。
1、顺序表的具体实现如下:
template
classAlist
{
private:
intmaxSize;//顺序表的最大长度
intlistSize;//顺序表的实际长度
intfence;//指向当前位置
Elem*listArray;//存储顺序表元素的数组
public:
Alist(intsize=DefaultListSize)//构造一个由用户指定最大长度的空顺序表
{
maxSize=size;
listSize=fence=0;
listArray=newElem[maxSize];
}
boolappend(constElem&item)//添加
{
if(listSize==maxSize)
returnfalse;
else
{
listArray[listSize++]=item;
returntrue;
}
}
intrightLength()const//右边长度
{
returnlistSize-fence;
}
boolgetvalue(iElem&it)const//获取当前位置的元素值,若右边为空,返回false
{
if(rightLength()==0)
returnfalse;
else
{
it=listArray[fence];
returntrue;
}
}
voidsetStart()//将当前位置置0
{
fence=0;
}
voidnext()//右移一位
{
if(fence fence++; } }; 2、图的具体实现如下: classGraph { private: intnumvertex,numedge;//存储顶点数和边数 int**matrix;//指向邻接矩阵的指针 int*mark;//指向访问标记数组的指针 public: Graph(intnumvert)//实现邻接矩阵 { inti,j; numvertex=numvert; numedge=0; mark=newint[numvert]; for(i=0;i mark[i]=0; matrix=(int**)newint*[numvertex];//构造邻接矩阵 for(i=0;i matrix[i]=newint[numvertex]; for(i=0;i for(j=0;j matrix[i][j]=0; } ~Graph()//析构函数 { delete[]mark; for(inti=0;i delete[]matrix[i]; delete[]matrix; } intn()//获取顶点个数 { returnnumvertex; } inte()//获取边的个数 { returnnumedge; } intfirst(intv)//访问所给顶点的第一个邻居 { inti; for(i=0;i if(matrix[v][i]! =0) returni; returni; } intnext(intv1,intv2)//访问当前邻居的下一个邻居 { inti; for(i=v2+1;i if(matrix[v1][i]! =0) returni; returni; } voidsetedge(intv1,intv2)//无向图中建立所给两顶点之间的边 { if(matrix[v1][v2]==0) numedge++; matrix[v1][v2]=1; matrix[v2][v1]=1; } voidsetmark(intv,intval)//给顶点做标记 { mark[v]=val; } intgetmark(intv)//获取顶点是否已做标记 { returnmark[v]; } }; 算法的具体步骤 1、定义顺序表L、图G,还有存储课程名的字符串stringcity,city1,city2, 输入顶点个数n和边数m。 2、输入顶点city并将输入的顶点依次存入顺序表L中。 for(inti=0;i { cin>>city; L.append(city); } 3、输入有路连接的两个城市编号,即相互间存在边的两个顶点,找到这两个顶点在线性表中的位置,然后在图的二维数组相应的位置上存入1建立该条边。 通过一个循环将所有的边都建完,完成图的存储。 for(inti=0;i { cin>>city1>>city2; G.setedge(find(L,n,city1),find(L,n,city2)); } 其中find函数即实现找到顶点在线性表中的位置的功能,具体如下: intfind(AlistL,intn,int&city) { inti; stringcity1; L.setStart(); for(i=0;i { L.getvalue(city1);//获取当前位置的元素值 if(city1==city)//若当前位置的元素值与所要找的顶点值相同 returni;//则返回当前位置所在的位置 else L.next();//若不同,则在向右移一位再做判断 } } 4、对图进行深度优先搜索 intaddr[100]; intnum=-1; voidDFS(Graph&G,intv,Alist&L,intd) { G.setmark(v,1); if(v==d) { for(inti=0;i<=num;i++) { printout(L,addr[i]); cout<<''; } cout< G.setmark(d,0); num--; return; } for(intw=G.first(v);w if(G.getmark(w)==0) { addr[++num]=w; DFS(G,w,L,d); } num--; G.setmark(v,0); } 其中的输出函数为: voidprintout(AlistL,intv) { L.setStart(); strings; for(inti=0;i L.next(); L.getvalue(s); cout< } 算法的时空分析 设V为顶点数,E为边数, (1)由于顺序表用来存储顶点,顺序队列用来存储入度为0的顶点,所以它们的空间代价都为Θ(|V|);而邻接矩阵的空间代价为Θ(|V|^2),故总的空间代价为Θ(|V|^2)。 (2)由于顺序表的添加操作的时间复杂度为Θ (1),故将所有结点存入顺序表的时间复杂度为Θ(|V|);在对无向图进行深度优先时,DFS从两个方向处理每条边,每个顶点都必须被访问,而且只能访问一次,故总的时间复杂度为Θ(|V|+|E|)。 输入和输出的格式 输入: 请输入结点总数和边数: //提示 等待输入 请输入城市编号: //提示 等待输入 请输入有路连接的两个城市的编号: //提示 等待输入 请输入要求取所有简单路径的两个城市编号: //提示 等待输入 输出: 这两个城市间的所有简单路径为: //提示 输出结果的位置 四、调试分析 大部分是语法错误,看着错误提示都改过来了,今天又学到点新知识,就是如果执行的界面没关的话,连接时会出现错误。 五、测试结果 六、用户使用说明 1、本程序的运行环境为DOS操作系统 2、运行程序时 提示输入结点总数和边数 城市编号 有路连接的两个城市的编号 要求取所有简单路径的两个城市编号 输出: 两个城市间的所有简单路径 七、实验心得 这次实验感觉好难啊,搞了一天的预习报告,结果就得了1分,那种感觉真的好难受的! 八、程序 #include #include usingnamespacestd; #defineElemstring classAlist { private: intmaxSize;//顺序表的最大长度 intlistSize;//顺序表的实际长度 intfence;//指向当前位置 Elem*listArray;//存储顺序表元素的数组 public: Alist(intsize)//构造一个由用户指定最大长度的空顺序表 { maxSize=size; listSize=fence=0; listArray=newElem[maxSize]; } boolappend(constElem&item)//添加 { if(listSize==maxSize) returnfalse; else { listArray[listSize++]=item; returntrue; } } boolremove()//删除 { Elemit; if(rightLength()==0) returnfalse; it=listArray[fence]; for(inti=fence;i listArray[i]=listArray[i+1]; listSize--; returntrue; } intrightLength()const//右边长度 { returnlistSize-fence; } boolgetvalue(Elem&it)const//获取当前位置的元素值,若右边为空,返回false { if(rightLength()==0) returnfalse; else { it=listArray[fence]; returntrue; } } voidsetStart()//将当前位置置0 { fence=0; } voidnext()//右移一位 { if(fence fence++; } voidprev() { if(fence! =0) fence--; } boolsetPos(intpos) { if((pos>=0)&&(pos<=listSize)) fence=pos; return(pos>=0)&&(pos<=listSize); } }; classGraph { private: intnumvertex,numedge; int**matrix; int*mark; public: Graph(intnumvert) { inti,j; numvertex=numvert; numedge=0; mark=newint[numvert]; for(i=0;i mark[i]=0; matrix=(int**)newint*[numvertex]; for(i=0;i matrix[i]=newint[numvertex]; for(i=0;i for(j=0;j matrix[i][j]=0; } ~Graph() { delete[]mark; for(inti=0;i delete[]matrix[i]; delete[]matrix; } intn() { returnnumvertex; } inte() { returnnumedge; } intfirst(intv) { inti; for(i=0;i if(matrix[v][i]! =0) returni; returni; } intnext(intv1,intv2) { inti; for(i=v2+1;i if(matrix[v1][i]! =0) returni; returni; } voidsetedge(intv1,intv2) { matrix[v1][v2]=1; matrix[v2][v1]=1; } voidsetmark(intv,intval) { mark[v]=val; } intgetmark(intv) { returnmark[v]; } }; intfind(AlistL,intn,strings) { inti; strings1; L.setStart(); for(i=0;i { L.getvalue(s1); if(s1==s) returni; else L.next(); } } voidprintout(AlistL,intv) { L.setStart(); strings; for(inti=0;i L.next(); L.getvalue(s); cout< } intaddr[100]; intnum=-1; voidDFS(Graph&G,intv,Alist&L,intd) { G.setmark(v,1); if(v==d) { for(inti=0;i<=num;i++) { printout(L,addr[i]); cout<<''; } cout< G.setmark(d,0); num--; return; } for(intw=G.first(v);w if(G.getmark(w)==0) { addr[++num]=w; DFS(G,w,L,d); } num--; G.setmark(v,0); } voidmain() { inti,n,m; stringcity,city1,city2; cout<<"请输入顶点数和边数: \n"; cin>>n>>m; GraphG(n); AlistL(n); cout<<"请输入城市编号: \n"; for(i=0;i { cin>>city; L.append(city); } cout<<"请输入有路连接的两个城市的编号: \n"; for(i=0;i { cin>>city1>>city2; G.setedge(find(L,n,city1),find(L,n,city2)); } cout<<"请输入要求取所有简单路径的两个城市编号: \n"; cin>>city1>>city2; cout<<"这两个城市间的所有简单路径为: \n"; addr[++num]=find(L,n,city1); DFS(G,find(L,n,city1),L,find(L,n,city2)); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 图中求 两点 所有 简单 路径