图那里的算法总结

来源:互联网 发布:阿里云rds逻辑备份恢复 编辑:程序博客网 时间:2024/05/01 11:58
//这里整理的为图那里的算法//邻接矩阵和邻接表的图的表示很重要//这里就不说明MAXSIZE就为最大值的默认了typedef struct ArcCell{     VRType adj;                            //这里是点中的值     InfoType *info;                        //这里是有关点的信息比如这里可以放权值 }ArcCel,AdjMatrix[MAXSIZE][MAXSIZE];       //后面的是矩阵typedef struct MGraph{              VertexType vexs[MAXSIZE];               //这里是顶点表AdjMatrix arcs;                         //这里是邻接矩阵边表int vexnum;                             //顶点的数目int arcnum;                             //边的数目GraphKind kind;                         //图的种类}MGraph;//这里是邻接表的表示方法很重要typedef struct ArcNode{                     //边节点int adjvex;                             //指向弧所指向的顶点的位置    ArcNode* nextarc;                       //指向下一条弧的指针    InfoType *info;                         //该相关弧的信息}ArcNode;typedef struct VexNode{                     //顶点节点ElemType data;                          //顶点信息ArcNode* firstarc;                      //指向第一条依附该顶点的指针}VexNode,AdjList[MAXSIZE];typedef struct ALGraph{AdjList vertices;                       //顶点组成的数组int vexnum;                             //顶点数目int arcnum;                             //边数目GraphKind kind;}ALGraph;//拓扑排序的代码//拓扑排序的原理就是每次把入度为0的节点删除,然后再把与其相连的边也删去。//拓扑排序可以检验是否图中有环bool Topologicalsort(MGraph M){Stack s;                                //这里需要一个栈来保存入度为0的节点init(s);int count = 0;                          //这里记录入度为0的节点的个数for(int i = 1;i < M.vexnum)             //这里把刚开始入度为0的节点入栈{if(indegree[i] == 0)                //indegree[i]表示的是i节点的入度个数push(s,i)}int k;while(!IsEmpty(S))                      //判断是不是栈为空{pop(s,k);                           //出栈因为栈里面保存的都是度为0的节点++count;                            // 把度为0的节点的个数加一for(ArcNode* p = M.vertices[k]->firstarc;p;p=p->nextarc) //这里的代码的意思就是删去和刚才出栈的节点的邻接边的入度的数目{int i = p->adjvex;              //这里找到邻接边所对应的弧所指向的顶点的位置if(--indegree[i] == 0)          //删除邻接边的入度的数目 即就是把入度数目减去1{push(s,i)                   //若入度数目为0,则把其压栈说明他是拓扑排序的下一个节点}}}return count == M.vexnum?true:false;//如果所有的节点都最后度为0,那么说明可以拓扑排序,若不可以则不行;}//最小生成树  这里的图使用邻接矩阵表示的//时间复杂度 O(n^2)                         //这里的closedge保存的是顶点adj和它邻接顶点中邻接边权值最小的邻接点和权值typedef struct closedge{VerTexType adjvex;                      //这里为邻接顶点VRType lowcost;                         //这里为邻接顶点的权值}closedge[MAXSIZE];                         //因为有好多的顶点所有用一个数组来表示void MinSpanTreePrim(MGraph G,VertexType u)//prime需要一个图和一个顶点作为参数{int k =LocateVex(G,u)                   //定位顶点u在图G中的位置for(int i = 0;i<G.vexnum;++i)           //根据图的信息更新closedge G.adjlist[k][i].adj这个保存的是i和k之间的权值{if(k==i)closedge[i]={u,G.arcs[k][i]};}closedge[k].lowcost = 0;                //这里把closedge[k].lowcost更新为0,说明了把节点k已经加入了最小生成树之中了for(int j = 1;j<G.vexnum;++j)           //因为已经有一个节点加入到最小生成树中了,所以循环只需要1-G.vexnum之间{k=minmum(closedge);                 //找到closedge中的lowcost最小值顶点closedge[k].lowcost = 0;            //把最小的lowcost加入到最小生成树中for(int l = 0;l<G.vexnum;++l)       //更新K周围的邻接点的最小权值{if(G.arcs[k][l] < closedge[l].lowcost)//当l与k的权值小于closedge[l].lowcost那么就需要更新closedge[l].lowcost{closedge[l].adjvex = k;                  //更新需要两部分一部分是邻接点 一部分是权值    closedge[l].lowcost = G.arcs[k][l];  //closedge[l]={k,G.arcs[k][l]}} }}}//最短路径算法Dijkstra算法//这个算是比较复杂的代码,但是不难理解//使用的是邻接矩阵存储的图//时间复杂度是O(n^2)适用于稠密的图Kruskal适用稀疏图kruskal时间复杂度是O(elge)//dijkstra处理的是单源最短路径//void Dijkstra(MGraph G,int k,PathMatrix& path,shortMetrix& d)//G是图,k是第一个顶点 path是保存路径的 d是保存到源点的最短距离{int final[MAXSIZE];                     //这个数组是用来标记是不是已经加入了最短路径的节点的标记0表示没有加入,1表示加入了for(int m = 0;m<G.vexnum;++m)           //这里是先把k与m之间的弧的权值赋给d[m]{final[m] = 0;d[m] = G.arcs[k][m];}final[k] = 1;                           //因为第一个顶点是k,所以把k加入到最短路径节点之中for(int j = 1;j<G.vexnum;++j)           //因为第一个节点已经找到了所以只需要寻找1-G.vexnum个节点就可以了{min = 32132322343;                  //min用保存于当前最短路径d[n]中的最短的一条路径int v;                              //v用来保存最短路径的那个顶点for(int n = 0;n < G.vexnum;++n)     //用来找到当前的最短的一条路径顶点保存在v中,权值保存在min中。{if(!final[n]&&d[n] < min){v = n;min = d[n];}}final[v] = 1;                       //找到的当前的最短的一条路径加入到最短路径之中所以把final[v]置1表示找到这个顶点for(int l = 0;k<G.vexnum;++k)       //用当前的v结点更新,未加入最短路径的节点的到源点的权值,当然这里更新要最短的权值{if(!final[l]&&d[l] > min+G.arcs[v][l])//G.arcs[v][l]表示的是顶点v到顶点l之间的权值{d[l] = min+G.arcs[v][l];}}}}//floyd这个算法比较简单//时间复杂度O(n^3)void floyd(MGraph G){for(int i =0;i<G.vexnum;++i)for(int j = 0;j<G.vexnum;++j)for(int k = 0;k<G.vexnum;++k)     //若v-k的路径大于v-j-k的路径把v-k的路径更新为v-j-k{if(G.arcs[i][k] > G.arcs[i][j]+G.arcs[j][k])G.arcs[i][k] = G.arcs[i][j]+G.arcs[j][k];}}//深度优先遍历和广度优先遍历int visited[MAXSIZE];//用来标记是否访问过void BFSTraverse(ALGraph G){for(int i = 0;i<G.vexnum;++i)             //这里是每个节点都进行广度优先遍历{if(!visited[i]){BFS(G,i)}}}void BFS(ALGraph,int k){Queue Q;                                  //初始化一个队列init(Q);EnQueue(Q,k);                             //第一个节点进入队列visited[k] = 1;                           //标记第一个节点表示访问while(!IsEmpty(Q)){DeQueue(Q,k);for(VexNode* p=G.vertices[k]->firstarc;p&&;p=p->nextarc)//找k节点邻接节点入队{int k = p->adjvex;if(!visited[k])                   //找到未访问的标记并且访问之后再入队列{visit(k);visited[k] = 1;    EnQueue(Q,k);}}}}//深度度优先遍历int visited[MAXSIZE];void DFSTraver(MGraph G,int v){for(int i = 0;i<G.vexnum;++i)              //每个节点都进行深度优先遍历{if(!visited[i]){DFS(G,i)}}}void DFS(MGraph G,int v){visited[v] = 1;visit(v);for(VexNode* p = G.adjlist[v]->firstarc;p;p=p->nextarc)//邻接边进行深度优先遍历{int i = p->adjvex;if(!visited[i]){DFS(G,i)}}}

0 0