数据结构之DFS递归与非递归遍历邻接表存图

学习邻接表存图请看:https://blog.csdn.net/HPU_FRDHR/article/details/83957240

 DFS (深度优先搜索)

       深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。

算法步骤: 

按如下将图存好后开始遍历:

1.在访问图中某一起始顶点 v 后,由 v 出发,访问它的任一邻接顶点 w1

2.再从 w1 出发,访问 w1邻接但还未被访问过的顶点 w2

3.然后再从 w2 出发,进行类似的访问,…,如果w2后所有的节点都被访问过了,接着,退回一步,退到前一次刚访问过的顶点,看是否还有其它没有被访问的邻接顶点,即回溯到前一个节点w1继续访问。

4.如此进行下去,直至到达所有的邻接顶点都被访问过的顶点 u 为止。

 代码实现:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;

#define OK 1
#define MVNum 100								//最大顶点数 

typedef int Status;
typedef int OtherInfo;
typedef char VerTexType;

Status visited[MVNum];							//访问标志数组,其初值为0 

typedef struct ArcNode{							//边节点
	int adjvex;									//该边所指向的在顶点的位置 
	struct ArcNode * nextarc;					//指向下一条边的指针 
	OtherInfo info;								//和边相关的信息 
}ArcNode;

typedef struct Vnode{							//顶点信息 
	VerTexType data;
	ArcNode *firstarc;							//指向第一条依附该顶点的指针 
}VNode,AdjList[MVNum];							//AdjList表示邻接表类型
 
typedef struct{
	AdjList vertices;
	int vexnum,arcnum;							//图当前的顶点数和边数 
}ALGraph;

//确定v在G中的位置,即顶点在G.vertices中的序号 
Status LocateVex(ALGraph G,char v){
	int i;
	for(i=0;i<G.vexnum;i++){
		if(v==G.vertices[i].data)
		    return i;
	}
}

//邻接表法创建无向图 
Status CreateUDG(ALGraph &G){
	Status i,j,k; 
	char v1,v2;
	ArcNode *p1,*p2;
	cout<<"请输入总顶点数 总边数:"; 
	cin>>G.vexnum>>G.arcnum;					//输入总顶点数总边数
	puts("请输入顶点信息:");
	for(i=0;i<G.vexnum;++i){					//输入各点,构造表头节点表
		cin>>G.vertices[i].data;				//输入顶点值
		G.vertices[i].firstarc=NULL;			//初始化表头节点的指针域为NULL
	}
	puts("请输入每一条边对应的两个顶点:");
	for(k=0;k<G.arcnum;++k){					//输入各边,构造邻接表
		cin>>v1>>v2;							//输入一条边依附的两个顶点
		i=LocateVex(G,v1);
		j=LocateVex(G,v2);
		p1=new ArcNode;							//生成一个新的边节点*p1
		p1->adjvex=j;							//邻接点序号为j
		p1->nextarc=G.vertices[i].firstarc;		//将新节点*p1插入顶点vi的边表头 
		G.vertices[i].firstarc=p1;
		p2=new ArcNode;							//生成一个新的边节点*p2
		p2->adjvex=i;							//邻接点序号为i
		p2->nextarc=G.vertices[j].firstarc;		//将新节点*p2插入顶点vj的边表头
		G.vertices[j].firstarc=p2;
	}
	return OK;
}

//打印邻接表存储数据
void print_position(ALGraph G){
	int i;
	for(i=0;i<G.vexnum;i++){
		ArcNode p;
		p.adjvex=G.vertices[i].firstarc->adjvex;
		p.nextarc=G.vertices[i].firstarc->nextarc;
		printf("%c->",G.vertices[i].data);
		while(p.nextarc!=NULL){
			printf("%c -> ",G.vertices[p.adjvex].data);
			p=*p.nextarc;
		}
		printf("%c\n",G.vertices[p.adjvex].data);
	} 
}

//递归实现从第v个顶点出发深度优先搜索遍历图G
void DFS_AL(ALGraph G,int v){
	ArcNode *p;
	int w;
	printf("%c ",G.vertices[v].data);			//访问第v个顶点
	visited[v]=1;								//置访问标志数组相应分量值为1
	p=G.vertices[v] .firstarc;					//p指向v的边链表的第一个边结点
	while (p!=NULL){							//边结点非空
		w=p->adjvex;							//表示w是V的邻接点
		if(!visited[w])	DFS_AL(G,w);			//如果w未访问,则递归调用DFS_ AL
		p=p->nextarc;							//p指向下一个边结点
	}
}

//非递归实现从第v个顶点出发深度优先搜索遍历图G
void DFS_ALL(ALGraph G,int v){
	memset(visited,0,sizeof(visited));
	stack<char> st;									//定义一个栈 
	ArcNode *p;
	int w,n,s;
	n=G.vexnum-1;
	printf("%c ",G.vertices[v].data);				//访问第v个顶点
	st.push(G.vertices[v].data);					//将第v个顶点压入栈中 
	visited[v]=1;									//置访问标志数组相应分量值为1
	p=G.vertices[v] .firstarc;						//p指向v的边链表的第一个边结点
	while(n){
		int cnt=0;
		while(p!=NULL){								//边结点非空
			w=p->adjvex;							//表示w是V的邻接点
			if(!visited[w]){//如果w未访问
				printf("%c ",G.vertices[w].data);
				st.push(G.vertices[w].data);
				visited[w]=1;
				cnt=1,n--;
				break;
			}else
				p=p->nextarc;
		}
		if(cnt==0)
			st.pop();
		s=LocateVex(G,st.top());
		p=G.vertices[s] .firstarc;
	}
} 

int main(){
	char s,k;
	int n,m; 
	memset(visited,0,sizeof(visited)); 
	ALGraph G;
	CreateUDG(G);
	puts("构建的邻接表为:");
	print_position(G);
	puts("请输入递归遍历开始的起点:"); 
	cin>>s;
	n=LocateVex(G,s);
	DFS_ALL(G,n);
	printf("\n");
	puts("请输入非递归遍历开始的起点:");
	cin>>k;
	m=LocateVex(G,k);
	DFS_ALL(G,m);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/HPU_FRDHR/article/details/83957492