无向图:查找最小环集合(最短路径回溯算法)

         在无向图中查找最小环,就像需要查找一个蜂窝中所有孔洞,如果只查找数目,可以利用欧拉公式,若查找到所有环,需要更进一步的搜索。

         方法:寻找到所有顶点的最短路径,对每一个顶点,取出环,循环删除顶点,输出所有最小环。

         注意:拓扑图具有位置可变性,不影响图结构的拓扑变化。所以此方法,只能找到拓扑最小环,若想找到距离最小环,需要对边进行加权。

         


        原文:找出无向图中所有环的算法。代码也转自于作者。

       

图片实例:

      

code:

       

bool findAllLoop(int argc, char* argv[]);

//查找所有路径的算法是成功的;但最短路径不能保证找到最小环
int main(int argc, char* argv[])
{
	findAllLoop(argc, argv);
	return 0;
}

bool findAllLoop(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\n");
		//exit(0);
	}
	//eage_size = atoi(argv[1]);
	//strcat(filename_eage, argv[2]);
	//vertax_size = atoi(argv[3]);
	//strcat(filename_vertax, argv[4]);
	wishchin::eage_size = 22;//边的个数
	//strcat(filename_eage, argv[2]);

	std::string filename_eages("D:/DataSet/RsData/loopFind/houseAdj.txt");

	wishchin::vertax_size = 17;//顶点个数
	//strcat(filename_vertax, argv[4]);
	std::string filename_vertaxs("D:/DataSet/RsData/loopFind/houseVotex.txt");
	//printf("eage_size : %d, vertax_size : %d, filename-eage : %s, filename-vertax : %s\n",\
				wishchin::eage_size, wishchin::vertax_size, filename_eages, wishchin::filename_vertax);

	wishchin::readEageDataFromFile(filename_eages);
	wishchin::readVertaxDataFromFile(filename_vertaxs);

	wishchin::createAdjacentMatrix();

	wishchin::DFSTraverse();
	//test_stack();  

	return true;
}

namespace wishchin{

	void readEageDataFromFile( std::string filename_eages)
	{
		FILE* f_read;
		if (NULL == (f_read = fopen(filename_eages.c_str(), "r")))
		{
			printf("open file(%s) error!\n", filename_eages.c_str());
			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);
			}
			printf("%d\t%d\n", eage_set[i][1], eage_set[i][2]);
		}

		//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 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 readVertaxDataFromFile( std::string filename_vertaxs )
	{
		//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_vertaxs.c_str(), "r")))
		{
			printf("open file(%s) error", filename_vertaxs.c_str());
			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  
	}
}

namespace wishchin{

	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;
	}
}

测试数据:

      houseAdj.txt:

1 2
2 3
3 4
1 5
2 6
3 7
4 8
5 6
5 9
7 8
7 12
9 10
10 11
11 12
12 17
9 13
10 14
11 15
17 16
13 14
14 15
15 16


      housevotex.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17


程序输出:




       



posted @ 2018-01-17 09:53  wishchin  阅读(1710)  评论(0编辑  收藏  举报