数据结构课程设计论文Word文件下载.docx

上传人:b****7 文档编号:22354897 上传时间:2023-02-03 格式:DOCX 页数:29 大小:181.45KB
下载 相关 举报
数据结构课程设计论文Word文件下载.docx_第1页
第1页 / 共29页
数据结构课程设计论文Word文件下载.docx_第2页
第2页 / 共29页
数据结构课程设计论文Word文件下载.docx_第3页
第3页 / 共29页
数据结构课程设计论文Word文件下载.docx_第4页
第4页 / 共29页
数据结构课程设计论文Word文件下载.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

数据结构课程设计论文Word文件下载.docx

《数据结构课程设计论文Word文件下载.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计论文Word文件下载.docx(29页珍藏版)》请在冰豆网上搜索。

数据结构课程设计论文Word文件下载.docx

附录:

C语言代码清单----------------------------------------------------------------19

1.课程设计的内容

1.1无向网部分:

无向网邻接矩阵的建立,无向网邻接矩阵的遍历,普里姆算法(最优生成树)的实现。

1.2有向图部分:

有向图邻接表的建立。

2.课程设计中所用的函数说明

2.1无向网部分:

函数名称

函数功能

creatMGraph

创建一张无向网的邻接矩阵

printMGraph

输出一张无向网的邻接矩阵

DFS

遍历一张无向网

MiniSpanTree_PRIM

实现基于无向网的普里姆算法,即生成最优树

2.2有向图部分:

creatALGraph

创建一张有向图的邻接表

printfALGraph

输出一张有向图的邻接表

3.算法的设计思想

3.1邻接矩阵的建立

邻接矩阵表示顶点之间的相邻关系,设

,是具有n个顶点的网,则G的邻接矩阵是具有如下性质的n阶方阵:

(1)如果顶点

相连,则

赋值为权值,否则为无穷大(本课设中采用最大数代替无穷大)。

(2)对于无向网,

用邻接矩阵表示法表示网,除了存储邻接矩阵外,通常还需要用一个顺序表来存储顶点信息。

其具体C语言代码如下:

#definevexnum6/*图的顶点数目*/

#definearcnum10/*图的边(弧)数目*/

intvisited[vexnum]={0};

/*顶点是否被遍历的标志数组*/

typedefstruct{/*创建一个用邻接矩阵表示的图*/

intvexs[vexnum];

/*顶点信息*/

floatarcs[vexnum][vexnum];

/*邻接矩阵*/

}MGraph;

3.2邻接矩阵的初始化

由于无向网的邻接矩阵是对称的,故可采用压缩存储的方法,仅存储下三角阵(不包括对角线上的元素)中的元素。

显然,邻接矩阵表示法的空间复杂度

邻接矩阵的建立过程如下代码所示:

voidcreatMGraph(MGraph*m)/*向一个用邻接矩阵表示的图中输入数值*/

{

inti,j,k;

floatwqd;

/*因为后面要应用普里姆算法,故设置“无穷大”为wqd*/

floatw;

for(i=0;

i<

vexnum;

i++)

printf("

请输入顶点(%d):

"

i);

/*输入第i号顶点的数据*/

scanf("

%d"

&

m->

vexs[i]);

}

请输入权值最大范围0--:

);

/*确定最大值,即“无穷大”,一般输入一个比最大值再大一些的数字作为“无穷大”*/

%f"

wqd);

for(j=0;

j<

j++)

m->

arcs[i][j]=wqd;

/*邻接矩阵初始化,全部赋值无穷大*/

for(k=0;

k<

arcnum;

k++)

inta=arcnum;

intb=(vexnum-1);

请输入边(1-%d)与权值(顶点0--%d):

a,b);

/*提示信息*/

scanf("

%d%d%f"

i,&

j,&

w);

/*读入边

上的权w*/

m->

arcs[i][j]=w;

arcs[j][i]=w;

3.3邻接矩阵的输出

本课设采用行列式的形式输出邻接矩阵,具体C语言代码如下:

