如题,
现在有一个想法是:
一个节点可能有四个状态: 0 , 1 , 2 , -1
0代表该节点未被访问,1代表该节点正在被访问,2表示该节点已经被访问且已经在一个环中,-1表示该节点已经被访问过且没有处于任何一个环中。
利用深度遍历有向图。
不知道这种算法是不是有缺陷,不知道咋论证。自己实现了一下没成功,总是出现各种问题,代码如下(不准确,未完成找环功能):
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define maxNum 10 //定义邻接举证的最大定点数
#define maxCycle 10
int temp[maxNum];//用于环路共用路径的暂时存储
typedef struct cycle_package
{
int visited[maxNum];//通过visited数组来标记这个顶点是否被访问过,0表示未被访问,1表示被访问
int cycle[maxCycle][maxNum];//存储找到的环路
int num_cycle ;//用于环路数量的增加
};
//图的邻接矩阵表示结构
typedef struct
{
char v[maxNum];//图的顶点信息
int e[maxNum][maxNum];//图的边信息
int vNum;//顶点个数
int eNum;//边的个数
}graph;
graph *g;
void createGraph(graph *g);//创建图g
void DFS(cycle_package *cp,graph *g);//深度优先遍历图g
void Print(cycle_package *cp,int head,int pre,int next,int num_dot);//保存环路径中的结点
void Visit(cycle_package *cp,int begin,int head,int pre_i,int j,int order=0);//沿visited值为2的搜索,不能回头,不能为环头
void Visit(cycle_package *cp,int begin,int head,int pre_i,int j,int order)
{
struct list
{
int order;
int positon;
int mark;
};
int temp_counter = 0;
temp[order] = j;
list visited_c[maxNum];
int v_c_counter = 0;
int go_mark = 0;//默认没有-1结点
for (int i = 0;i<g->vNum;i++)//此循环与下一循环是为了将visited数组中的标志排序,优先访问-1结点
{
if (cp->visited[i]==-1)
{
visited_c[v_c_counter].mark= -1;
visited_c[v_c_counter].positon = i;
v_c_counter++;
//head_mark = 1;
}
}
for (int i = 0;i<g->vNum;i++)
{
if (cp->visited[i]==2)
{
visited_c[v_c_counter].mark=2;
visited_c[v_c_counter].positon = i;
v_c_counter++;
}
}
for (int i = 0;i<v_c_counter;i++)
{
/*在此循环中出现了这样的问题,按照标志=-1的结点走完之后,又会走标志等于2的路径,导致进入一个无限的循环*/
if(g->e[j][visited_c[i].positon]!=0&&visited_c[i].mark==-1&&go_mark == 0)
{
int temp_i;
for (temp_i = 1;temp_i<=(order+1);temp_i++)
{
cp->cycle[cp->num_cycle][temp_i] = temp[temp_i-1];
}
int temp_num = temp[order];//temp[order]不能直接传给print()
// cp->visited[visited_c[i].positon] = 2;
Print(cp,temp_num,j,visited_c[i].positon,temp_i);
cp->visited[begin] = 2;
cp->cycle[cp->num_cycle][0] = begin;
go_mark = 1;
cp->num_cycle++;
order = 0;
}
else if (visited_c[i].positon!=head&&visited_c[i].positon!=pre_i&&visited_c[i].mark==2&&g->e[j][visited_c[i].positon]!=0&&go_mark== 0)
{
Visit(cp,begin,head,j,visited_c[i].positon,order+1);
}
}
}
void Print(cycle_package *cp,int head,int pre,int next,int num_dot)//num_dot记录环路中的点数量
//有半途指向2的情况!!!
{
int temp_n = num_dot;
int go_mark = 0;
if (next != head)
{
for (int k = 0;k<g->vNum;k++)
{
if (g->e[next][k]!= 0&&(cp->visited[k] == -1)&&go_mark == 0)
{
//cp->viitesd[next] = 2;
cp->visited[next] = 2;
cp->cycle[cp->num_cycle][num_dot] = next;
temp_n++;
Print(cp,head,next,k,temp_n);
go_mark = 1;
}
else if(g->e[next][k]!=0&&(cp->visited[k]==2)&&k!=pre)
{
cp->visited[next] = 2;
cp->cycle[cp->num_cycle][num_dot] = next;
temp_n++;
Visit(cp,next,k,-1,k);
}
}
}
//else {cp->visited[next] = 2;
// cp->cycle[cp->num_cycle][num_dot] = next;
// temp_n++;}
}
void dfs(cycle_package *cp,graph *g,int cur_point)
{
//cout<<"顶点"<<g->v[i]<<"已经被访问"<<endl;
// cout<<"顶点"<<i<<"已经被访问"<<endl;
cp->visited[cur_point]=-1;//标记顶点i被访问
for(int next_point=0;next_point<g->vNum;next_point++)
{
if(g->e[cur_point][next_point]!=0&&cp->visited[next_point]==0)
{dfs(cp,g,next_point); }
else if(g->e[cur_point][next_point]!=0&&cp->visited[next_point]==-1&&next_point!=cur_point)
{
Print(cp,cur_point,cur_point,next_point,1);
cp->visited[cur_point] = 2;
cp->cycle[cp->num_cycle][0] = cur_point;
cp->num_cycle++;
}
else if (g->e[cur_point][next_point]!=0&&cp->visited[next_point]==2)
{
Visit(cp,cur_point,next_point,-1,next_point);
}
}
if(cp->visited[cur_point]!=2)
cp->visited[cur_point] = 1;
}
void DFS(cycle_package *cp,graph *g)
{
int i;
//初始化visited数组,表示一开始所有顶点都未被访问过
for(i=0;i<g->vNum;i++)
cp->visited[i]=0;
//深度优先搜索
for(i=0;i<g->vNum;i++)
if(cp->visited[i]==0)//如果这个顶点未被访问过,则从i顶点出发进行深度优先遍历
dfs(cp,g,i);
int k = 0;
cout <<k<<endl;
}
void createGraph(graph *g)//创建图g
{
cout<<"正在创建无向图..."<<endl;
cout<<"请输入顶点个数vNum:";
cin>>g->vNum;
cout<<"请输入边的个数eNum:";
cin>>g->eNum;
int i,j;
//输入顶点信息
//cout<<"请输入顶点信息:"<<endl;
//for(i=0;i<g->vNum;i++)
// cin>>g->v[i];
//初始画图g
for(i=0;i<g->vNum;i++)
for(j=0;j<g->vNum;j++)
g->e[i][j]=0;
//输入边的情况
cout<<"请输入边的头和尾"<<endl;
for(int k=0;k<g->eNum;k++)
{
cin>>i>>j;
g->e[i][j]=1;
}
}
int main()
{
cycle_package *cy;
cy = (cycle_package *)malloc(sizeof(cycle_package));
cy->num_cycle = 0;
g=(graph*)malloc(sizeof(graph));
createGraph(g);
DFS(cy,g);
int i;
cin>>i;
system("pause");
return 0;
}