图的基本操作与实现的课程设计报告.docx

上传人:b****5 文档编号:6407485 上传时间:2023-01-06 格式:DOCX 页数:30 大小:54.61KB
下载 相关 举报
图的基本操作与实现的课程设计报告.docx_第1页
第1页 / 共30页
图的基本操作与实现的课程设计报告.docx_第2页
第2页 / 共30页
图的基本操作与实现的课程设计报告.docx_第3页
第3页 / 共30页
图的基本操作与实现的课程设计报告.docx_第4页
第4页 / 共30页
图的基本操作与实现的课程设计报告.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

图的基本操作与实现的课程设计报告.docx

《图的基本操作与实现的课程设计报告.docx》由会员分享,可在线阅读,更多相关《图的基本操作与实现的课程设计报告.docx(30页珍藏版)》请在冰豆网上搜索。

图的基本操作与实现的课程设计报告.docx

图的基本操作与实现的课程设计报告

 

中国矿业大学徐海学院计算机系

《软件认知实践》报告

姓名:

学号:

专业:

设计题目:

指导教师:

2013年12月30日

 

目录

第1章题目概述2

第1.1节题目要求2

第1.2节主要难点3

第2章系统流程图4

第3章数据结构和算法5

第4章核心代码分析6

第5章复杂度分析25

参考文献25

 

第1章题目概述

第1.1节题目要求

(1)自选存储结构,输入含n个顶点(用字符表示顶点)和e条边的图G;

(2)求每个顶点的度,输出结果;

(3)指定任意顶点x为初始顶点,对图G作DFS遍历,输出DFS顶点序列(提示:

使用一个栈实现DFS);

(4)指定任意顶点x为初始顶点,对图G作BFS遍历,输出BFS顶点序列(提示:

使用一个队列实现BFS);

(5)输入顶点x,查找图G:

若存在含x的顶点,则删除该结点及与之相关连的边,并作DFS遍历(执行操作3);否则输出信息“无x”;

(6)判断图G是否是连通图,输出信息“YES”/“NO”;

(7)如果选用的存储结构是邻接矩阵,则用邻接矩阵的信息生成图G的邻接表,即复制图G,然再执行操作

(2);反之亦然。

第1.2节主要难点

(1)自选存储结构创建一个图:

通过用户从键盘敲入的两个数值分别确定图的顶点数和边数,选择邻接矩阵存储结构将图的结点信息存储在一个顺序表中,图的边信息存储在一个二维数组中。

(2)求每个顶点的度:

1.邻接矩阵存储结构下求每个顶点的度:

利用图的邻接矩阵,每个顶点所在行和所在列的边的权值如果存在则该顶点的度+1,依次算出每个顶点的度,并且记录在一个数组中输出。

2.邻接表存储结构下求每个顶点的度:

定义一个邻接边指针循环指向顶点的邻接边单链表头结点,当结点不空时,该顶点的出度+1,邻接边弧头结点的入度+1,依次求出每个顶点的出度和入度之和就为该顶点的度。

(3)图的深度优先遍历:

采取邻接矩阵结构,指定任意顶点x为初始顶点

1.访问结点v并标记结点v已访问;

2.查找结点v的第一个邻接结点w;

3.若结点v的邻接结点w存在,则继续执行,否则算法结束;

4.若结点w尚未被访问,则递归访问结点w;

5.查找结点v的w邻接结点的下一个邻接结点w,转到步骤3。

(4)图的广度优先遍历:

采取邻接矩阵结构,指定任意顶点x为初始顶点,利用顺序循环队列以保持访问过的结点的顺序

1.首先访问初始结点v并标记结点v为已访问;

2.结点v入队列;

3.当队列非空时则继续执行,否则算法结束;

4.出队列取得队头结点u;

5.查找u的第一个邻接结点w;

6.若u的邻接结点w不存在则转到步骤3,否则循环执行下列步骤:

6.1若结点w尚未被访问,则访问结点w并标记结点w为已访问;

6.2结点w入队列;

6.3查找结点u的w邻接结点的下一个邻接结点w,转到步骤6。

(5)判断有向图的强连通性:

采取邻接表结构,在图中寻找一个包含所有顶点且首尾相连的环,若这样的环存在,则该图为强连通图,否则不为强连通图。

(6)用邻接矩阵的信息生成邻接表:

