C++ 深度优先搜索(邻接表+栈实现)
深度优先搜索的结果是图的生成树,也就是极小连通图(n个顶点有n-1条边)
图的生成树的结果是不唯一的,它是根据你的存储方式的变化而变化的。
深度搜索步骤:
1.确定一个开始顶点,并将该顶点标记为已访问。
2.访问开始顶点的第一个邻接顶点,
if(未被访问)
将该邻接顶点标记为已访问。
将该邻接顶点作为新的开始顶点。
重复2
else
搜索下一个邻接顶点。重复2
3.当开始顶点的所有邻接顶点均已被访问
回溯到上一个开始顶点,重复2
4.直到所有的顶点都已被访问过(没有点作为开始顶点),程序结束。
假设我们有以下这个图:
那么我们深度搜索的结果应该是:
v1->v2->v4->v8->v5->v3->v6->v7
深度搜索的代码实现(栈实现)
像这种先深入后回溯的算法 很适合我们栈这样先进后出的数据结构。当然也可以用递归解决。这里我们选用栈实现上面那个图的深度搜索过程
1.邻接表的实现
//AdjanceyList.h
#pragma once
#include<iostream>
#include<vector>
using namespace std;
//邻接表+DFS实现图的深度优先搜索(无向图)
struct AdjacenyList
{
int adjacenyNode;
AdjacenyList *nextarc;
};
//邻接表表头
struct headerList
{
int headerNode;
AdjacenyList *firstarc;
};
//邻接表
class graphAdjacencyList
{
public:
graphAdjacencyList(int nodeNum)
{
this->nodeNum=nodeNum;
this->hvexArray=new headerList[nodeNum]();
if(hvexArray==NULL)
{
cout<<"out of space"<<endl;
exit(1);
}
for(int i=0;i<nodeNum;++i)
{
hvexArray[i].firstarc=NULL;
hvexArray[i].headerNode=-1;
}
}
~graphAdjacencyList()
{
if(hvexArray!=NULL)
{
delete[] hvexArray;
}
if(!adjvector.empty())
{
for(vector<AdjacenyList*>::iterator it=adjvector.begin();it!=adjvector.end();++it)
{
delete (*it);
}
}
}
void addEdge(int tail,int head)//(tail,head)
{
AdjacenyList *adjvex=new AdjacenyList();
adjvex->nextarc=NULL;
adjvex->adjacenyNode=head;//邻接顶点信息
if((hvexArray+tail)->headerNode==-1)
{
//设置头列表
(hvexArray+tail)->headerNode=tail;
(hvexArray+tail)->firstarc=adjvex;
}
else
{
//设置邻接表
AdjacenyList *tempAdjList=(hvexArray+tail)->firstarc;
while(tempAdjList->nextarc!=NULL)//迭代找到最后一个列表接上
{
tempAdjList=tempAdjList->nextarc;
}
tempAdjList->nextarc=adjvex;
}
adjvector.push_back(adjvex);
}
headerList *getList()
{
return hvexArray;
}
private:
//AdjacenyList *adjvex;
vector<AdjacenyList*> adjvector;//用vector来管理领接顶点的内存
headerList *hvexArray;
int nodeNum;
};
2.深度搜索(DFS)实现
void dfs(graphAdjacencyList &graph, int start,int nodeNum)
{
stack<int> s;
vector<bool> visited(nodeNum,false);//顶点是否被访问
s.push(start);
cout<<start;
visited[start]=true;
while(!s.empty())
{
int currentNode=s.top();
AdjacenyList *temp=graph.getList()[currentNode].firstarc;
//栈顶元素顶点存在未被访问过的领接点
//1.找到未被访问的点
while(temp!=NULL)
{
if(visited[temp->adjacenyNode]!=false)//已被访问
{
temp=temp->nextarc;
}
else//未被访问
{
//输出顶点
cout<<"-->"<<temp->adjacenyNode;
//将顶点改为:已访问
visited[temp->adjacenyNode]=true;
//将顶点入栈,作为新的起点开始搜索
s.push(temp->adjacenyNode);
break;//跳出搜索
}
}
if(temp==NULL)//无领接点未被访问(叶顶点)
{
s.pop();
}
}
cout<<endl;
}
实现上图的深度搜索
int main(int argc, const char** argv) {
graphAdjacencyList graph_adjlist(8);
graph_adjlist.addEdge(0,1);
graph_adjlist.addEdge(0,2);
graph_adjlist.addEdge(1,0);
graph_adjlist.addEdge(1,3);
graph_adjlist.addEdge(1,4);
graph_adjlist.addEdge(2,0);
graph_adjlist.addEdge(2,5);
graph_adjlist.addEdge(2,6);
graph_adjlist.addEdge(3,1);
graph_adjlist.addEdge(3,7);
graph_adjlist.addEdge(4,1);
graph_adjlist.addEdge(4,7);
graph_adjlist.addEdge(5,2);
graph_adjlist.addEdge(5,6);
graph_adjlist.addEdge(6,2);
graph_adjlist.addEdge(6,5);
graph_adjlist.addEdge(7,3);
graph_adjlist.addEdge(7,4);
// printgraphAdjList(graph_adjlist,8);
dfs(graph_adjlist,0,8);
// bfs(graph_adjlist,0,8);
system("pause");
return 0;
}