voidprintMGraph(MGraph*m)

{

inti,j;

"

/*格式*/

%d(%d)"

m->

vexs[i],i);

/*输出格式为“顶点信息(顶点编号)”*/

\n"

---"

------------"

/*下横线*/

%d(%d)|"

%f"

arcs[i][j]);

/*依次输出每一个顶点与其他顶点的关系*/

}

3.4邻接矩阵的遍历

对于图的遍历,和树的遍历类似,也是从某个顶点出发,沿着某条搜索路径对图中所有顶点做一次访问。

若给定的图是连通图,则从图中任一顶点出发顺着边可以访问到该图的所有顶点。

又因为图中任一顶点都可能和其余顶点相邻接,故在访问了某个顶点之后,可能顺着某条回路又回到了该顶点。

为了避免重复访问同顶点,必须记住每个顶点是否被访问过。

为此,我们已经在前面设置了向量intvisited[vexnum]={0}来标识。

它的初值为0,一旦访问了顶点

,便将顶点

置为1。

邻接矩阵遍历的具体C语言代码如下:

voidDFS(MGraph*m,inti)/*从邻接矩阵的第i个顶点开始遍历*/

intj;

visited[i]=1;

/*i号顶点标识为1,代表已经遍历过了*/

%d-"

/*输出已经遍历的顶点序号*/

if((m->

arcs[i][j]!

=0)&

&

(visited[j]==0))/*只有当顶点i与另外一个顶点j相邻且j顶点没有被遍历过的时候,才采用递归遍历*/

DFS(m,j);

/*递归遍历j顶点*/

\b"

/*退格键,去掉最后一个“-”*/

3.5普里姆最小生成树

不少图论问题在计算时,往往首先必须求出一棵最小生成树。

是一个无向图,如果

是由G的全部顶点及一部分边组成的子图,并且T是树(连通,没有环的图),则称T是G的一棵生成树。

一个连通图G的生成树不是唯一的,从不同的顶点出发进行遍历,得到不同的生成树。

对于连通网络

,边是带权的,因而G的生成树的各边也是带权的。

我们把生成树各边的权值总和称为生成树的权,并把权最小的生成树称为G的最小生成树。

最小生成树有许多重要的应用。

令图G的顶点表示城市,边表示连接两个城市之间的通信线路。

n个城市之间最多可设立的线路有

条,把n个城市连接起来至少要有n-1条线路,则图G的生成树表示了建立通信网络的可行方案。

如果给图中的边都赋予权,则这些权可表示两个城市之间通信线路的长度或建造代价,那么,如何选择一条线路,使得建立的n-1条通信网络其线路的总长度最短或总代价最小呢?

这就需要构造该图的一棵最小生成树。

本课设采用普里姆算法生成一个无向网的最优生成树。

基本思想为:

在所有

的边

中找到一条代价最小的边

并入最小生成树边的集合

中,同时

并入

,直至

为止。

为此,需要特别说明一个辅助矩阵——closedge,本课设中closedge的定义是这样的:

closedge为一个结构体数组,每一个结构体由两部分组成,一个是U集合中对应于第i号元素的边的集合中,最小权值的顶点序号,实际上就是两个顶点(i和closedge.adjvex)所确定的边;

另一个是该边上的权值。

数组closedge代码如下:

typedefstruct{/*辅助功能,用来选择最小生成树的边*/

intadjvex;

/*顶点序号*/

floatlowcost;

/*最小权值*/

}closedge;

首先,我们从邻接矩阵中选一个顶点开始查找,设该顶点序号为u,将辅助数组closedge中的所有元素依次赋值为与顶点u对应的边的信息,而顶点u的lowcost的值为0,表明此顶点已经并入集合U之中了。

然后,我们搜索数组closedge,从中找到权值最小的边所对应的序号,此序号所表示的顶点即为下一个进入集合U的顶点。

