图:
1、深度优先搜索算法的非递归形式(邻接表)
输入:无
输出:输出图的深度优先遍历序列
优化目标:无
思路:在深度优先搜索的非递归算法中使用了一个栈,记忆下一步可能访问的顶点,同时使用了一个访问数据visited[i],在visited[i]中记忆第i个顶点是否在栈内或曾经在栈内。若是,以后它不能再进栈。
void DFS_Non_RC(AGraph Graph,int v){//从顶点v开始进行深度优先搜索,一次遍历一个连通分量的所有顶点
int w;//顶点序号
int stack[maxsize],top=-1;//初始化栈
PtrToAdjVNode p;
for(i=0;i<G.vexnum;i++)
visited[i]=FALSE;//初始化visited
stack[++top]=v;//将顶点入栈
visited[v]=TRUE;//标记顶点为:已访问
while(top!=-1){
k=stack[top--];//取栈顶元素
visit(k);//访问当前结点(出栈时候访问)
for(p=Graph->G[k].FirstEdge;p;p=p->Next)//对当前结点进行深度遍历
Vertex w=p->AdjV;
if(!visited[w]){//将未进过栈的结点进栈
stack[++top]=w;
visited[w]=true;//进栈后做好标记,以免再次入栈
}
}
}
ps:由于使用了栈,使得遍历的方式从右端到左端进行,不同于常规的从左端到右端,但仍然是深度优先遍历。另外树的先序遍历是入栈时访问,中序遍历是出栈时访问,层次遍历是出队时访问,图的深度遍历是出栈时访问,广度遍历是入队时访问。
2、判断一个无向图G是否为一棵树
输入:无
输出:输出判断图是否为一颗树
优化目标:无
思路:一个无向图G是一棵树的条件是G必须是无回路的连通图或者是有n-1条边的连通图。这里采用后者作为判断条件。对连通图的判定,可用能否遍历全部顶点来实现。可以采用深度优先搜索算法在遍历图的过程中统计可能访问到的顶点个数和边的条数,如果一次遍历就能访问到n个顶点和n-1条边,则可判定此图是一棵树。
bool isTree(AGraph Graph)
{
for (int i=0; i<G.vexnum; i++)
visited[i]=FALSE; //访问标记visited[]初始化
int Vnum=0, Enum=0; //记录点数和边数
DFS(G,1,Vnum,Enum);
if(Vnum==G.vexnum &&Enum==2*(G.vexnum-1))
return 1; //符合树的条件
else
return 0; //不符合树的条件
}
void DFS(MGraph Graph,int v, int& Vnum, int& Enum) {
PtrToAdjVNode p;
Visited[v]=true;//先设置当前结点已访问
Vnum++; //做访问标记,顶点计数
p=Graph->G[v].FirstEdge;
while(p)
{
Enum++;
if(!visited[p->adjvex])
DFS(Graph,p->AdjV,Vnum,Enum);
p=p->next;
}
}
3、假设一个图G采用邻接表作为存储结构,设计一个算法,判断该图中是否存在回路。
输入:无
输出:输出判断图中是否存在回路
优化目标:无
思路:采用深度优先遍历方法,从顶点v出发,对每个访问的顶点做标记。若顶点w(先访问)和i(后访问)均已访问过,表示从顶点w到顶点i存在一条路径。当从顶点i出发遍历,发现顶点i到顶点w有一条边时,表示存在一个回路(该回路上包含顶点w和i)。
void Cycle(AGraph *G,int v,bool &has)
{ //调用时has置初值false
PtrToAdjVNode *p;
int w;
visited[v]=1; //置已访问标记
p=Graph->G[v].FirstEdge; //p指向顶点v的第一个邻接点
while (p)
{
w=p->Adjv;
if (visited[i]==0) //若顶点w未访问,递归访问它
Cycle(G,w,has);
else //又找到了已访问过的顶点说明有回路
has=true;
p=p->next; //找下一个邻接点
}
}
ps:同样利用深度优先遍历。
总结:今天练习了几道图的题,不太熟练,还是需要认真学一下图。接下来的重心主要转移到排序和线性表上来,多多加强练习,及时复习以前的题目。