转载请注明出处:http://blog.csdn.net/ns_code/article/details/23206519
题目:
Given a directed graph, design an algorithm to find out whether there is a route between two nodes.
翻译:
给定一个有向图,设计算法判断两结点间是否存在路径。
思路:
考察图的遍历,如果遍历路径上经过该顶点,则存在路径,不经过则不存在路径,在遍历算法上做一些改进即可。我们这里用图的DFS来改进。并采用图的BFS和DFS一文中的有向图来作测试,并采用邻接矩阵来存储该有向图中的边和顶点信息。
实现代码:
/*
DFS遍历保存路过的顶点字符
*/
int count = 0;
char BL[NUM]; //用来保存遍历路过的顶点字符
void DFS(Graph Gp, int begin)
{
BL[count++] = Gp[begin].data;
visited[begin] = true;
//循环访问当前节点的所有邻接点(即该节点对应的链表)
int i;
for(i=first_vertex(Gp,begin); i>=0; i=next_vertex(Gp,begin,i))
{
if(!visited[i]) //对于尚未遍历的邻接节点,递归调用DFS
DFS(Gp,i);
}
}
/*
判断两个顶点是否连通
*/
bool isArrived(Graph Gp,int begin,int end)
{
DFS(Gp,begin);
int i;
for(i=0;i<count;i++)
if(BL[i] == Gp[end].data)
return true;
return false;
}
完整代码:
/**********************************
题目描述:
给定一个有向图,设计算法判断两结点间是否存在路径
Date:2014-04-08
**********************************/
#define NUM 4 //图中顶点的个数
bool visited[NUM]; //定义全局变量辅助数组,用来保存每个节点的访问信息
/*
用邻接表作为图的存储结构
在邻接表中,用一个一维数组存储图中的每个顶点的信息,
同时为每个顶点建立一个单链表,链表中的节点保存依附在该顶点上的边或弧的信息
*/
typedef struct node
{ //链表中的每个节点,保存依附在该节点上的边或弧的信息
int vertex; //在有向图中表示该弧所指向的顶点(即弧头)的位置,
//在无向图中表示依附在该边上的另一个顶点的位置
struct node *pNext; //指向下一条依附在该顶点上的弧或边
}Node;
typedef struct head
{ //数组中的每个元素,保存图中每个顶点的相关信息
char data; //顶点的数据域
Node *first; //在有向图中,指向以该顶点为弧尾的第一条弧
//在无向图中,指向依附在该顶点上的第一条边
}Head,*Graph; //动态分配数组保存每个顶点的相关信息
//根据图例创建对应的图
Graph create_graph();
//返回图中指定序号顶点的第一个邻接点
int first_vertex(Graph,int);
//返回图中指定序号节点的下一个邻接点
int next_vertex(Graph,int,int);
//DFS保存路过的顶点字符
void DFS(Graph, int);
//判断两顶点是否连通
bool isArrived(Graph,int,int);
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
Graph Gp = create_graph();
memset(visited,0,sizeof(visited));
if(isArrived(Gp,3,2))
printf("D To C Existed\n");
else
printf("D To C Not Existed\n");
if(isArrived(Gp,1,2))
printf("B To C Existed\n");
else
printf("B To C Not Existed\n");
if(isArrived(Gp,3,1))
printf("D To B Existed\n");
else
printf("D To B Not Existed\n");
if(isArrived(Gp,0,3))
printf("A To D Existed\n");
else
printf("A To D Not Existed\n");
int i;
//释放掉为每个单链表所分配的内存
for(i=0;i<NUM;i++)
{
free(Gp[i].first);
Gp[i].first = 0; //防止悬垂指针的产生
}
//释放掉为顶点数组所分配的内存
free(Gp);
Gp = 0;
return 0;
}
/*
根据图例创建对应的图
*/
Graph create_graph()
{
//为保存顶点相关信息的数组分配空间,并对数据域赋值
Graph graph = (Graph)malloc(NUM*sizeof(Head));
int i;
//顶点的序号按照输入顺序从0依次向后
for(i=0;i<NUM;i++)
graph[i].data = 'A' + i;
//为每个节点对应的的单链表中的节点分配空间
Node *p00 = (Node *)malloc(sizeof(Node));
Node *p20 = (Node *)malloc(sizeof(Node));
Node *p21 = (Node *)malloc(sizeof(Node));
Node *p30 = (Node *)malloc(sizeof(Node));
//为各单链表中的节点的相关属性赋值
p00->vertex = 1;
p00->pNext = NULL;
p20->vertex = 0;
p20->pNext = p21;
p21->vertex = 3;
p21->pNext = NULL;
p30->vertex = 0;
p30->pNext = NULL;
//将顶点与每个单链表连接起来
graph[0].first = p00;
graph[1].first = NULL;
graph[2].first = p20;
graph[3].first = p30;
return graph;
}
/*
返回图Gp中pos顶点(序号为pos的顶点)的第一个邻接顶点的序号,如果不存在,则返回-1
*/
int first_vertex(Graph Gp,int pos)
{
if(Gp[pos].first) //如果存在邻接顶点,返回第一个邻接顶点的序号
return Gp[pos].first->vertex;
else //如果不存在,则返回-1
return -1;
}
/*
cur顶点是pos顶点(cur和pos均为顶点的序号)的其中一个邻接顶点,
返回图Gp中,pos顶点的(相对于cur顶点)下一个邻接顶点的序号,如果不存在,则返回-1
*/
int next_vertex(Graph Gp,int pos,int cur)
{
Node *p = Gp[pos].first; //p初始指向顶点的第一个邻接点
//循环pos节点对应的链表,直到p指向序号为cur的邻接点
while(p->vertex != cur)
p = p->pNext;
//返回下一个节点的序号
if(p->pNext)
return p->pNext->vertex;
else
return -1;
}
/*
DFS遍历保存路过的顶点字符
*/
int count = 0;
char BL[NUM]; //用来保存遍历路过的顶点字符
void DFS(Graph Gp, int begin)
{
BL[count++] = Gp[begin].data;
visited[begin] = true;
//循环访问当前节点的所有邻接点(即该节点对应的链表)
int i;
for(i=first_vertex(Gp,begin); i>=0; i=next_vertex(Gp,begin,i))
{
if(!visited[i]) //对于尚未遍历的邻接节点,递归调用DFS
DFS(Gp,i);
}
}
/*
判断两个顶点是否连通
*/
bool isArrived(Graph Gp,int begin,int end)
{
DFS(Gp,begin);
int i;
for(i=0;i<count;i++)
if(BL[i] == Gp[end].data)
return true;
return false;
}
测试结果:
注:代码开源到Github:https://github.com/mmc-maodun/CareerCup