定义一个邻接表的边信息结构体,将邻接矩阵的边信息转换成邻接表的边信息存储到邻接边的单链表中。

 

第二章系统流程图

第3章数据结构和算法

(1)有向图顶点的数据类型DataType定义如下:

typedefintDataType;

(2)邻接矩阵存储结构下图的结构体定义如下:

typedefstruct

{

SeqListVertices;

intedge[MaxVertices][MaxVertices];

intnumOfEdges;

}AdjMGraph;

(3)邻接矩阵存储结构下图的边信息结构体定义如下:

typedefstruct

{

introw;

intcol;

intweight;

}RowColWeight;

(4)邻接表存储结构下图的结构体定义如下:

typedefstructNode

{

intdest;

structNode*next;

}Edge;

typedefstruct

{

DataTypedata;

intsorce;

Edge*adj;

}AdjLHeight;

typedefstruct

{

AdjLHeighta[MaxVertices];

intnumOfVerts;

intnumOfEdges;

}AdjLGraph;

(5)邻接表存储结构下图的边信息结构体定义如下:

typedefstruct

{

introw;

intcol;

}RowCol;

(6)顺序循环队列的结构体定义如下:

typedefstruct

{

DataTypequeue[MaxQueueSize];

intrear;

intfront;

intcount;

}SeqCQueue;

(7)顺序表的结构体定义如下:

typedefstruct

{

DataTypelist[MaxSize];

intsize;

}SeqList;

第四章核心代码分析

源程序存放在八个文件夹中,文件SeqList.h是顺序表的结构体定义和操作函数,文件SeqCQueue.h是顺序循环队列的结构体定义和操作函数,文件AdjMGraph.h是邻接矩阵存储结构下图的结构体定义和操作函数,文件AdjMGraphCreate.h是邻接矩阵存储结构下图的创建函数,文件AdjLGraph.h是邻接表存储结构下图的结构体定义和操作函数,文件AdjLGraphCreate.h是邻接表存储结构下图的创建函数,文件AdjMGraphTraverse.h是邻接矩阵存储结构下图的深度优先遍历和广度优先遍历操作函数,文件图的基本操作与实现.c是主函数。

(1)/*文件SeqList.h*/

typedefstruct

{

DataTypelist[MaxSize];

intsize;

}SeqList;

voidListInitiate(SeqList*L)

{

L->size=0;

}

intListLength(SeqListL)

{

returnL.size;

}

intListInsert(SeqList*L,inti,DataTypex)

{

intj;

if(L->size>=MaxSize)

{

printf("数组已满无法插入!

\n");

return0;

}

elseif(i<0||i>L->size)

{

printf("参数不合法!

\n");

return0;

}

else

{

for(j=L->size;j>i;i--)L->list[j]=L->list[j-1];

L->list[i]=x;

L->size++;

return1;

}

}

intListDelete(SeqList*L,inti,DataType*x)

{

intj;

if(L->size<=0)

{

printf("顺序表已空无数据元素可删!

\n");

return0;

}

elseif(i<0||i>L->size-1)

{

printf("参数i不合法!

\n");

return0;

}

else

{

*x=L->list[i];

for(j=i+1;j<=L->size-1;j++)L->list[j-1]=L->list[j];

L->size--;

return1;

}

}

intListGet(SeqListL,inti,DataType*x)

{

if(i<0||i>L.size-1)

{

printf("参数i不合法!

\n");

return0;

}

else

{

*x=L.list[i];

return1;

}

}

(2)/*文件SeqCQueue.h*/

typedefstruct

{

DataTypequeue[MaxQueueSize];

intrear;

intfront;

intcount;

}SeqCQueue;

voidQueueInitiate(SeqCQueue*Q)

{

Q->rear=0;

Q->front=0;

Q->count=0;

}

intQueueNotEmpty(SeqCQueueQ)

{

if(Q.count!

=0)return1;

elsereturn0;

}

intQueueAppend(SeqCQueue*Q,DataTypex)

{

if(Q->count>0&&Q->rear==Q->front)

{

printf("队列已满无法插入!

");

return0;

}

else

{

Q->queue[Q->rear]=x;

Q->rear=(Q->rear+1)%MaxQueueSize;

Q->count++;

return1;

}

}

intQueueDelete(SeqCQueue*Q,DataType*d)

{

if(Q->count==0)

{

printf("队列已空无数据出队列!

\n");

return0;

}

else

{

*d=Q->queue[Q->front];

Q->front=(Q->front+1)%MaxQueueSize;

Q->count--;

return1;

}

}

intQueueGet(SeqCQueueQ,DataType*d)

{

if(Q.count==0)

{

printf("队列已空无数据出队列!

\n");

return0;

}

else

{

*d=Q.queue[Q.front];

return1;

}

}

(3)/*文件AdjMGraph.h*/

#include"SeqList.h"

typedefstruct

{

SeqListVertices;//存放结点的顺序表

intedge[MaxVertices][MaxVertices];//存放边的邻接矩阵

intnumOfEdges;//边的条数

}AdjMGraph;//边的结构体定义

voidInitiate(AdjMGraph*G,intn)//初始化

{

inti,j;

for(i=0;i

for(j=0;j

{

if(i==j)

G->edge[i][j]=0;

else

G->edge[i][j]=MaxWeight;

}

G->numOfEdges=0;//边的条数置为0

ListInitiate(&G->Vertices);//顺序表初始化

}

voidInsertVertex(AdjMGraph*G,DataTypevertex)//在图G中插入结点vertex

{

ListInsert(&G->Vertices,G->Vertices.size,vertex);//顺序表尾插入

}

voidInsertEdge(AdjMGraph*G,intv1,intv2,intweight)

//在图G中插入边,边的权为weight

{

if(v1<0||v1>G->Vertices.size||v2<0||v2>G->Vertices.size)

{

printf("参数v1或v2越界出错!

\n");

exit

(1);

}

G->edge[v1][v2]=weight;

G->numOfEdges++;

}

voidDeleteEdge(AdjMGraph*G,intv1,intv2)//在图中删除边

{

if(v1<0||v1>G->Vertices.size||v2<0||v2>G->Vertices.size||v1==v2)

{

printf("参数v1或v2越界出错!

\n");

exit

(1);

}

if(G->edge[v1][v2]==MaxWeight||v1==v2)

{

printf("该边不存在!

\n");

exit(0);

}

G->edge[v1][v2]=MaxWeight;

G->numOfEdges--;

}

voidDeleteVerten(AdjMGraph*G,intv)//删除结点v

{

intn=ListLength(G->Vertices),i,j;

DataTypex;

for(i=0;i

{

for(j=0;j

if((i==v||j==v)&&G->edge[i][j]>0&&G->edge[i][j]

G->numOfEdges--;//计算被删除边

}

for(i=v;i

{

for(j=0;j

G->edge[i][j]=G->edge[i+1][j];

}

for(i=0;i

{

for(j=v;j

G->edge[i][j]=G->edge[i][j+1];

}

ListDelete(&G->Vertices,v,&x);//删除结点v

}

intGetFistVex(AdjMGraph*G,intv)

//在图G中寻找序号为v的结点的第一个邻接结点

//如果这样的邻接结点存在,返回该邻接结点的序号;否则,返回-1

{

intcol;

if(v<0||v>G->Vertices.size)

{

printf("参数v1越界出错!

\n");

exit

(1);

}

for(col=0;colVertices.size;col++)

if(G->edge[v][col]>0&&G->edge[v][col]

return-1;

}

intGetNextVex(AdjMGraph*G,intv1,intv2)

//在图中寻找v1结点的邻接结点v2的下一个邻接结点

//如果这样的结点存在,返回该邻接结点的序号;否则,返回-1

//v1和v2都是相应结点的序号

{

intcol;

if(v1<0||v1>G->Vertices.size||v2<0||v2>G->Vertices.size)

{

printf("参数v1或v2越界出错!

\n");

exit

(1);

}

for(col=v2+1;colVertices.size;col++)

if(G->edge[v1][col]>0&&G->edge[v1][col]

return-1;

}

//输出图G的邻接矩阵

voidPrint(AdjMGraph*G)

{

inti,j;

for(i=0;iVertices.size;i++)

{

for(j=0;jVertices.size;j++)

printf("%6d",G->edge[i][j]);

printf("\n");

}

}

//邻接矩阵存储结构下求出每个顶点的度并输出

voidMVertices(AdjMGraph*G,DataTypea[])

{

inti,j,m;

DataTypeb[MaxVertices];//用数组b[]记录相应结点的度

for(i=0;iVertices.size;i++)

b[i]=0;//置0

printf("邻接矩阵存储结构下图的顶点的度为:

\n");

for(m=0;mVertices.size;m++)//求出每个结点的度

{

for(i=0;iVertices.size;i++)

for(j=0;jVertices.size;j++)

{

if(i==m&&G->edge[i][j]>0&&G->edge[i][j]

//求出邻接矩阵第i行权值存在的边的个数,当边存在时,b[m]加1

b[m]++;

if(j==m&&i!

=m&&G->edge[i][j]>0&&G->edge[i][j]

//求出邻接矩阵第j列权值存在的边的个数,当边存在时,b[m]加1

b[m]++;

}

printf("顶点%d的度为:

%d\n",a[m],b[m]);

}

}

//查找图G中是否存在点v

intChaZhao(AdjMGraph*G,intv)

{

if(0<=v&&vVertices.size)

{

printf("存在顶点%d\n",v);

return1;

}

else

{

printf("不存在顶点%d\n",v);

return0;

}

}

//删除查找到的结点v并删除该结点及与之相关的边

voidMDelete(AdjMGraph*G,intv)

{

inti;

for(i=0;iVertices.size;i++)

{

if(G->edge[v][i]>0&&G->edge[v][i]

//当邻接矩阵的第v行有边存在时,删除边

DeleteEdge(G,v,i);

if(G->edge[i][v]>0&&G->edge[i][v]

//当邻接矩阵的第j行有边存在时,删除边

DeleteEdge(G,i,v);

}

DeleteVerten(G,v);//删除结点v

}

(4)/*文件AdjMGraphCreate.h*/

typedefstruct

{

introw;//行下标

intcol;//列下标

intweight;//权值

}RowColWeight;//边信息结构体定义

voidCreatGraph(AdjMGraph*G,DataTypev[],intn,RowColWeightE[],inte)

//在图G中插入n个结点信息v和e条边信息E

{

inti,k;

Initiate(G,n);//结点顺序表初始化

for(i=0;i

InsertVertex(G,v[i]);//结点插入

for(k=0;k

InsertEdge(G,E[k].row,E[k].col,E[k].weight);//边插入

}

(5)/*文件AdjLGraph.h*/

//邻接表的存储结构

typedefstructNode

{

intdest;//邻接边的弧头结点序号

structNode*next;

}Edge;//邻接边单链表的结点结构体

typedefstruct

{

DataTypedata;//结点数据元素

intsorce;//邻接边的弧尾结点序号

Edge*adj;//邻接边的头指针

}AdjLHeight;//数组的数据元素类型结构体

typedefstruct

{

AdjLHeighta[MaxVertices];//邻接表数组

intnumOfVerts;//结点个数

intnumOfEdges;//边个数

}AdjLGraph;//邻接表结构体

//初始化操作函数

voidLAdjInitiate(AdjLGraph*G)

{

inti;

G->numOfVerts=0;

G->numOfEdges=0;

for(i=0;i

{

G->a[i].sorce=i;

G->a[i].adj=NULL;

}

}

//撤销操作函数

voidLAdjDestroy(AdjLGraph*G)

//撤销图G中的所有邻接边单链表

{

inti;

Edge*p,*q;

for(i=0;inumOfVerts;i++)

{

p=G->a[i].adj;

while(p!

=NULL)

{

q=p->next;

free(p);

p=q;

}

}

}

//插入结点操作函数

voidLInsertVertex(AdjLGraph*G,inti,DataTypevertex)

//在图G中的第i(0<=i

{

if(i>=0&&i

{

G->a[i].data=vertex;//存储结点数据元素vertex

G->numOfVerts++;//个数加1

}

else

printf("结点越界");

}

//插入边操作函数

voidLInsertEdge(AdjLGraph*G,intv1,intv2)

//在图G中加入边的信息

{

Edge*p;//定义一个邻接边指针

if(v1<0||v1>=G->numOfVerts||v2<0||v2>=G->numOfVerts)

{

printf("参数v1或v2越界出错");

exit(0);

}

p=(Edge*)malloc(sizeof(Edge));//申请邻接边单链表结点空间

p->dest=v2;//置邻接边弧头序号

p->next=G->a[v1].adj;//新结点插入单链表的表头

G->a[v1].adj=p;//头指针指向新的单链表表头

G->numOfEdges++;//边数个数加1

}

//删除边操作函数

voidLDeleteEdge(AdjLGraph*G,intv1,intv2)

//删除图G中的边

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

当前位置:首页 > 工程科技 > 能源化工

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

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