找出无向图中所有的环的算法

本文给出了一个找到无向图中所有的环的递归算法,该算法是基于DFS(深度优先搜索)的,大概的思路是:在深度优先搜索无向图的过程中,当遇到起始点的时候,会认定为出现环(在本文中只是找出了无向图中所有的长度大于等于3的环(长度为1和2的环没有意思),所以在深搜的过程中,当遇到的是起始点的时候,还需要进行判断是否是环),当确定是出现了环之后,根据是否在遇到环之前的那个点还有其他的路径,来决定是进一步的进行深度优先搜索还是进行回退,在进行深度优先搜索的过程中,将访问过的节点标记,若当前的节点无路可走(不能进行深度优先搜索了),在回退的过程中,将标记取消。算法的过程就下图做简单的介绍:


假设以1为起点进行深度优先搜索,经过访问2,3,4,5,6会得到一个环,因为节点6还有下一条路径可走,此时程序会进入7,8,9,10这些点进行深度优先搜索,但是都再没有回到节点1,于是程序会一层一层的在从7,8,9,10(不一定是这样的顺序)这些点退出来。退至节点6,5,4直到3节点(将6,5,4的标记全部取消)找到了下一条路径5,在走到6,此时又发现了另一条环1->2->3->5->6->1.以此类推。

主要代码如下:

<span style="font-family:Courier New;font-size:12px;">void DFS(int startVertax)
{
	setVisitedFlag(startVertax, 1);
	int nextVertax;
	push_stack(&loop_stack, startVertax);
	nextVertax = firstAdjacentVertax(startVertax);
	innerStep++;
	for( ; ; )
	{
		if( nextVertax != -1 )
		{
			if( visitedFlag[nextVertax] == 1 && nextVertax == heap && innerStep == 2 ) //从1到2,又从2到1,这不算是一个环
			{
				nextVertax = nextAdjacentVertax(startVertax, nextVertax);
				continue;
			}
			else if( visitedFlag[nextVertax] == 1 && nextVertax == heap && innerStep != 2 ) //找到了一个环
			{
				printf("loop length: %d\t", innerStep);
				print_stack(loop_stack);
				nextVertax = nextAdjacentVertax(startVertax, nextVertax);
				continue;
			}
			else if( visitedFlag[nextVertax] == 0 )<span style="white-space:pre">	</span>//进行递归
			{
				DFS(nextVertax);
			}
			if( isRecall == 1 ) //进行回退
			{
				innerStep--;
				temp = nextVertax;
				nextVertax = nextAdjacentVertax(startVertax, nextVertax);
				pop_stack(&loop_stack, &pop_value);
				setVisitedFlag(temp, 0);
				isRecall = 0;
				continue;
			}
			nextVertax = nextAdjacentVertax(startVertax, nextVertax);
		}
		else if( nextVertax == -1 )
		{
			isRecall = 1;
			break;
		}
	}
}
void DFSTraverse()
{
	initialVisitedFlagArray();
	initializeSequenceStack(&loop_stack);
	int i;
	for( heap = 1; heap <= vertax_size; heap++ )
	{
		for( i = 1; i <= vertax_size; i++ )
		{
			visitedFlag[i] = 0;
		}
		/*
		printf("print the visitedFlag array: ");
		for( i = 1; i <= vertax_size; i++ )
		{
			printf("%d ", visitedFlag[i]);
		}
		printf("\n");
		*/
		if( visitedFlag[heap] == 0 )
		{
			printf("\n-------------------the loop start and end with %d----------------\n", heap);
			clear_stack(&loop_stack);
			innerStep = 0;
			isRecall = 0;
			DFS(heap);
		}
	}
}</span>

对于上图的程序的运行结果为:(需要注意的是:对于无向图中的每一条环会出现两次,因为是有方向的:顺时针和逆时针)。






完整代码

<span style="font-family:Courier New;">#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>

int eage_size;
int vertax_size;
char filename_eage[200];
char filename_vertax[200];

int** eage_set;
char** vertax_set;
int** adjacentMatrix;
int* visitedFlag;

typedef struct SequenceStack
{
	int* base;
	int* top;
	int stackSize;
}SequenceStack;

