




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
图 表图定义图是由顶点集合(vertex)及顶点间的关Graph=(V,E其 V={x|x某个数据对象是顶点的有穷非空集合E={(x,y)|x,yV E={<x,y>|x,yV&&Path(x,集合。Path(xy)表示xy的一条单向通路, 在有向图中,顶点对<x,y>是有序的。在无向图中,顶点对(x,y)是无序的。 若有n个顶点的无向图有n(n-1)/2条边,则此图为完全无向图。有n个顶点的有向图有n(n-1)条边,则此图为完全有向图。 如果(u,v)是E(G)中的一条边,则称u与v互为邻接顶点。 某些图的边具有与它相关的数,称之为权。子图设有两个图G=(V,E)和G‘=(V’,E‘)。若V’VE‘E,则称GG的子图。顶点的度一个顶点v的度是与它相关联的边的条数。记作TD(v)。在有向图中,顶点的度等于v的入度是以v为终点的有向边的条数,记作ID(v);顶点v的出度是以v为始点的有向边的条数,记作OD(v)。 在图G=(V,E)中,若从顶点vi出发,沿一些边经过一些顶点vp1,vp2,…,vpm,到达顶点vj。则称顶点序列(vi vp1vp2...vpm vj)为从顶点vi到顶点vj的路径。它经过的边(vi,vp1)、(vp1,vp2)、...、(vpm,vj)应是属于E的边。路径长带权图的路径长度是指路径上各边的权 若路径上各顶点v1,v2,...,vm均不互相重复,则称这样的路径为简单路径。回 若路径上第一个顶点v1与最后一个顶vm重合,则称这样的路径为回路或环 在无向图中,若从顶点v1到顶点v2有路径,则称顶点v1与v2是连通的。如果图中任意一对顶点都是连通的,则称此图是连通强连通图与强连通分量在有向图中若对于每一对顶点vi和vj,都存在一条从vi到vj和从vj到vi的路径则称此图是强连通图。非强连通图的极大 讨论的classGraph{Graph(voidInsertVertex(constType&vertex);voidInsertEdge(constintv1,constintv2,intweight);voidRemoveVertex(constintv);voidRemoveEdge(constintv1,constintv2);intIsEmpty();TypeGetWeight(constintv1,constintv2);intGetFirstNeighbor(constintv);intGetNextNeighbor(constintv1,constintv2}图 表(Adjacency在图的邻接矩阵表示中,有一个信息的顶点表,还有一个的邻接矩阵。AVE)是一个n个顶点的图,则图的邻接矩阵是一个二维数组A.edge[n][n],定义A.Edge[i][j]
否
j>E
(i,
j)无向图的邻接矩阵是对称的,有向图的邻接矩阵可能是不对称的。在有向图中,统计第i1的个数可得顶点i的出度,统计第j1的个数可得顶点j的入度。在无向图中,统计第i(列)1的个数可得顶点i的度。W(i,
j且
j
或
j)A.Edge[i][j]=
i!=
i==constintMaxEdges=50;constintMaxVertices=10;template<classNameType,classDistType>classGraph{DistTypeEdge[MaxVertices][MaxVertices];intintFindVertex(SeqList<NameType>&L;constNameType&vertex){returnL.Find(vertex);intGetVertexPos(ConstNameType&vertex{returnFindVertex(VerticesList,vertex);}Graph(constintsz=MaxNumEdges);intGraphEmpty()const{returnVerticesList.IsEmpty();}intGraphFull()const{returnVerticesList.IsFull()CurrentEdges==MaxEdges;}intNumberOfVertices()intNumberOfEdges(){returnCurrentEdges;NameTypeGetValue(constinti{returni>=0&&i<?VerticesList.data[i]:NULL;}intGetWeight(constintv1,constintv2);intGetFirstNeighbor(constintv);intGetNextNeighbor(constintv1,constintv2);voidInsertVertex(constNameType&vertex);voidInsertEdge(constintv1,constintv2,DistTypeweight);voidRemoveVertex(constintv);voidRemoveEdge(constintv1,constintv2}邻接矩阵实现的部分图template<classNameType,class//构造for(inti=0;i<sz;i++for(intj=0;j<sz;j++)Edge[i][j]=CurrentEdges=}template<classNameType,classDistType>DistTypeGraph<NameType,DistType>::GetWeight(constintv1,constintv2){//给出以顶v1v2为两端点的边上的权if(v1!=-1&&v2!=-1returnelsereturn}template<classNameType,classDistType>intGraph<NameType,DistType>::GetFirstNeighbor(constintv){//给出顶点位置为v的第一个邻接顶点的位if(v!=-1)for(intcol=0;col<CurrentEdges;col++if(Edge[row][col]>0)return}return-}template<classNameType,classDistType>intGraph<NameType,DistType>::GetNextNeighbor(constintv1,constintv2){if(v1!=-1&&v2!=-1){for(intcol=v2+1;col<CurrentEdges;col++if(Edge[v1][col]>0)return}return-}(Adjacency无向图的邻接 下标dest和指向同一链表中下一个边结点的指针link。有向图的邻接表和逆邻在有向图的邻接表中,第i个边链表 都是顶点i发出的边。也叫做出边表。在有向图的逆邻接表中,第i个边链表 边都是进入顶点i的边。也叫做入边表。带权图的边结点中保存该边上的权值cost。顶点i的边链表的表头指针adj在顶点表的下标为i的顶点记录中,该记录还保存了该顶点在邻接表的边链表中,各个边结点的链入顺任意,视边结点输入次序而定设图中有n个顶点,e条边,则用邻接表表示无向图时,需要n个顶点结点,2e个边结点;只需n个顶点结点,e个边结点。constintDefaultSize=template<classDistType>classtemplate<classDistType>structEdge{intdest;DistTypecost;Edge(){}Edge(intD,DistTypeC)dest(D),cost(C),link(NULL){}intoperator!=(constEdge&E)const{returndest!=E.dest;}template<classNameType,classDistType>structVertex{NemeTypedata;}template<classNameType,classDistType>classGraph{friendclassvertex<NameType,DistType>;friendclassEdge<DistType>;intNumVertices;intintintGetVertexPos(constType&vertex);Graph(intsz~Graph(intGraphEmpty(const{returnNumVertices==0;}intGraphFull()constNumEdges==MaxEdges;}NameTypeGetValue(constinti){returni>=0&&i<NumVerticesNodeTable[i].data:NULL;intNumberOfVertices(){returnNumVertices;}intNumberOfEdges(){returnNumEdges;}voidInsertVertex(constNameType&vertex);voidRemoveVertex(constintv);voidInsertEdge(constintv1,constintconstDistTypeweightvoidRemoveEdge(constintv1,constintv2);DistTypeGetWeight(constintv1,constintv2);intGetFirstNeighbor(constintv);intGetNextNeighbor(constintv1,constintv2}(带权图邻接表的构造函数和析构函template<classNameType,classGraph<NameType,Graph(constintsz=DefaultSize)intn,e,k,j;NameTypename,tail,head;DistTypeweight;NodeTable= newcin>>n; forinti0ini++)//输入各顶点信{cin>>name;InserVertex(name);}cin>>e; fori0iei{//逐条边输cin>>tail>>head>>k=GetVertexPos(tail);j=GetVertexPos(head);InsertEdge(k,j,weight}}template<classNameType,classGraph<NameType,DistType>::~Graph(){for(inti=0;i<NumVertices;i++){Edge<DistType>*p=NodeTable[i].adj;while(p!=NULL){ NodeTable[i].adj=p→link;deletep=NodeTable[i].adj;}delete //释放顶点}邻接表部分成员函数的template<classNameType,classDistType>intGraph<NameType,DistType>::GetVertexPos(ConstNameType&vertex){for(inti=0;i<NumVertices;i++)if(NodeTable[i].data==vertex)returnreturn-}template<ClassNameType,classDistType>intGraph<NameType,DistType>::GetFirstNeighbor(constintv){//查找顶点v的第一个邻接顶点在邻接表中ifv-1 //若顶点Edge<DistType>*p=if(p!=NULL)return}return- //若顶点不存}template<ClassNameType,classDistTypeType>intGraph<NameType,DistType>::GetNextNeighbor(constintv1,constintv2){//查找顶点v1在邻接顶v2后下一个邻if(v1!=-1)Edge<DistType>*p=while(p!=NULL)if(p→dest==v2&&p→link!=NULLreturnelsep=p→link;}}return- //没有查到下一个邻接顶点返回-}template<ClassNameType,classDistType>DistTypeGraph<NameType,DistType>::GetWeight(constintv1,constintv2){//取两端点v1v2的边上的权if(v1!=-1&&v2!=-1)Edge<DistType>*p=while(p!=NULL)if(p→dest==v2)retur elsep=p→link;}}return}(Adjacency无向图的情其中,mark是记录是否处理过的标记; 一个存放与该边相关的权值的域cost。顶点结点的结顶点信息的结点表以顺序表方式组织,每一个顶点结点有两个数据成员:其中,ata存放与该顶点相关的信息,irtot是指示第一条依附于该顶点的边的指针。 从i出发可以循链找到所有依附于该顶点有向图的情在用邻接表表示有向图时,有时需要同时使用邻接表和逆邻接表。用有向图的邻接多重表(链表可把这两个表结合起来表示。markvertex1和vertex2指path1是指向始顶点与该边相同的下一条边的指针;path2指针。需要时还可cost。顶点结点的结每个顶点有一个结点,它相当于出边表和入data存放与FirstinFirstout指示以该顶点为终顶点的入边表的第一条边。邻接多重表的一次,就叫做图的遍历(GraphTraversal)。其它顶点相通,在完某个顶点之后可能会沿着某些边又回到了曾经过的顶点。为了避免重复,可设置一个标志顶点是否被过的辅助数组visited[],它的初始状态为0,在图的遍历过程中,一旦某一个顶点i,就立即让visited[i1,防止它被多。深度优先搜索DFSDepthFirstSearch深度优先搜索的示DFS在 图中某一起始顶点v后,由v出发,它的任一邻接顶点w1;再从w1出发,访问与w1邻接但还没有过的顶点w2;然再从w2出发,进行类似的 ,…如此进行 顶点u为止。接着,退回一步,退到前一次刚 邻接顶点。如果有,则此顶点,之后再此顶点出发,进行与前述类似的;如果没直到连通图中所有顶点都被过为止。viodGraph::DFSconstintvintvisited{cout<<GetValue(v)<<‘’;// vvisited[v]= //顶点v 标intw=GetFirstNeighbor//v的第一个邻接顶whilew-1 //若邻接顶w存if(!visited[w])DFS(w,visited//若顶点w 过,递 顶点w=GetNextNeighbor(v,w//取顶v的排w后面的下一个邻接顶}}voidGraph::DFS()visitednewBoolean //创建for(inti=0;i<n;i++)visited[i]= 标记数visited初始DFSdelete //}图中n个顶点,e条边如果用邻接表表示图,沿Firstout→link链可以找到某个顶点v的所有邻接顶点w。由于总共有2e个边结点,所以扫描边的时间为O(e)。 ,则遍历图中所有2。广度优先搜索BFSBreadthFirstSearch广度优先搜索的示广度优先搜索过 广度优先生成 了起始顶点v之后,由v出发,依次 v的各个未曾被 过的邻接顶点w1,w2,…,wt,然后再顺序 w2,…,wt的所有还未被 过的邻接顶点,…如此做下去, 走一步可能是一个递归的过程,其算法也不是递归的。为了实现逐层,算法中使用了一个队列,以正在的这一层和上一层的顶点,以便于向下一层。与深度优先搜索过程一样,为避免重复,需要一个辅助数组visited,给被过的顶图的广度优先搜索算voidGraph::BFS(constintv)visitednew //for(inti=0;i<NumVertices;i++visited[i //visited初始化cout<<GetValue(v)<<'';visited[v]=Queue<int>q; q.EnQueue(v);// v,进队列while(!q.IsEmpty()){ v=q.DeQueue(); //不空,出队列intw=GetFirstNeighbor//取顶v的第一个邻接顶whilew-1 //若邻接顶w存if(!visited[w]) //若该邻接顶点 cout<<GetValue(w)<<‘ visited[w q.EnQueue //进}w=GetNextNeighbor(v,//取顶v的排w后面的下一邻接顶 //重复检测v的所有邻接顶}delete[]}价为d0+d1+…+d-1=,其中的di是i的度。如果使用邻接矩阵,则对于每一个被过的顶点,循环要检测矩阵中n个元素,总(Connected当无向图为非连通图时,从图中某一顶点出发,利用深度优先搜索算法或广度优先搜索算法不可能遍历到图中的所有顶点,只能 到该顶点所在的最大连通子图连通分的所有顶点。若从无向图的每 通分量中的一个顶点出发进行遍历,可求得无向图的所有连通分量。在算法中,需要对图的每一个顶点进行检测:若已被 过,则该顶点一定是落在图中已求得的连通分量上;若还未被 ,则从该顶点出发遍历图,可求得图的另 通分量。对于非连通的无向图,所有连通分量的生成树组成了非连通图的生成森林。确定连通分量的算 ponents()visitednew //创建for(inti=0;i<NumVertices;i++visited[i] //visited初始for(i=0;i<NumVertices;i++if(!visited[i]) //检测所有顶点是 DFS(i,visited);//从 的顶点出ponent(//输 通分}delete //释放(Biconnected中的顶点v及v的所有边v关节点。关节点的连通图叫做重连通图。在重连通图上任何一对顶点之间至少存在有两条路径在删去某个顶点及与该顶点相关联的边时,也不破坏图的连通性。在一个无向连通图G中重连通分量可以利用深dfn顶点的深度优先数,标明进行深度优先搜索时各顶点的次序。如果在深度优先生成树中,顶点u是顶点的祖先则有dfn[udfn[v]深度优先生成树的根是关节点的充要条件是它至少有两个。其它顶点u是关节点的充要条件是它至少有一个w,从w出发,不能通过w、w的一条回边所组成的路径到达u的祖先在图G的每一个顶点上定义一个low值,low[u]是从u或u的子孙出发通过回边可以low[u]=min{min{low[w]|w是u的一个 min{dfn[x]|(u,x)是一条回边}}u是关节点的充要条件是 的生成树的u不是根,但它有一 w,使low[w]这时w及其子孙不存在指向顶点u的祖先的回计算dfn与low的算法voidGraph::DfnLow(constintx)//公有函数:从顶点x开始深度优先搜intnum= //num 计数dfn=newlow=new//dfn是深度优先数,low是最小祖 顺序for(inti=0;i<NumVertices;i++{dfn[i]=low[i]=0;//给 计数器num及dfn[u],low[u]初DfnLow(x,-1); delete[]dfn;delete[]low;}计算dfn与low的算法voidGraph::DfnLow(constintu,constintv)//私有函数:从顶点u开始深度优先搜索计算和low。在产生的生成树vu的双dfn[u]=low[u]=intw=GetFirstNeighborwhile(w!=-1){ if(dfn[w]==0){//未 过,w是u的孩子DfnLowwu //从w递归深度优先搜low[u]=min2(low[u],low[w] w的low[w]先求出,再求}elseifwv 过且w不是v,是回low[u]=min2(low[u],dfn[w]//根据回边另一顶点w调整w=GetNextNeighbor(u,//找顶点u在w后面的下一个邻接顶}}DnLow,,DnLoww,)的返回,计算loww。如果loww]dfu,则开始计算新的重连通分量。在算法中利用一个栈,Biconnected就能输出一个重连通分量的所有的边。n1时输出重连通分量voidGraph::Biconnected()intnum=1; dfnnewint[NumVertices];//dfn是深度优先lownewint[NumVertices]//low是最小祖先for(inti=0;i<NumVertices;i++{dfn[i]=low[i]=0;DfnLow0-1 //从顶0开delete[]dfn;delete[]}n1时输出重连通分量voidGraph::Biconnected(constintu,constintv)//私有函数:计算dfn与low,根据其重连通分量//出Graph的边。在产生的生成树中,v是u的双//结点,S是一个初始为空的栈, 为图的intxyw;dfn[u]=low[u]=num++;w=GetFirstNeighbor(u);while(w!=1){if(v!=w&&dfn[w]<dfn[u])S.Push((u,w)//w不是u的双亲且w先于u ,(u,w)进栈if(dfn[w]==0){ //未 过,w是u的孩子Biconnected(w,u); low[u]=min2(low[u],low[w]);//根据先求出的low[w],调整low[u]if(low[w]>=dfn[u]){//无回边,原来的重连通分量结束cout新重连通分量end1;do{(x,y)=S.Pop();cout<<x<<","<<y<<whilexy(uw不是同一条 //输出该重连通分量的各}elseifwv //有回边,计low[u]=min2(low[u],dfn[w]//根据回边另一顶点w调整w=GetNextNeighbor(u,//找顶点u的邻接顶点w的下一个邻接顶}}算法Biconnected的时间代价是O(n+e)。其中n是该连通图的顶点数,e是该连通图的边数。因为正好有一个顶点的图连一条边也没(minimumcostspanningtree按照生成树的定义,n个顶点的连通网络的生成树有n个顶点、n-1条边。构造最小生成树的准必须使用且仅使用n-1条边来联结网络中的n个顶点不能使用产生回路的边(Kruskal)算法的基本思想设有一个有n个顶点的连通网络N={V,E},最初先构造一个只有n个顶点,没有边的非连通图T={V,}, 分量。当在E中选到一条具有最小权值的边时,将此边加入到T中;否则将此边舍去,重新选 首先,利用最小堆来存放E中的所有的边堆中边的两个顶点位 边的权tail、haed通分量即并查集的同一个子集合)上,是则舍去点放在同步合并,直到形成通分量为止。应 算法构造最小生成树的过constintMAXINT机器可问题中不可能出现的大classclassMSTEdgeNode{ friendclassMinSpanTree;inttail //生成树各边的两顶int //生成树各边的代classMinSpanTree{ MinSpanTree(intsz=MaxEdges-1)MaxSize(sz),n{edgevalue=newMSTEdgeNode[MaxSize];}intInsert(MSTEdgeNode&item);//将item加到最小生成树MSTEdgeNode //边值intMaxSize //最大边数,当前边利 算法建立最小生成voidGraph<string,Kruskal(MinSpanTree&T)MSTEdgeNode //边结点辅助单MinHeap<MstEdgeNode>intNumVertices=VerticesList.last; UFSetsF(NumVertices); //并查集F并初始化for(intu=0;u<NumVertices;u++)//邻接矩阵for(intv=i+1;v<NumVertices;v++ifEdge[u][vMAXINT{//检出所有e.tail=u;e.head=e.costw;H.Insert }intcount=1; while(count<NumVertices){ eH.RemoveMin //从堆中退出一条uF.Finde.tail //检测两端点的v=F.Find(e.headifuv //根不同,不在同一连通分量F.Unionuv //合T.Inserte //该边存入最小生成树T}}}间代价为O(n2)。且做了e次堆 操作,每次调用了一个堆调整算法SiftUp()算法,因此 需要的时间代价为O(elog2e)在构造最小生成树时,最多调用了e次出堆操作RemoveMin(),2e次并查集的Find()操作,n-1次Union操作,计算时间分别为O(elog2e),总的计算时间O(elog2eelog2n姆(Prim)姆算法的基本思想从连通网络N={V,E}中的某一顶点u0出发,选择与它关联的具有最小权值的边(u0v),以后每一步从一个顶点在U中,而另一点不在U中的各条边中选择权值最小的边(uv),采用邻接矩阵作为图的 姆算法构造最小生成树的过lowcost[] nearvex[] 例若选择从顶点0出发,即u00,则两个辅助数在lowcost[]中选择nearvex[i]-1&&lowcost[i]最小的边i用v标记它。则选中的权值最小的边为(nearvex[vv),相应的权值lowcost[v]。nearvex[v-1,表示它已加入生成树顶点集合。将边(nearvex[v],v,lowcost[v])lowcost[imin{lowcost[iEdge[v][i,即用生成树顶点集合外各顶点i到刚加入该集合的新顶点v的距离Edge[v][i]与原来它lowcost[i]做比较,取距离近的作为这些集合外顶点到生成树顶点集合内顶点的最短距离如果生成树顶点集合外顶点i到刚加入该集合的新顶点v的距离比原来它到生成树顶点nearvex[i]:nearvex[i]=v。表示生成树外顶v=
v=最后生成树中边集合里存入得各条边为(0,5,10),(5,4,25),(4,3,(3,2,12),(2,1,16),(1,6,利 姆算法建立最小生成voidGraph<string,Prim(MinSpanTree&T)intNumVertices //图中顶lowcost=newnearvex=newfor(inti=1;i<NumVertices;i++){lowcost[i]=Edge[0][i];//顶点0到各边的代价nearvex[i]=0; }nearvex[0]=-1; intcount=0; MSTEdgeNodee; for(i=1;i<NumVertices;i++){//循环n-1次,加入n-1条intmin=MAXINT;intv=for(intj=0;j<NumVertices;j++if(nearvex[j]!=-1&&lowcost[j]<min{v=j;min=lowcost[j];//求生成树外顶点到生成树内顶点具有最//权值的边,v是当前具最小权值的边的位ifv //v==0表示再也找不到要求的 //向生成树边值数组内存e.tail=nearvex[v]; e.head=v;e.cost=lowcost[v];T.Insert(e); nearvex[v]=-1; for(j=1;j<NumVertices;j++)ifnearvex[j-1 //j不在生成树Edge[v][jlowcost[j //需要修lowcost[j]=nearvex[j]=}分析分析以上算法,设连通网络有nO(n2),它适用于边稠密的网络。}}(Shortest称为源点)到达另一顶点的路径可能不止一条,如何找到一条路径使得沿此路径上各边上的权值总和达到最小。问题解Dijkstra算边上权值为任意值的单源最短路径问Floyd算为求得这些最短路径,tra提出按路径长度的递增次序,逐步产生最短路径的算法。首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从顶点v到其它各顶点的最短路径全部求出为止。举例说明源终最短路径路径长(v0, (v0,v1,v2)(v0,v3,v2)(v0,v3)—(v0, (v0,v3,v4)(v0,v3,v2,表示当前找到的从源点v0到终点vi的最短路径的若从源点v0到顶点vi没有边,则dist[i]为+。一般情况下,假设S是已求得的最短路径的终从v0出发,中间只经过S中的顶点便可到达的那些顶点vx(vxV-S)的路径中的一条。每次求得一条最短路径之后,其终点vk加入集合S,然后对所有的viV-S,修改其dist[i]值。Sv0dist[j]← j=1,2,…,n-n为图中顶点个数dist[k]←min{dist[i]},iV-SS←SU{kdist[i]←min{dist[i],dist[k]+Edge[k][i]iVS判断:若S=V,则算法结束,否则 constintNumVertices //图中最大顶点个classGraph{ intdist[NumVertices]; intpath[NumVertices]; voidShortestPath(constint,constint);intchoose(constint);voidGraph::ShortestPath(constintn,constintv//Graph是一个具有n个顶点的带权有向图,各边上//的权值由Edge[i][j]给出。本算法建立起一个//组dist[j0jn,是当前求到的从顶点v到顶//j的最短路径长度同时用数组path[j0jn//放求到的最短路径for(inti=0;i<n;i++)dist[i //dist数组初始S[i]=if(i!=v&&dist[i]<MAXINT)path[i]=elsepath[i- //path数组初始}S[v dist[v //顶点v加入顶for(i=0;i<n-1;i++){intmin=MAXINT;intu=for(intj=0;j<n;j++if(!S[j]&&dist[j]<min{u= min=dist[j];S[u]=1; //将顶点u加入集合Sfor(intw=0;w<n;w++) if(!S[w]&&Edge[u][w]<MAXINTdist[u]+Edge[u][w]<dist[w])dist[w]=dist[u]+Edge[u][w];path[w]=u;}}}算算法得时间复杂度如何从如何从点v的最短路径?举顶点4为例path[4]=2→path[2]=3→path[3]=0,反过来排列,得到路径0,3,2,4,这就是源点0到终点4的最短路径源点0到00011031000带权有向图的某几条边或所有边的长度可能为负值。利用a算法,不一定能得到正确的结果。若设源点v=0,使用选顶点0顶点1顶点2顶010-070050210-070150110-170150Bellan和Ford提出了从源点逐次绕过其它顶有由带负权值的边组成的回路。序列dist1[u],dist2[u],…,distn-1[u]。其中,dist1[u]是从源点v到终点u的只经过一条边的最短路径的长度,dist1[u]=Edge[v][u];dist2[u]径的长度,dist3[u]是从源点v出发最多经过不构径的长度,…,distn-1[u]是从源点v出发最多经可以用递推方式计算distk[u]。dist1[u]=distk[u]=min{distk-1[u],min{distk-1Edge[j][u]}distk-1[jj01n-1此即从源点v最多经过不构成带负长度边回路的k-1条边到达终点j的最短路径的长度。j到达顶uEdge[j][u]min{distk-1[j]+Edge[j][u]},可得从源点v绕过各个顶点,最k条边到达终用它与distk-1[u]比较,取小者作为distk[u]k1234voidGraph::BellmanFord(constintn,constintv{//在带权有向图中有的边具有负的权值。从顶点//找到所有其它顶点的最短路径for(inti=0;i<n;i++)dist[i]=if(i!=v&&dist[i]<MAXINTpath[i]=v;elsepath[i]=-1;}for(intk=2;k<n;k++for(intu=0;u<n;u++if(u!=vfor(i=0;i<n;i++if(Edge[i][u]>0Edge[i][u]<MAXINTdist[u]>dist[i]+Edge[i][u])dist[u]=dist[i]+Edge[i][u];path[u]=i;}}问题的提法:0的带权有向图,对每一对顶点ivj,要求求出ij定义一个n阶方阵序列A(-1),A(0),…,A(n-其中A(-1[i][jA(k)[i][j]=min{A(k-A(k-1)[i][k]+A(k-1)[k][j]},k=0,1,…,n-A(0)[i][j]是从顶点vi到vj,中间顶点是v0的最短路径的长度,A(k)[i][j]是从顶点vi到vj,中间顶点的序号不大于k的最短路径的长度A(n-1)[i][j]是从顶点vi到vj的最短路径长度。所有各对顶点之间的最短路voidGraph::AllLengths(constintn)//Edge[n][n]是一个具有n个顶点的图的邻接矩阵//a[i][j]ij之间的最短路径长度。//是相应路径上顶j的前一顶点的顶点号,在//最短路径时图的类定义中要修改path//path[NumVertices][NumVertices]for(inti=0;i<n;i++) //矩阵a与path初始化for(intj=0;j<n;j++){a[i][j]=if(i<>j&&a[i][j]<MAXINTpath[i][j ij有路elsepath[i][j ij无路}for(intk=0;k<n;k++) for(i=0;i<n;i++)for(j=0;j<n;j++if(a[i][k]+a[k][j]<a[i][j])a[i][j]=a[i][k]+a[k][j];path[i][j]=path[k][j]; //缩短路径长度k} 201 以Path(3)为例,对最短路径的读法加以说明。从A(3)知,顶点1到0的最短路径长度为a[1][011,其最短路径看path[1][0]2,path[1][2]3,path[1][3]=1,表示顶点0顶点2顶点3顶点1;从顶点1到顶点0最短路径为<1,3>,<3,2>,<2,0>。包含带负权值的边组成的回路在顶点vi与vj之间存在无向边(vi,vj),就可以看成vi,vj>和<vj,vi>。(Activity(AOV网络“工程分为若干个叫做“些活动,这个工程就可以完成了。以并行地学习。 高等数程序设计基离散数数据结高级语言程序设编译方操作系普通物计算机原学生课程学习可以用有向图用顶点表示活动,<i,j>表示活动。ij进行。这种有向图叫做顶点V(civitynerices)。Vij进行,则存在有向边<i,j>,V网络中不能出现有向回路,即有向环。在AV网络中如果出现了有向环,则意味着某项活动应以自己作为先决条件。V存在有向环。V网络构造它的拓扑有序序列。即将各个顶点代表各个活动)排列成一个线性有序的序列,使得AOV运算就叫做拓扑排序。的拓扑有序序列为C1,C2,C3,C4,C5,C6,C8,C9, C1,C8,C9,C2,C5,C3,C4,C7,输入AOV网络。令n为顶点个数从图中删去该顶点同时删去所有它发出的有重复以 步,直最后得到的拓扑有序序列为最后得到的拓扑有序序列为C4,C0,C3,C2,C1,C5。它满足图中给出的所有前驱和后继关系AOVAOV在邻接表中增设了一个数组count[],记录各个在输入数据前,邻接表的顶点表NodeTable和入度数组count[]全部初始化。在输入数据时,每输入一条边<j,k>,就需要建立一个边结点并将它链入相应边链表中,统计入度信Edge<int>*p=new//建立边结点dest域赋kp→link=NodeTable[j].adj;NodeTable[j].adj=p;//链入顶j的边链 //k入度使用这种栈的拓扑排序算法可以描述如下:建立入度为零的顶点栈当入度为零的顶点栈不空时重复执行从顶点栈中退出一个顶点,并输出之;如果边的终顶点入度减至0则该顶点进入数,则 可以不另外分配空间,直接利用入度为零的顶点的count数组元素。我们设立了一个栈度为零的顶点位置。栈初始化时置top-1,表将顶点I进栈时,执行以下指针的修改count[i]=top;top=//top指向新栈顶i,原栈顶元素放在count[i]退栈操作可以写成j=top;top=//位于栈顶的顶点的位置记于j,top退到次栈//图的邻接表//图的邻接表的类定friendclass<int>Vertex;friendclass<int,int>Edge;int*count;intn;Graph(constintvertices=0):n(vertices)NodeTable=newvertex<int,count=new}拓扑排序的算voidGraph::TopologicalSort()inttop=-1; for(inti=0;i<n;i++) if(count[i]==0){count[i]=top;top=i;}for
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 医疗器械质量管理体系的国际化标准解读
- 医疗信息共享的伦理与法律电子病历与隐私保护的平衡
- 减少医疗浪费提高资源利用效率
- 医疗AI技术的发展及其对健康产业的贡献分析
- HIPAA政策解析及其实施要点详解
- 医疗大数据与决策科学融合的未来
- 医疗器械法规对康复机器人研发的规范与引导
- 弥漫性食管壁内憩室的临床护理
- 代理广告租赁合同范例
- 全生命周期健康管理平台的未来趋势分析
- GB/T 12759-1991双圆弧圆柱齿轮基本齿廓
- 《法拉第电磁感应定律》设计 省赛一等奖
- 《小区植物景观调查报告【论文】》
- 监理工程师通知回复单11
- 立式加工中心操作指导书
- 禁毒学校青少年预防远离毒品教育模板课件
- 汽车4S店售后回访流程
- SCAN-企业危机计划及风险评估管理程序
- 举升机每日维护检查表
- DB32-T 3897-2020地方政府规章立法规范-(高清现行)
- 质量管理手册-非发酵性豆制品
评论
0/150
提交评论