江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx

上传人:b****2 文档编号:2705505 上传时间:2023-05-04 格式:DOCX 页数:16 大小:34.88KB
下载 相关 举报
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第1页
第1页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第2页
第2页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第3页
第3页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第4页
第4页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第5页
第5页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第6页
第6页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第7页
第7页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第8页
第8页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第9页
第9页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第10页
第10页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第11页
第11页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第12页
第12页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第13页
第13页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第14页
第14页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第15页
第15页 / 共16页
江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx

《江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx》由会员分享,可在线阅读,更多相关《江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx(16页珍藏版)》请在冰点文库上搜索。

江苏大学数据结构C++以邻接链表的方式确定一个无向网.docx

江苏大学数据结构C++以邻接链表的方式确定一个无向网

题目3.以邻接链表的方式确定一个无向网,完成:

⑴建立并显示出它的邻接矩阵;

⑵对该图进行广度优先遍历,显示遍历的结果,(并随时显示队列的入、出情况);

⑶用普里姆算法构造其最小生成树,随时显示其构造的过程;

4用克鲁斯卡尔算法构造其最小生成树,随时显示其构造的过程;

一、需求分析

1.运行环境:

MicrosoftVisualStudio2010

2.程序所实现的功能:

(1)建立并显示图的邻接矩阵;

(2)广度优先遍历该图,显示遍历结果;

(3)用普里姆算法构造该图的最小生成树,显示构造过程;

(4)用克鲁斯卡尔算法构造该图的最小生成树,显示构造过程。

3.程序的输入,包含输入的数据格式和说明:

(1)输入顶点数,及各顶点信息(数据格式为整形);

(2)输入弧以及其权值(数据格式为整形)。

4.程序的输出,程序输出的形式:

(1)输出图的邻接矩阵;

(2)广度优先遍历结果;

(3)普里姆算法构造最小生成树的结果;

(4)克鲁斯卡尔算法构造最小生成树的结果。

5.测试数据,如果输入的数据量较大,需要给出测试数据:

(1)顶点个数:

4

(2)各个顶点为:

abcd

(3)输入所有的弧(格式为“顶点顶点权值”)为:

ab2ad4bc1bd8cd7ac6

二、设计说明

1.算法设计的思想:

建立图类,建立相关成员函数。

最后在主函数中实现。

具体成员函数的实现请参看源程序。

(1)邻接链表:

邻接链表是一种链式存储结构。

在邻接链表中,对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点Vi的边(对有向图是以顶点Vi为尾的弧)。

每个结点由3个域组成,其中邻接点域指示与顶点Vi邻接的点在图中的位置,链域指示下一条边或弧的结点;数据域存储和边或弧相关的信息,如权值等。

所以一开始必须先定义邻接链表的边结点类型以及邻接链表类型,并对邻接链表进行初始化,然后根据所输入的相关信息,包括图的顶点数、边数、是否为有向,以及各条边的起点与终点序号,建立图的邻接链表。

(2)邻接矩阵:

图的邻接矩阵存储表示即是数组存储表示,在邻接矩阵中,我们定义两个数组分别存储数据元素的信息和数据元素之间的关系(边或弧)的信息,以二维数组表示有n个顶点的图时,需存放n个顶点信息和n的平方个弧信息的存储量。

借助于邻接矩阵容易判定任意两个顶点之间是否有边或弧相连,并容易求得各个顶点的度。

故在建立邻接矩阵之前,必须先定义顶点关系类型和相关指针指示弧的信息。

(3)广度优先遍历:

假设从图总某顶点出发,在访问了v之后依次访问v的各个未曾访问到的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的邻接点”先于“后被访问的邻接点”被访问,直至图中所有已被访问的邻接点都被访问到。

若此时图中尚有顶点未被访问到,则另选图中一个未曾被访问的顶点作为起始点,重复上述过程,直至图中所有顶点都被访问到为止。

换句话说,广度优先搜索遍历图的过程是以v为起始点,由近及远,依次访问饿v有路径相通且路径长度为1,2….的顶点。

和深度优先搜索类似,在遍历过程中也需要一个访问标志数组。

并且,为了顺次访问路径长度为2,3…的顶点,需附设队列以存储已被访问的路径长度为1,2….的顶点。

所以要实现算法必须先建立一个元素类型为整形的空队列,并定义队首与队尾指针,同时也要定义一个标志数组以标记结点是否被访问。