void readEageDataFromFile();
void readVertaxDataFromFile();
void createAdjacentMatrix();
void DFS(int); 
void DFSTraverse();
void initialVisitedFlagArray();
void printVisitedVertax(int); 
void setVisitedFlag(int,int); 
int firstAdjacentVertax(int); 
int nextAdjacentVertax(int,int);

void initializeSequenceStack(SequenceStack*);
void pop_stack(SequenceStack*, int*);
void push_stack(SequenceStack*, int);
void print_stack(SequenceStack);
int empty_stack(SequenceStack);
void clear_stack(SequenceStack*);
void test_stack();

int main(int argc, char* argv[])
{
	if( argc != 5 )
	{
		printf("\tThis algorithm require 3 parameters"
				"\n\t\t1:the size of eage"
				"\n\t\t2:the filename contain eage-data"
				"\n\t\t3:the size of vertax"
				"\n\t\t4:the filename contain vertax-data");
		exit(0);
	}
	eage_size = atoi(argv[1]);
	strcat(filename_eage, argv[2]);
	vertax_size = atoi(argv[3]);
	strcat(filename_vertax, argv[4]);
	printf("eage_size : %d, vertax_size : %d, filename-eage : %s, filename-vertax : %s\n", eage_size, vertax_size, filename_eage, filename_vertax);
	readEageDataFromFile();
	readVertaxDataFromFile();
	createAdjacentMatrix();
	DFSTraverse();
	//test_stack(); 
	return 0; 
}

void readEageDataFromFile()
{
	FILE* f_read;
	if( NULL == (f_read = fopen(filename_eage, "r")))
	{
		printf("open file(%s) error!\n", filename_eage);
		exit(0);
	}
	//create dynamic array for storing original data form file @filename
	eage_set = (int**)malloc(sizeof(int*) * (eage_size + 1));
	if( !eage_set )
	{
		printf("malloc error: eage_set**\n");
		exit(0);
	}
	int i;
	for( i = 1; i <= eage_size; i++ )
	{
		eage_set[i] = (int*)malloc(sizeof(int) * (2 + 1));
		if( !eage_set[i] )
		{
			printf("eage_set[%d] malloc error", i);
			exit(0);
		}
	}
	//read original data from file
	for( i = 1; i <= eage_size; i++ )
	{
		if( 2 != fscanf(f_read, "%d %d", &eage_set[i][1], &eage_set[i][2]))
		{
			printf("fscanf error: %d\n", i);
			exit(0);
		}
	}
	//test
	printf("\n show the origin data from file\n");
	for( i = 1; i <= eage_size; i++ )
	{
		printf("%d\t%d\n", eage_set[i][1], eage_set[i][2]);
	}
	printf("\n");
	//test END
}

void readVertaxDataFromFile()
{
	//create the dynamic array for saving vertax-set information
	vertax_set = (char**)malloc(sizeof(char*) * (vertax_size + 1));
	if( !vertax_set )
	{
		printf("vertax_set malloc error");
		exit(0);
	}
	int i;
	for( i = 1; i <= vertax_size; i++ )
	{
		vertax_set[i] = (char*)malloc(sizeof(char) * (20 + 1));
		if( !vertax_set[i] )
		{
			printf("vertax_set[%d] malloc error");
			exit(0);
		}
	}

	//open file
	FILE* f_read;
	if( NULL == (f_read = fopen(filename_vertax, "r")))
	{
		printf("open file(%s) error", filename_vertax);
		exit(0);
	}

	//read vertax-set information
	for( i = 1; i <= vertax_size; i++ )
	{
		if( 1 != fscanf(f_read, "%s ", vertax_set[i]) )
		{
			printf("fscanf vertax_set[%d] error", i);
			exit(0);
		}
	}

	//test
	for( i = 1; i <= vertax_size; i++ )
	{
		printf("%s\n", vertax_set[i]);
	}
	printf("\n");
	//test END
}

