参加某面试遇到的题目,当时只有一个想法,也没有写对,回来后自己想了两个思路,如有错误请大家给与指正。
VS2010可以运行通过。
1.深度优先搜寻遍历法(结果不准确)
存储结构:邻接链表
判断图中是否有环的思想:
如果存在回路,则必存在一个子图,是一个环路。
找出环个数和环中元素的思想:
遍历过程中记录节点个数,当节点个数大于三个,并且当前被遍历节点数和首节点相同,则求得该环。
2.回溯法搜寻遍历法
存储结构:邻接矩阵
判断图中是否有环的思想:
如果存在回路,则必存在一个子图,是一个环路。
找出环个数和环中元素的思想:
把度为1 的结点都删除后,剩下的均为环中元素,之后进回溯法遍历。
两种方法都是先求得所有可能的环,这其中有重复环,文中使用节点字母组成字符串,最后对字符串排序后,删除重复字符串,
因此程序中输出的结果是这些节点组成字符串的排序后值。
具体程序如下所示
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
//图的个数
const int Num=13;
//边连接情况
int path[13][2]={{0,1},{0,2},{0,5},{0,11},{1,12},{3,4},{6,7},{6,10},{6,8},{7,10},{11,9},{11,12},{9,12}};
//存储所有遍历到的环,最后根据环字符串,删除重复环
vector<string> AllCircle,AllCircle2;
//回溯法求解时,剔除度为一的节点后剩余节点
vector<int> NewNode;
/*******************************以下为深度优先遍历(答案不太对)*****************************************/
//深度优先遍历 部分
struct Link
{
int data;
int dim;
Link* next;
};
//邻接链表存储
Link* CreateLink()
{
Link* MyLink=new Link[Num];
for(int i=0;i<Num;++i)
{
MyLink[i].data=i;
MyLink[i].next=NULL;
MyLink[i].dim=0;
}
for(int i=0;i<_countof(path);++i)
{
int a,b;
a=path[i][0];
b=path[i][1];
Link* Linka=new Link;
Linka->data=b;
Linka->dim=0;
Linka->next=MyLink[a].next;
MyLink[a].next=Linka;
MyLink[a].dim++;
Link* Linkb=new Link;
Linkb->data=a;
Linkb->dim=0;
Linkb->next=MyLink[b].next;
MyLink[b].next=Linkb;
MyLink[b].dim++;
}
/*cout<<"Output of link table:"<<endl;
for (int i=0;i<Num;++i)
{
Link *p=&MyLink[i];
cout<<char(p->data+'A')<<" "<<p->dim<<" ";
while(p->next!=NULL)
{
p=p->next;
cout<<char(p->data+'A')<<" ";
}
cout<<endl;
}*/
return MyLink;
}
//深度优先遍历
void DFS(int n,Link* MyLink,bool* visit,vector<char>& Circle)
{
Link *Tmp=&MyLink[n];
Circle.push_back(n+'A');
visit[n]=true;
while(Tmp->next!=NULL)
{
int nn=Tmp->next->data;
int dim=MyLink[nn].dim;
if(!visit[nn]&&dim>1)
DFS(nn,MyLink,visit,Circle);
else
{
if((nn+'A')==Circle[0]&&Circle.size()>2)
{
AllCircle.push_back(string(Circle.begin(),Circle.end()));
}
}
Tmp=Tmp->next;
}
}
//深度优先遍历处理函数
void DFSSearch()
{
Link* MyLink=CreateLink();
for (int i=0;i<Num;++i)
{
if(MyLink[i].dim>1)
{
vector<char> Circle;
bool* visit=new bool[Num];
memset(visit,0,Num);
DFS(i,MyLink,visit,Circle);
//cout<<string(Circle.begin(),Circle.end())<<endl;
}
}
vector<string> TmpCircle=AllCircle;
for (int i=0;i<TmpCircle.size();++i)
{
sort(TmpCircle[i].begin(),TmpCircle[i].end());
}
sort(TmpCircle.begin(),TmpCircle.end());
vector<string>::iterator it=unique(TmpCircle.begin(),TmpCircle.end());
TmpCircle.erase(it,TmpCircle.end());
cout<<"深度优先遍历所求环组合"<<endl;
for (int i=0;i<TmpCircle.size();++i)
{
cout<<TmpCircle[i]<<" ";
}
cout<<endl;
}
/*******************************以下为回溯法遍历(请大家给予意见)*****************************************/
//判断节点是否选择正确
bool IsSafe(int m,int n,int** path,vector<int>& Circle)
{
if (n>0)
{
if(n==1)
{
if(!path[m][Circle[n-1]]||m==Circle[n-1])
return false;
}
else
{
if(!path[m][Circle[n-1]]||m==Circle[n-1]||m==Circle[n-2])
{
return false;
}
if(count(Circle.begin(),Circle.end(),m)>0&&Circle[0]!=m)
{
return false;
}
}
}
return true;
}
//回溯寻找
void FindCircle(int n,int** path,vector<int>& Circle,int NewLen)
{
if(Circle.size()>2&&Circle[n-1]==Circle[0])
{
string TmpCircle;
for (int i=0;i<Circle.size()-1;++i)
{
TmpCircle+=char(NewNode[Circle[i]]+'A');
}
AllCircle2.push_back(TmpCircle);
//cout<<TmpCircle<<endl;
return;
}
else
{
int i,j(0);
for(i=j;i<NewLen;++i)
{
if(IsSafe(i,n,path,Circle))
{
++n;
Circle.push_back(i);
FindCircle(n,path,Circle,NewLen);
--n;
Circle.pop_back();
if(n==0)
++j;
}
}
}
}
//回溯法处理函数
void RecallSearch()
{
int NodeDim[Num]={0};
int a,b;
for(int i=0;i<_countof(path);++i)
{
a=path[i][0];
b=path[i][1];
NodeDim[a]++;
NodeDim[b]++;
}
for(int i=0;i<Num;++i)
{
if(NodeDim[i]>1)
{
NewNode.push_back(i);
//cout<<char(i+'A')<<endl;
}
}
int Len=NewNode.size();
int **NewPath=new int*[Len];
for(int i=0;i<Len;++i)
NewPath[i]=new int [Len]();
vector<int>::iterator ita,itb;;
for(int i=0;i<_countof(path);++i)
{
a=path[i][0];
b=path[i][1];
if( (ita=find(NewNode.begin(),NewNode.end(),a))!=NewNode.end()
&&(itb=find(NewNode.begin(),NewNode.end(),b))!=NewNode.end() )
{
NewPath[ita-NewNode.begin()][itb-NewNode.begin()]=1;
NewPath[itb-NewNode.begin()][ita-NewNode.begin()]=1;
}
}
/*for(int i=0;i<Len;++i)
{
for(int j=0;j<Len;++j)
cout<<NewPath[i][j]<<" ";
cout<<endl;
}*/
vector<int> Circle;
FindCircle(0,NewPath,Circle,Len);
vector<string> TmpCircle=AllCircle2;
for (int i=0;i<TmpCircle.size();++i)
{
sort(TmpCircle[i].begin(),TmpCircle[i].end());
}
sort(TmpCircle.begin(),TmpCircle.end());
vector<string>::iterator it=unique(TmpCircle.begin(),TmpCircle.end());
TmpCircle.erase(it,TmpCircle.end());
cout<<"回溯法遍历所求环组合"<<endl;
for (int i=0;i<TmpCircle.size();++i)
{
cout<<TmpCircle[i]<<" ";
}
cout<<endl;
for(int i=0;i<Len;++i)
delete []NewPath[i];
delete NewPath;
}
int main()
{
DFSSearch();
RecallSearch();
system("pause");
return 0;
}
测试:
要输入的图:
结果: