数据结构图的算法程序Word格式.docx
《数据结构图的算法程序Word格式.docx》由会员分享,可在线阅读,更多相关《数据结构图的算法程序Word格式.docx(26页珍藏版)》请在冰豆网上搜索。
getchar();
%c"
vexs[i]));
}
for(j=0;
j<
j++)
edges[i][j]=0;
请输入每条边对应的两个顶点的序号(输入格式为:
i,j):
for(k=0;
k<
e;
k++)
请输入第%d条边的顶点序号:
"
k+1);
%c,%c"
ch1,&
ch2);
ch1!
=G->
vexs[i];
i++);
ch2!
vexs[j];
j++);
edges[i][j]=1;
7-2-2
邻接表
#define
10
//
最大顶点数为10
struct
node{
边表结点
adjvex;
邻接点域
node
*
next;
指向下一个邻接点的指针域
//若要表示边上信息,则应增加一个数据域info
}EdgeNode;
vnode{
顶点表结点
VertexType
vertex;
顶点域
EdgeNode
firstedge;
边表头指针
}VertexNode;
VertexNode
AdjList[MAXLEN];
AdjList是邻接表类型
struct{
AdjList
adjlist;
接表
顶点数和边数
}ALGraph;
ALGraph是以邻接表方式存储的图类型
建立一个有向图的邻接表存储的算法如下:
CreateGraphAL
(ALGraph
s;
顶点数,边数):
读入顶点数和边数
请输入顶点信息(输入格式为:
顶点号<
for
(i=0;
i++)
立有n个顶点的顶点表
\n%c"
adjlist[i].vertex));
读入顶点信息
adjlist[i].firstedge=NULL;
点的边表头指针设为空
请输入边的信息(输入格式为:
i,j):
(k=0;
k++)
建立边表
\n%d,%d"
i,&
j);
读入边<
Vi,Vj>
的顶点对应序号
s=new
EdgeNode;
生成新边表结点s
s->
adjvex=j;
邻接点序号为j
next=G->
adjlist[i].firstedge;
将新边表结点s插入到顶点Vi的边表头部
adjlist[i].firstedge=s;
7-3
图的遍历
7-3-1
深度优先搜索
DFSTraverseM(MGraph
i;
visited[i]=FALSE;
FALSE在c语言中定义为0,以下同
if(!
visited[i])
DFSM(G,i);
DFSM(MGraph
*G,int
i)
j;
\t\t深度优先遍历结点:
结点%c\n"
G->
vexs[i]);
visited[i]=TRUE;
TRUE在c语言中定义为0,以下同
if(G->
edges[i][j]==1&
&
!
visited[j])
DFSM(G,j);
7-3-2
广度优先搜索
BFSTraverseM(MGraph
if
(!
BFSM(G,i);
BFSM(MGraph
k)
i,j;
CirQueue
Q;
InitQueue(&
Q);
广度优先遍历结点:
vexs[k]);
visited[k]=TRUE;
EnQueue(&
Q,k);
while
QueueEmpty(&
Q))
i=DeQueue(&
(j=0;
%c\n"
vexs[j]);
visited[j]=TRUE;
Q,j);
7-4
图的连通性
7-4-1
无向图的连通分量和生成树
7-4-2
最小生成树
1.最小生成树的基本概念
2.常用的构造最小生成树的方法
构造最小生成树的Prim算法
构造最小生成树的Kruskal算法
7-5
最短路径
小结
实验7
图子系统
1.实验目的
2.实验内容
3.操作举例
4.参考程序
#include
<
stdio.h>
FALSE
TRUE
1
Error
printf
QueueSize
30
visited[10];
*G);
i);
front;
rear;
count;
data[QueueSize];
}CirQueue;
InitQueue(CirQueue
*Q)
{Q->
front=Q->
rear=0;
Q->
count=0;
QueueEmpty(CirQueue
{return
count=QueueSize;
QueueFull(CirQueue
count==QueueSize;
EnQueue(CirQueue
*Q,int
x)
(QueueFull(Q))
Error("
Queue
overflow"
else
count++;
data[Q->
rear]=x;
rear=(Q->
rear+1)%QueueSize;
DeQueue(CirQueue
{int
temp;
if(QueueEmpty(Q))
underflow"
return
NULL;
else{temp=Q->
front];
count--;
front=(Q->
front+1)%QueueSize;
main()
{MGraph
*G,a;
ch1;
i,j,ch2;
G=&
a;
\n\t\t建立一个有向图的邻接矩阵表示\n"
CreateMGraph(G);
\n\t\t已建立一个图的邻矩阵存储\n\t\t"
%5d"
edges[i][j]);
\n\t\t"
ch1='
y'
;
while(ch1=='
||ch1=='
Y'
)
\n\n\n\n\n\t\t图
子
系
统\n"
\t\t*****************************************\n"
\t\t*
1-------更新邻接矩阵
*\n"
2-------深度优先遍历
3-------广度优先遍历
0-------退
出
\t\t请选择菜单号(0--3):
%d"
switch(ch2)
case
1:
\t\t\t图的邻接矩阵存储建立完毕.\n"
break;
2:
DFSTraverseM(G);
3:
BFSTraverseM(G);
0:
n'
default:
\t\t输入错误!
请重新输入!
\t\t请输入顶点数和边数(输入格式为:
\t\t请输入顶点信息(顶点号<
\t\t"
\t\t请输入每条边对应的两个顶点的序号(输入格式为:
\t\t请输入第%d条边的顶点序号:
\t\t广度优先遍历结点:
数据结构中图的应用
图在数据结构中应用十分广泛,对于图来说最重要的当然是算法,而且相当的一部分都是很专业的,一般的人几乎不会接触到;
相对而言,结构就显得分量很轻。
你可以看到关于图中元素的操作很少,远没有单链表那里列出的一大堆“接口”。
——一个结构如果复杂,那么能确切定义的操作就很有限。
基本储存方法
不管怎么说,还是先得把图存起来。
不要看书上列出了好多方法,根本只有一个——邻接矩阵。
如果矩阵是稀疏的,那就可以用十字链表来储存矩阵(见前面的《稀疏矩阵(十字链表)》)。
如果我们只关系行的关系,那么就是邻接表(出边表);
反之,只关心列的关系,就是逆邻接表(入边表)。
下面给出两种储存方法的实现。
#ifndefGraphmem_H
#defineGraphmem_H
#include<
vector>
list>
usingnamespacestd;
template<
classname,classdist,classmem>
classNetwork;
constintmaxV=20;
//最大节点数
classname,classdist>
classAdjMatrix
friendclassNetwork<
name,dist,AdjMatrix<
name,dist>
>
public:
AdjMatrix():
vNum(0),eNum(0)
vertex=newname[maxV];
edge=newdist*[maxV];
for(inti=0;
i<
maxV;
i++)edge[i]=newdist[maxV];
~AdjMatrix()
i++)delete[]edge[i];
delete[]edge;
delete[]vertex;
boolinsertV(namev)
if(find(v))returnfalse;
vertex[vNum]=v;
i++)edge[vNum][i]=NoEdge;
vNum++;
returntrue;
boolinsertE(namev1,namev2,distcost)
inti,j;
if(v1==v2||!
find(v1,i)||!
find(v2,j))returnfalse;
if(edge[i][j]!
=NoEdge)returnfalse;
edge[i][j]=cost;
eNum++;
name&
getV(intn){returnvertex[n];
}//没有越界检查
intnextV(intm,intn)//返回m号顶点的第n号顶点后第一个邻接顶点号,无返回-1
for(inti=n+1;
vNum;
i++)if(edge[m][i]!
=NoEdge)returni;
return-1;
private:
intvNum,eNum;
distNoEdge,**edge;
name*vertex;
boolfind(constname&
v)
i++)if(v==vertex[i])returntrue;
returnfalse;
v,int&
i)
for(i=0;
};
classLinkedList
name,dist,LinkedList<
LinkedList():
vNum(0),eNum(0){}
~LinkedList()
i++)deletevertices[i].e;
vertices.push_back(vertex(v,newlist<
edge>
));
boolinsertE(constname&
v1,constname&
v2,constdist&
cost)
for(list<
:
iteratoriter=vertices[i].e->
begin();
iter!
=vertices[i].e->
end()&
iter->
vID<
j;
iter++);
if(iter==vertices[i].e->
end())
vertices[i].e->
push_back(edge(j,cost));
if(iter->
vID==j)returnfalse;
insert(iter,edge(j,cost));
getV(intn){returnvertices[n].v;
iteratoriter=vertices[m].e->
=vertices[m].e->
end();
iter++)if(iter->
vID>
n)returniter->
vID;
i++)if(v==vertices[i].v)returntrue;
structedge
edge(){}
edge(intvID,distcost):
vID(vID),cost(cost){}
intvID;
distcost;
structvertex
vertex(){}
vertex(namev,list<
*e):
v(v),e(e){}
namev;
list<
*e;
vector<
vertex>
vertices;
#endif
这个实现是很简陋的,但应该能满足后面的讲解了。
现在这个还什么都不能做,不要急,在下篇将讲述图的DFS和BFS
DFS和BFS
对于非线性的结构,遍历都会首先成为一个问题。
和二叉树的遍历一样,图也有深度优先搜索(DFS)和广度优先搜索(BFS)两种。
不同的是,图中每个顶点没有了祖先和子孙的关系,因此,前序、中序、后序不再有意义了。
仿照二叉树的遍历,很容易就能完成DFS和BFS,只