void createAdjacentMatrix()
{
	//create the dynamic array for saving adjcaent matrix
	adjacentMatrix = (int**)malloc(sizeof(int*) * (vertax_size + 1));
	if( !adjacentMatrix )
	{
		printf("adjacentMatrix** malloc error");
		exit(0);
	}
	int i;
	for( i = 1; i <= vertax_size; i++ )
	{
		adjacentMatrix[i] = (int*)malloc(sizeof(int) * (vertax_size + 1));
		if( !adjacentMatrix[i] )
		{
			printf("adjacentMatrix[%d] malloc error");
			exit(0);
		}
	}
	//initial the value of adjacentMatrix
	int j;
	for( i = 1; i <= vertax_size; i++ )
	{
		for( j = 1; j <= vertax_size; j++ )
		{
			adjacentMatrix[i][j] = 0;
		}
	}

	//set the value for adjacentMatrix 
	for( i = 1; i <= eage_size; i++ )
	{
		adjacentMatrix[eage_set[i][1]][eage_set[i][2]] = 1;
		adjacentMatrix[eage_set[i][2]][eage_set[i][1]] = 1;
	}

	//test
	printf("\n show the information about adjacent matrix: \n");
	for( i = 1; i <= vertax_size; i++ )
	{
		for( j = 1; j <= vertax_size; j++ )
		{
			printf("%d ", adjacentMatrix[i][j]);
		}
		printf("\n");
	}
	//test END
}