同样,也是从初始点出发开始访问,访问初始点,标志其已被访问,并将其入队。

当队列非空时进行循环处理。

当结点被访问时对其进行标志,并入队列。

通过while()循环,并以是否被访问为控制条件,访问所有结点,完成图的广度优先遍历。

(4)普里姆算法:

假设N=(V,{E})是连通网,TE是N上最小生成数中边的集合。

算法从U={U0},TE={}开始,重复执行如下操作;在所有的边(u,v)中找一条代价最小的边(u0,v0)并入集合TE,同时V0并入U,直到U=V为止。

此时TE中必有n-1条边,则,T=(V,{TE})为N的最小生成树。

(5)克鲁斯卡尔算法:

假设连通网N=(V,{E}),则令最小生成树的初始状态为只有n个顶点且无边的非连通图T=(V,{}),图中每个顶点自成一个连通分量。

在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。

依次类推,直到T中的所有顶点都在同一个连通分量上为止。

2.主要的数据结构设计说明:

图的邻接矩阵、邻接表的建立。

图的广度优先遍历以及分别用普里姆算法和克鲁斯卡尔算法构造最小生成树。

 

3.程序的主要流程图:

 

4.程序的主要模块,要求对主要流程图中出现的模块进行说明:

用邻接链表的方式确定一个无向图,以邻接矩阵的方式输出,再进行图的广度优先遍历以及分别用普里姆算法和克鲁斯卡尔算法构造最小生成树并输出。

5.程序的主要函数及其伪代码说明(不需要完整的代码):

Intlocateding(string);定位节点位置

intisempty();判断是否为空

voidguangdubianli();广度优先遍历

voidprintgragh();邻接矩阵的输出

voidprim();普里姆算法

voidktus();克鲁斯卡尔算法

 

三、上机结果及体会

1.上机过程中出现的问题及其解决方案。

问题:

刚开始编译没有错误,但结果有问题。

解决方案:

虽然程序的编译通过,只能说明语法上没有问题,结果只所以不正确是因为算法上原因。

2.程序中可以改进的地方说明

(1)程序中的广度优先遍历,可以考虑用循环来做。

(2)邻接矩阵输出应定义一个”-”来代表无穷

四、实验源程序

#include

#include

#include

usingnamespacestd;

#definemax10

classnode_shuzu;

//邻接链表链结点

classnode_lianbiao

{

public:

intposition;

intquanzhi;

node_lianbiao*next;

node_lianbiao(inta,intb){position=a;quanzhi=b;next=NULL;}

node_lianbiao(){next=NULL;}

~node_lianbiao(){}

};

//邻接链表数组结点

classnode_shuzu

{

public:

node_lianbiao*next;

stringdata;

node_shuzu(){next=NULL;}

~node_shuzu(){}

};

//图类

classtu_juzhen

{

private:

intjuzhen[max][max];

stringdingdian[max];

intnumding,numhu;

node_shuzulianbiao[max];

public:

tu_juzhen(){}

voidcreat();

intlocateding(string);//返回这个顶点的第几位

intisempty();//判断是否为空

voidguangdubianli();

voidprintgragh();

voidprim();

voidktus();

};

inttu_juzhen:

:

locateding(stringb)

