对于一个有向图,请实现一个算法,找出两点之间是否存在一条路径。 给定图中的两个结点的指针UndirectedGraphNode*a,UndirectedGraphNode* b(请不要在意数据类型,图是有向图),请返回一个bool,代表两点之间是否存在一条路径(a到b或b到a)。 题目分析: 这个题目考察的其实是有向图的遍历,图的遍历分为深度优先遍历和广度优先遍历,深度优先遍历(DFS)用堆栈(Stack)实现,广度优先遍历(BFS)用队列(queue)实现,在该题目中给出了每个节点的子节点,所以最好用广度优先遍历。 图的广度优先遍历和树的层次遍历类似,但是不是完全相同,因为图是连通的,所以我们必须去标志那个节点被访问过,那个节点没有被访问过,最后如果全部访问完以后,还没有找到a到b的路径,则返回false。 广度优先类似于一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点。 具体算法表述如下:
如下图,其广度优先算法的遍历顺序为:1->2->3->4->5->6->7->8 注意知识点: (1)图中有环,记得标记是否被访问
(2)要分别检测两个方向(a->b,b->a) //BFS class Path { public : bool checkPath(UndirectedGraphNode* a, UndirectedGraphNode* b) { // write code here return check(a,b)||check(b,a); } bool check(UndirectedGraphNode* a, UndirectedGraphNode* b) { // write code here //a,b为空,直接返回false if (a==NULL||b==NULL) return false ; if (a==b) //最开始检查//a,b相等,直接返回true return true ; // 为了防止环的产生,已经入栈过的点不再入栈,用map管理 //用来标记是否访问过该节点 //上不同。这里graphNode没有isVisit属性,无法标记是否访问,所以用map辅助
map<UndirectedGraphNode*, bool > map1; //BFS工作队列 queue<UndirectedGraphNode*> que; //队列保存节点 que.push(a); //入队列 while (!que.empty()) //队列不为空 { UndirectedGraphNode* ptr=que.front(); //弹出队列首元素 map1[ptr]= true ; //标记访问//ptr节点被访问 for ( int i=0;i<ptr->neighbors.size();i++) { if ((ptr->neighbors)[i]==b) //如果邻居为b return true ; //近邻节点存在,且未被访问,进队列 if (ptr->neighbors[i]&&map1[ptr->neighbors[i]]!= true ) que.push((ptr->neighbors)[i]); //入队 } que.pop(); //出队 } return false ; } };
BFS还有一种方法:
两种方法:基本相同,就是队列的出队时的代码写的地方不同,但是,因为队列是先进先出,所以,写的上面两个地方的位置均可。
|
|
来自: 雪柳花明 > 《C 笔试 算法题准备》