int loop_count;
int heap;
int innerStep = 0;
int temp;
int isRecall;
SequenceStack loop_stack;
int pop_value;
void DFS(int startVertax)
{
	setVisitedFlag(startVertax, 1);
	int nextVertax;
	push_stack(&loop_stack, startVertax);
	nextVertax = firstAdjacentVertax(startVertax);
	innerStep++;
	for( ; ; )
	{
		if( nextVertax != -1 )
		{
			if( visitedFlag[nextVertax] == 1 && nextVertax == heap && innerStep == 2 )
			{
				nextVertax = nextAdjacentVertax(startVertax, nextVertax);
				continue;
			}
			else if( visitedFlag[nextVertax] == 1 && nextVertax == heap && innerStep != 2 )
			{
				print_stack(loop_stack);
				nextVertax = nextAdjacentVertax(startVertax, nextVertax);
				continue;
			}
			else if( visitedFlag[nextVertax] == 0 )
			{
				DFS(nextVertax);
			}
			if( isRecall == 1 )
			{
				innerStep--;
				temp = nextVertax;
				nextVertax = nextAdjacentVertax(startVertax, nextVertax);
				pop_stack(&loop_stack, &pop_value);
				setVisitedFlag(temp, 0);
				isRecall = 0;
				continue;
			}
			nextVertax = nextAdjacentVertax(startVertax, nextVertax);
		}
		else if( nextVertax == -1 )
		{
			isRecall = 1;
			break;
		}
	}
}
void DFSTraverse()
{
	initialVisitedFlagArray();
	initializeSequenceStack(&loop_stack);
	int i;
	for( heap = 1; heap <= vertax_size; heap++ )
	{
		for( i = 1; i <= vertax_size; i++ )
		{
			visitedFlag[i] = 0;
		}
		/*
		printf("print the visitedFlag array: ");
		for( i = 1; i <= vertax_size; i++ )
		{
			printf("%d ", visitedFlag[i]);
		}
		printf("\n");
		*/
		if( visitedFlag[heap] == 0 )
		{
			printf("\n-------------------the loop start and end with %d----------------\n", heap);
			clear_stack(&loop_stack);
			innerStep = 0;
			//printf("isRecall : %d, findLoop : %d, hasOthers : %d\n", isRecall, findLoop, hasOthers);
			isRecall = 0;
			DFS(heap);
		}
	}
}
void initialVisitedFlagArray()
{
	visitedFlag = (int*)malloc(sizeof(int) * (vertax_size + 1));
	if( !visitedFlag )
	{
		printf("visitedFlag* malloc error");
		exit(0);
	}
	int i;
	for( i = 1; i <= vertax_size; i++ )
		visitedFlag[i] = 0;
}
void printVisitedVertax(int vertaxID)
{
	printf("visited: %d \n", vertaxID);
}
void setVisitedFlag(int vertaxID, int value)
{
	visitedFlag[vertaxID] = value;
}
int firstAdjacentVertax(int vertaxID)
{
	int i;
	for( i = 1; i <= vertax_size; i++ )
	{
		if( adjacentMatrix[vertaxID][i] == 1 )
			return i;
	}
	return -1;
}
int nextAdjacentVertax(int vertaxID, int nextVertaxID)
{
	int i;
	for( i = nextVertaxID + 1; i <= vertax_size; i++ )
	{
		if( adjacentMatrix[vertaxID][i] == 1 )
			return i;
	}
	return -1;
}
void initializeSequenceStack(SequenceStack* stack)
{
	stack->base = (int*)malloc(sizeof(int) * (vertax_size + 1));
	if( !stack->base )
	{
		printf("Sequence stack malloc error!\n");
		exit(0);
	}
	stack->top = stack->base;
	stack->stackSize = vertax_size;
}
void pop_stack(SequenceStack* stack, int* value)
{
	if( empty_stack(*stack) == 1 )
	{
		printf("stack is empty , can not to pop!\n");
		exit(0);
	}
	*value = *(--(stack->top));
}
void push_stack(SequenceStack* stack, int value)
{
	*(stack->top) = value;
	(stack->top)++;
}
int empty_stack(SequenceStack stack)
{
	return stack.top == stack.base ? 1 : 0;
}
void print_stack(SequenceStack stack)
{
	int temp = *(stack.base);
	while( stack.top != stack.base )
	{
		printf("%d->", *((stack.base)++));
	}
	printf("%d\n", temp);
}
void clear_stack(SequenceStack* stack)
{
	stack->top = stack->base;
}</span>




  • 23
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
### 回答1: 下面是一个简单的Julia代码,用于在无向图找出所有: ```julia using LightGraphs function find_cycles(g::AbstractGraph) cycles = [] for node in vertices(g) for neighbor in neighbors(g, node) path = [node, neighbor] current = neighbor while current != node next_node = nextneighbor(g, current, path[end]) if next_node == nothing break end push!(path, next_node) current = next_node end if current == node push!(cycles, path) end end end return cycles end ``` 这段代码使用了LightGraphs包,它是一个用于处理图形数据的高效Julia库。上面的函数接受一个无向图(g)作为输入,并返回一个的列表。首先,它对图中的每个节点进行遍历,然后对该节点的每个邻居进行遍历,如果当前节点和开始节点相同,则将路径添加到的列表。 ### 回答2: 在Julia,我们可以用图论库`LightGraphs`来找出无向图的所有。下面是使用`LightGraphs`库的代码示例: ```julia using LightGraphs # 创建一个无向图 graph = Graph(5) # 替换5为你想要的节点数量 # 添加边到图中 add_edge!(graph, 1, 2) add_edge!(graph, 1, 3) add_edge!(graph, 2, 3) add_edge!(graph, 3, 4) add_edge!(graph, 4, 5) add_edge!(graph, 5, 1) # 找出无向图的所有 cycles = find_cycle(graph) # 输出所有 for cycle in cycles println(cycle) end ``` 在这个示例,我们创建了一个有5个节点的无向图,然后添加了一些边。接着,我们使用`find_cycle`函数找出了所有的,然后遍历并打印出每个的节点。 注意:这只是一个示例,你可以根据需要修改图的大小、边的连接方式等。 ### 回答3: 在Julia语言,可以使用遍历算法找出无向图的所有。以下是一个示例代码: ```julia # 定义无向图 graph = Dict( 1 => [2, 3, 4], 2 => [1, 4], 3 => [1, 4], 4 => [1, 2, 3, 5], 5 => [4] ) # 定义函数遍历无向图,查找所有 function find_cycles(graph, start, node, visited, path, cycles) visited[node] = true push!(path, node) for neighbor in graph[node] if neighbor == start push!(cycles, copy(path)) elseif !visited[neighbor] find_cycles(graph, start, neighbor, visited, path, cycles) end end pop!(path) visited[node] = false end # 主函数,遍历无向图的每个节点 function find_all_cycles(graph) cycles = [] for node in keys(graph) visited = falses(length(graph)) path = [] find_cycles(graph, node, node, visited, path, cycles) end return cycles end # 调用主函数并输出结果 cycles = find_all_cycles(graph) for cycle in cycles println(cycle) end ``` 以上代码首先定义了一个无向图,其`graph`是一个字典数据结构,表示节点之间的连接关系。然后,通过`find_cycles`函数使用深度优先搜索遍历无向图,查找所有,并将它们存储在`cycles`数组。最后,通过`find_all_cycles`函数遍历无向图的每个节点,调用`find_cycles`函数查找所有,并将结果输出。 请注意,以上代码是一个简单示例,可以根据具体的无向图数据结构进行修改。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值