接下来,我们对剩下的vexnum-1个顶点进行同样的逐个查找,依次找出每个顶点所对应的,当前集合U中的(集合U是不断变化的),与之所形成的边的最小值,将最小值赋给lowcost,对应集合U中的顶点序号赋给adjvex。

依次往复,即可找出所有最有树的边。

但是,我发现书中的算法出现了一个小小的错误,即175页中算法7.9正数第二个for循环中,i<

G.vexnum,我认为应当改写为i<

G.vexnum-1,实践证明,如果每一次循环都进行逐个比较的话,最后一次循环的显示结果往往是错误的,因为当算法执行到最后一个循环的时候,由于集合

中仅剩下一个顶点元素,所以无需再进行比较,直接插入最优树即可,也就是说,最后一次循环中,数组closedge仅剩下一个顶点的lowcost不等于0,其所对应的adjvex即为需要连接进入集合U的顶点。

相应的,在书中算法7.9的结尾,也应当编写一段类C语言说明最后一次循环的情况。

具体普里姆算法C语言代码如下:

voidMiniSpanTree_PRIM(MGraph*m,intu)/*u为开始顶点编号*/

intk,i,j;

closedgecs[vexnum];

j++)/*先处理第一个顶点u*/

if(j!

=u)

{

cs[j].lowcost=m->

arcs[u][j];

cs[j].adjvex=u;

cs[u].lowcost=0;

/*表明已进入顶点集U*/

floatsum=0.0;

/*用于计算最小权值总和*/

for(i=1;

(vexnum-1);

i++)/*对剩余的vexnum-2个顶点(循环次数)*/

intp;

/*找出数组cs中的最小权值所对的序号(lowcost为MAX的除外)*/

floatmax=0.0;

for(p=0;

p<

p++)

if(max<

cs[p].lowcost)

max=cs[p].lowcost;

floatmin=max;

if((cs[p].lowcost!

(min>

cs[p].lowcost))

{min=cs[p].lowcost;

k=p;

/*下一个进入集合U的顶点编号,即V-U中的最小权值顶点*/

%d---%d最小权值为%f"

cs[k].adjvex,k,cs[k].lowcost);

sum=sum+cs[k].lowcost;

/*求权值*/

cs[k].lowcost=0;

if(m->

arcs[k][j]<

cs[j].lowcost)

cs[j].adjvex=k;

/*相对于上一个u而言,k所对应的权值更小*/

arcs[k][j];

if(cs[i].lowcost!

=0)k=i;

/*最后一个进入集合U的顶点序号*/

该最小生成树权值总和为:

sum);

3.6邻接表的建立

邻接表是把图的每个顶点的邻接顶点用链接表表示,这种表示方法类似于树的孩子链表表示法。

为此,需要建立一个顺序存储n个顶点的表,针对图G中的每个顶点

,该方法把所有邻接于

的顶点

链成一个单链表,这个单链表就称为顶点

的邻接表。

邻接表中每个表结点均有两个域,其一是邻接域,用以存放与

相邻接的顶点

的序号;

其二是链接域,用来指向与顶点

相邻的下一个顶点,这样,就可以将邻接表的所有表结点链接在一起。

同时,为每个顶点

的邻接表设置一个具有两个域的表头结点,一个是顶点域,用来存放顶点

的信息。

另一个是指针域,用于存入指向

的邻接表中第一个表结点的头指针。

#definevexnum6

#definearcnum5

typedefstruct{/*表头结点*/

structArcnode*next;

}Arcnode;

typedefstructVnode{/*表结点*/

intdata;

}Vnode;

typedefstruct{/*用邻接表表示的有向图*/

VnodeGmap[vexnum];

}ALGraph;

/*————————————邻接表的建立————————————*/

voidcreatALGraph(ALGraph*m)

i++)/*初始化*/

Gmap[i].data=0;

Gmap[i].next=NULL;

i++)/*输入顶点数值*/

请输入顶点(%d)数值:

Gmap[i].data);

k++)/*按照邻接表的格式,输入对应边的信息*/

inta=(vexnum-1);

