在无向图中查找最小环,就像需要查找一个蜂窝中所有孔洞,如果只查找数目,可以利用欧拉公式,若查找到所有环,需要更进一步的搜索。
方法:寻找到所有顶点的最短路径,对每一个顶点,取出环,循环删除顶点,输出所有最小环。
注意:拓扑图具有位置可变性,不影响图结构的拓扑变化。所以此方法,只能找到拓扑最小环,若想找到距离最小环,需要对边进行加权。
原文:找出无向图中所有环的算法。代码也转自于作者。
图片实例:
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
程序输出: