基于深度优先算法的有向图环路检测
来源:互联网 发布:联通网络信号怎么样 编辑:程序博客网 时间:2024/05/01 14:12
1、digraph.h
#ifndef _DIGRAPH_H_H#define _DIGRAPH_H_H#define ENABLE_DIGRAPH_TEST 0#define CHECK_NULL_AND_RET(x) { if((x) == NULL) return -1; }typedef struct _ADJ_ENTRY{ int adjoinPoint; struct _ADJ_ENTRY* pNext;} ADJ_ENTRY;typedef struct{ struct _ADJ_ENTRY* entryHead;} ADJ_HEAD;typedef struct{ int V; //顶点数 int E; //边数 ADJ_HEAD* adjTable; //邻接表} DIGRAPH;int digraphCreate(DIGRAPH *pDigraph, int V);int reverseDigraphCreate(DIGRAPH* pSrcDigraph, DIGRAPH* pDstDigraph);int digraphDestroy(DIGRAPH *pDigraph);int V(DIGRAPH *pDigraph);int E(DIGRAPH *pDigraph);int addEdge(DIGRAPH *pDigraph, int x, int y);void showDigraph(DIGRAPH *pDigraph);#endif
2、digraph.c
#include <stdio.h>#include <stdlib.h>#include "digraph.h"//有向图的数据结构//当前图对象使用邻接表表示,大部分情况下,图中的所有顶点并非//都是关联的,这种叫作稀疏图,使用邻接表来做为稀疏图的数据结//构,可以节省很大的内存空间。如果以前了解过操作系统原理中内//存机制的一级页表、二级页表机制,就会很快明白,为什么使用邻//接表来表示稀疏图可以节省大部内存空间了。//创建图对象,其中V表示最大顶点个数int digraphCreate(DIGRAPH *pDigraph, int V){ if ( pDigraph == NULL ) { return -1; } pDigraph->V = V; pDigraph->E = 0; pDigraph->adjTable = (ADJ_HEAD *)malloc(sizeof(ADJ_HEAD) * V); CHECK_NULL_AND_RET(pDigraph->adjTable); return 0;}//创建反向图int reverseDigraphCreate(DIGRAPH* pSrcDigraph, DIGRAPH* pDstDigraph){ int i = 0; if ( pSrcDigraph == NULL || pDstDigraph == NULL ) { return -1; } if ( digraphCreate(pDstDigraph, V(pSrcDigraph)) < 0 ) { return -1; } for ( i = 0; i < V(pSrcDigraph); i++ ) { ADJ_ENTRY* pCurAdjEntry = (pSrcDigraph->adjTable + i)->entryHead; while ( pCurAdjEntry != NULL ) { addEdge(pDstDigraph, pCurAdjEntry->adjoinPoint, i); pCurAdjEntry = pCurAdjEntry->pNext; } } return 0;}//销毁图对象int digraphDestroy(DIGRAPH *pDigraph){ int i = 0; if ( pDigraph == NULL ) { return -1; } for ( i = 0; i < V(pDigraph); i++ ) { ADJ_ENTRY *pCurAdjEntry = (pDigraph->adjTable + i)->entryHead; while ( pCurAdjEntry != NULL ) { ADJ_ENTRY *pFreeAdjEntry = pCurAdjEntry; pCurAdjEntry = pCurAdjEntry->pNext; free(pFreeAdjEntry); } } free(pDigraph->adjTable); pDigraph->V = 0; pDigraph->E = 0; pDigraph->adjTable = NULL; return 0;}//获取图对象的顶点个数int V(DIGRAPH *pDigraph){ if ( pDigraph == NULL ) { return -1; } return pDigraph->V;}//获取图对象的边数int E(DIGRAPH *pDigraph){ if ( pDigraph == NULL ) { return -1; } return pDigraph->E;}//邻接表添加条目static int adjAdd(DIGRAPH *pDigraph, int x, int y){ ADJ_HEAD *pAdjHead = NULL; ADJ_ENTRY *pNewAdjEntry = NULL; if ( pDigraph == NULL ) { return -1; } if ( x >= pDigraph->V || x < 0 || y >= pDigraph->V || y < 0 ) { return -1; } pNewAdjEntry = (ADJ_ENTRY *)malloc(sizeof(ADJ_ENTRY)); CHECK_NULL_AND_RET(pNewAdjEntry); memset(pNewAdjEntry, 0, sizeof(ADJ_ENTRY)); pNewAdjEntry->adjoinPoint = y; pAdjHead = (pDigraph->adjTable + x); pNewAdjEntry->pNext = pAdjHead->entryHead; pAdjHead->entryHead = pNewAdjEntry; return 0;}//向图对象中增加路径int addEdge(DIGRAPH *pDigraph, int x, int y){ if ( adjAdd(pDigraph, x, y) < 0 ) { return -1; } pDigraph->E++; return 0;}//显示图对象的信息void showDigraph(DIGRAPH *pDigraph){ int i = 0; if ( pDigraph == NULL ) { return; } printf("point count: %d\r\n", V(pDigraph)); printf("edge count: %d\r\n", E(pDigraph)); printf("------------------\r\n"); for ( i = 0; i < V(pDigraph); i++ ) { ADJ_ENTRY* pCurEntry = (pDigraph->adjTable + i)->entryHead; while ( pCurEntry != NULL ) { printf("%d --> %d\r\n", i, pCurEntry->adjoinPoint); pCurEntry = pCurEntry->pNext; } } printf("------------------\r\n");}#if ENABLE_DIGRAPH_TESTint main(){ DIGRAPH digraphObj = {0}; DIGRAPH reverseDigraphObj = {0}; digraphCreate(&digraphObj, 10); addEdge(&digraphObj, 0, 1); addEdge(&digraphObj, 0, 2); addEdge(&digraphObj, 0, 3); addEdge(&digraphObj, 0, 4); showDigraph(&digraphObj); reverseDigraphCreate(&digraphObj, &reverseDigraphObj); showDigraph(&reverseDigraphObj); digraphDestroy(&digraphObj); digraphDestroy(&reverseDigraphObj); return 0;}#endif
3、digraphCycle.c
#include "stdio.h"#include "digraph.h"#define CHECK_NULL_RET(x) { if ( (x) == NULL ) return -1; }enum{ FALSE, TRUE} E_BOOL;int* gMarked = NULL;int* gOnStack = NULL;int gIsCycle = FALSE;//基于深度优先算法实现的有向图环路检测void dfs(DIGRAPH* pDigraph, int s){ ADJ_ENTRY* pCurAdjEntry = NULL; if ( s < 0 || s >= V(pDigraph) ) { printf("invalid s %d\r\n", s); return; } gMarked[s] = TRUE; gOnStack[s] = TRUE; pCurAdjEntry = (pDigraph->adjTable + s)->entryHead; while ( pCurAdjEntry != NULL ) { if ( !gMarked[pCurAdjEntry->adjoinPoint] ) { dfs(pDigraph, pCurAdjEntry->adjoinPoint); } else if ( gOnStack[pCurAdjEntry->adjoinPoint] ) { gIsCycle = TRUE; return; } pCurAdjEntry = pCurAdjEntry->pNext; } //注意这里gOnStack与gMarked的区别,gMarked是深度优先算法所使用的 //标记,记录当前该点是否走过,如果走过就选择其它点进行尝试。 //而gOnStack表示从源点到当前点的路径,如果在遇到每条路不通的情况下, //需要退回到上个点,这时候gOnStack中就要撤销标记,如下示例,当走到 //3的时候,此时gOnStack和gMarked一样,0~3的数组索引都标为TRUE, //但这时候已经没有路,需要退回到2,此时gOnStack[3]则为FALSE,这时候 //发现2也没有其它可走的路,则退回到1,此时gOnStack[2]则为FALSE, //当从1走到4的时候,gOnStack只有索引0、1、4为TRUE,而gMarked则 //索引0~4都为TRUE。 // //示例: //0 --> 1 --> 2 --> 3 // | // |---> 4 --> 5 gOnStack[s] = FALSE;}int main(){ int size = 0; DIGRAPH digraphObj = {0}; //创建有向图对象 digraphCreate(&digraphObj, 5); #if 0 addEdge(&digraphObj, 0, 1); addEdge(&digraphObj, 0, 2); addEdge(&digraphObj, 1, 3); addEdge(&digraphObj, 2, 3); addEdge(&digraphObj, 3, 4); #else addEdge(&digraphObj, 0, 1); addEdge(&digraphObj, 0, 2); addEdge(&digraphObj, 1, 3); addEdge(&digraphObj, 2, 3); addEdge(&digraphObj, 3, 0); #endif showDigraph(&digraphObj); //资源分配 size = sizeof(int) * V(&digraphObj); gMarked = (int *)malloc(size); CHECK_NULL_RET(gMarked); memset(gMarked, 0, size); gOnStack = (int *)malloc(size); CHECK_NULL_RET(gOnStack); memset(gOnStack, 0, size); //基于深度优先算法实现的有向图环路检测 dfs(&digraphObj, 0); printf("Cycle: %s\r\n", gIsCycle ? "TRUE" : "FALSE" ); //资源销毁 free(gMarked); free(gOnStack); digraphDestroy(&digraphObj); return 0;}
0 0
- 基于深度优先算法的有向图环路检测
- 有向图(4)--基于深度优先的拓扑排序
- 【算法导论】有向图的深度优先搜索遍历
- 【算法】图的深度优先遍历(有向)
- 有向图深度优先与广度优先算法的C++实现
- 图的深度优先遍历递归算法主针对邻接表有向图
- 有向图邻接表的深度优先遍历
- 有向加权图的深度优先遍历—C
- 输出有向图的环路(山债版)
- 有向图中打印所有的环路
- 无向图的邻接表深度优先算法
- 有向图(2)--深度优先搜索&&广度优先搜索
- 有向图的深度优先搜索和广度优先搜索
- 图------有向网的建立、深度优先遍历,广度优先遍历
- 记数据结构之有向图的深度优先遍历,广度优先遍历
- 图的广度优先遍历和深度优先遍历(基于链式前向星)
- 基于邻接矩阵的无向图构造,以及宽度优先、深度优先搜索(Java)
- 算法: 无向图的深度优先搜索(dfs)和广度优先搜索(bfs)
- 采集ajax加载生成的网页
- .Net 雜談
- Leetcode#74||Search a 2D Matrix
- 深度学习(deep learning)如果有春天,先得摆脱高能耗高资源依赖的局面
- Linux————TCP/IP协议
- 基于深度优先算法的有向图环路检测
- 消息MSG、 获取消息GetMessage、消息过滤、第一个鼠标、键盘消息等
- Android点击应用Icon发生了什么
- Android Api Demos登顶之路(三十六)Fragment-->Custom Animation
- Hibernate 下载、安装和使用
- HDU 5399(简单数学)
- ios开发数组排序(数组中包括字典)
- Windows线程池
- iOS 带cookie进行网络请求