请输入有向边“弧头弧尾”(以0为起点,0-%d):

a);

%d%d"

j);

Arcnode*q=(Arcnode*)malloc(sizeof(Arcnode));

/*开辟一个新的结点空间,并且从表头插入*/

q->

adjvex=i;

next=m->

Gmap[j].next;

Gmap[j].next=q;

}

/*——————————邻接表的输出————————————*/

voidprintfALGraph(ALGraph*m)

inti;

%d(%d)|"

Gmap[i].data,i);

/*输出顶点信息,顶点序号*/

Arcnode*p=m->

Gmap[i].next;

while(p!

=NULL)/*从表头输出至表尾*/

-%d-"

p->

adjvex);

p=p->

next;

printf(“\n”);

4.运行结果

运行环境:

MicrosoftVisualC++

程序语言:

C语言

下面,我们来检验一下程序能否正确运行。

4.1无向网部分

如图所示,为一张无向网。

主程序main()编写如下:

voidmain()

intv;

MGraphg={{0},{0}};

/*无向网的初始化*/

MGraph*y=&

g;

creatMGraph(y);

/*输入无向网的信息*/

printf("

无向网的邻接矩阵如下:

printMGraph(y);

/*输出无向网的邻接矩阵*/

无向网的遍历如下:

for(v=0;

v<

v++)/*从序号为0的顶点开始无向网的遍历*/

if(!

visited[v])DFS(y,v);

依据普里姆算法,得该图的最小生成树为:

intu=0;

/*从序号为0的顶点开始普里姆算法*/

MiniSpanTree_PRIM(y,u);

/*无向网的最小生成树*/

运行步骤:

1.编译无误,运行,界面如下所示

2.输入顶点

3.输入“无穷大”值,譬如90

4.输入各条边的信息

5.运行结果为

因为程序设置的是浮点型数据(float),故输出结果中会有一些误差。

其余的结果皆正确。

4.2有向图部分

如图所示,为一张有向图

ALGraphm={{0,NULL}};

/*有向图的初始化*/

ALGraph*g=&

m;

creatALGraph(g);

/*输入有向图的信息*/

该有向图的邻接表如下所示:

printfALGraph(g);

/*输出邻接表*/

2.输入顶点信息

3.输入各条边的信息

与原图对照,可知结果正确。

5.时间复杂度说明

构造一个具有n个顶点和e条边的无向网MGraph的时间复杂度是

,其中对邻接矩阵MGraph.arcs的初始化耗费了

的时间。

假设网中有n个顶点,对用邻接矩阵表示的无向网进行遍历所需的时间复杂度为

对普里姆算法而言,第一个进行初始化的循环语句的频度为n,第二个循环语句的频度为n-1。

其中有2个内循环:

其一是在cs[v].lowcost中求最小值,其频度为n-1;

其二是重新选择具有最小代价的边,其频度为n。

由此,普里姆算法的时间复杂度为

,与网中的边数无关,因此适用于求边稠密的网的最小生成树。

建立有向图的邻接表的时间复杂度为

6.心得体会

数据结构这门课的思想性很强,它包纳了线性表、树、图等等逻辑结构。

但学习这门课,光靠上课听讲还远远不能满足学习的需要,必须亲自编写源程序,不断地调试、运行、反复地思考,才能加深对本学科的认识,强化对所学知识的应用。

我认为,数据结构的相关知识和C语言的学习完全可以融为一体,一方面学习算法思想,另一方面用语言去实践。

相得益彰,趣味盎然。

参考文献

严蔚敏吴伟民.数据结构(C语言版).北京:

清华大学出版社.1992年4月

徐孝凯贺桂英.数据结构(C语言描述).北京:

清华大学出版社.2004年2月

李克清夏祥胜崔洪芳.数据结构——C语言描述.武汉:

华中科技大学出版社.2004年12月

C语言代码清单

1.无向网部分

#include<

stdio.h>

stdlib.h>

#definearcn

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

当前位置:首页 > 法律文书 > 起诉状

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1