{

inti=0;

for(;i

{

if(dingdian[i]==b)returni;

}

return-1;

}

voidtu_juzhen:

:

creat()

{

stringdata,data1,data2;

intn,m,num;

//输入顶点个数

cout<<"请输入顶点个数:

";

cin>>numding;

//输入顶点

cout<<"请依次输入各个顶点:

";

for(inti=0;i

{

cin>>dingdian[i];

}

//以邻接链表确定有向网

node_lianbiao**po[max];//指向数组链表的最后一位的next成员

for(inti=0;i

{lianbiao[i].data=dingdian[i];po[i]=&lianbiao[i].next;}

cout<<"输入所有的弧,格式为:

“顶点顶点权值”,以格式000结束"<

do

{

cin>>data1>>data2>>num;

n=locateding(data1);

m=locateding(data2);

//node_lianbiaoa(m,num);

if((n!

=-1)&&(m!

=-1))

{

*po[n]=newnode_lianbiao(m,num);

po[n]=&((*po[n])->next);

*po[m]=newnode_lianbiao(n,num);

po[m]=&((*po[m])->next);

}

}

while((data1!

="0")&&(data2!

="0")&&(num!

=0));

//根据邻接链表建立邻接矩阵

node_lianbiao*po1;

for(inti=0;i

for(intj=0;j

juzhen[i][j]=0;

for(inti=0;i

{

po1=lianbiao[i].next;

while(po1)

{

n=po1->position;

m=po1->quanzhi;

po1=po1->next;

juzhen[i][n]=m;

};

}

}

voidtu_juzhen:

:

printgragh()//打印有向网的邻接矩阵

{

cout<

cout<<"邻接矩阵为:

"<

inti,j;

for(i=0;i

{

for(j=0;j

{

cout<

}

cout<

}

}

voidtu_juzhen:

:

guangdubianli()

{

int*flag=newint[numding];//记录顶点访问状态

int*duilie=newint[numding];//记录未广度遍历的顶点数

intfront,rear;

front=0;rear=0;

inti;

cout<

cout<<"该图的广度优先遍历为:

"<

for(i=0;i

 

do

{

for(i=0;i

if(i!

=numding)

{

cout<<"-->"<

rear++;

duilie[rear]=i;

cout<<"入队列"<

flag[i]=1;

do

{

cout<<"出队列"<

front=(front+1)%20;

for(intj=0;j

{

if((juzhen[duilie[front]][j]!

=0)*(flag[j]!

=1))

{

rear++;

duilie[rear]=j;

cout<<"入队列"<

flag[j]=1;

cout<<"-->"<

}

}

}

while((((rear+1)%20)!

=front)*(rear!

=front));//队列结束条件。

队列满或空

}

}

while(i!

=numding);

cout<

}

voidtu_juzhen:

:

prim()

{

intflag[max],dian[max],n,m,l,p=0;//flag[]标志结点所属树,p表示已写出结点个数

intjuzhen1[max][max];//矩阵的映像

for(inti=0;i

for(intj=0;j

juzhen1[i][j]=juzhen[i][j];

for(inti=0;i

cout<<"普里姆算法"<

//先找到最小的一个弧

l=n=m=10000;//假设一个很大值

for(inti=0;i

for(intj=i;j

{

if((juzhen1[i][j]!

=0)&&(juzhen1[i][j]

{

l=juzhen1[i][j];

m=i;n=j;

}

}

p+=2;dian[0]=m;dian[1]=n;flag[n]=flag[m]=1;

cout<

while(p

{

l=n=m=10000;

for(inti=0;i

{

for(intj=0;j

{

if((juzhen1[j][dian[i]]!

=0)&&(juzhen1[j][dian[i]]

{

l=juzhen1[j][dian[i]];

n=dian[i];m=j;

}

}

}

if((m!

=10000)&&(n!

=10000)&&(l!

=10000))

{

dian[p]=m;

p++;

cout<

flag[m]=1;

}

}

cout<

}

voidtu_juzhen:

:

ktus()

{

intflag[max],n,m,l,p,k;//flag[]标志结点所属树,p表示已写出弧个数

intjuzhen1[max][max];//矩阵的映像

for(inti=0;i

for(intj=0;j

juzhen1[i][j]=juzhen[i][j];

cout<<"克鲁斯卡尔算法:

"<

for(inti=0;i

k=p=0;

while(p<(numding-1))

{

l=n=m=10000;//假设一个很大值

 

for(inti=0;i

for(intj=0;j

{

if((juzhen1[i][j]!

=0)&&(juzhen1[i][j]

{

l=juzhen1[i][j];

m=i;n=j;

}

}

if((m!

=10000)&&(n!

=10000)&&(l!

=10000))

{

if(flag[n]!

=0)

if(flag[m]!

=0)

if(flag[n]==flag[m])//成环情况

{continue;}

else

{

cout<

p++;

flag[numding]=flag[m];

for(inth=0;h

if(flag[h]==flag[numding])

flag[h]=flag[n];

}

else

{cout<

else

if(flag[m]!

=0)

{cout<

else

{cout<

juzhen1[m][n]=juzhen1[n][m]=0;

}

k++;

};

cout<

}

voidmain()

{

tu_juzhenli;

li.creat();

li.printgragh();

li.guangdubianli();

li.ktus();

li.prim();

}

 

五、输出结果显示

一些说明,本程序的健壮性还不是很好,比如说在数据的录入的时候,用户需要小心的正确输入顶点和权值。

 

六、收获及体会

七、参考文献:

缪淮扣,顾训穰,沈俊.数据结构――C++实现.科学出版社,2011年修订

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2