数据结构学习笔记 图:深度优先搜索(严蔚敏版)

深度优先搜索:假设初始状态是图中的所有顶点未曾被访问,则深度优先搜索可从图中某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中的所有和v有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中的所有顶点都被访问到为止。

       邻接表存储结构分为两部份:一是顺序表,二是链表。图中的顶点按顺序存储在顺序表中,顺序表结点分为两个域:数据域(data)和链域(firstarc),数据域存储的是图中顶点的信息,链域存储的是指针,指向该点的其中一个邻接点;在链表中存储的是顶点vi的邻接点,链表中分为邻接点域(adjvex)、链域(nextarc)和数据域(info),邻接点域(adjvex)存储的是顶点vi的邻接点在顺序表中的位置,链域(firstarc)指向顶点vi下一个邻接点,数据域存储的是网的权值。

       如果图是用邻接表存储结构存储,那么在进行深度优先搜索遍历时,先从顺序表中的第一个顶点vi出发,访问该顶点(记得别忘了将已访问过的顶点做标记),然后访问vi在存储结构中的第一个邻接点vj,接着再访问vj的邻接点,不断的进行“访问邻接点的邻接点”这样一个循环,直到遇到一个顶点它的邻接点已经被访问过,循环结束,接着访问vi的下一个邻接点,直至vi的邻接点都被访问完。访问完vi的邻接点后,接着访问顺序表中的第二个顶点,直至顺序表中的所有顶点都已经被访问到。

顺序表中的结点:

链表中的结点:

 

图:


邻接表:


#include<iostream>               ///深度优先搜索,通过有向图的邻接表存储
#include<malloc.h>               ///有向图的邻接表中,第i个链表的的结点数只是顶点vi的出度,为求入度,必须遍历整个邻接表或是建立有向图的逆邻接表

#define MAX_VERTEX_NUM 20
#define MAX_NAME 5
#define OK 1
#define TRUE 1
#define FALSE -1
typedef char VertexType[MAX_NAME];    
typedef int InfoType;       

using std::cin;
using std::cout;
using std::endl;
typedef struct ArcNode                           //单链表中结点的类型
{
	int adjvex;                              //该边指向的顶点在顺序表中的位置
	struct ArcNode *nextarc;  
	InfoType *info;                          //网的权值指针
}ArcNode;

typedef struct VNode                             //定义顶点类型
{
	VertexType data;
	ArcNode *firstarc; 
}VNode, AdjList[MAX_VERTEX_NUM];

typedef struct      
{	AdjList vertices;                        //顺序表
	int vexnum, arcnum;    
	int kind;
}ALGraph;
int LocateVex(ALGraph &G, VertexType &u)         //返回顶点u在vertices中的位置
{
   for(int i = 0;i < G.vexnum; ++i)
   {
	   if(strcmp(G.vertices[i].data,u) == 0)
		   return i;
   }
   return FALSE ;
}

int CreateDG( ALGraph &G )                       //有向图的邻接表
{
   int  i,j,k,w;
  VertexType v1,v2;
   cout <<"开始构造有向图:\n请输入图的顶点的个数:";
	cin >> G.vexnum;
	cout << "请输入图的边的数目:";
	cin >> G.arcnum;
  cout <<"请输入所有的顶点:\n";
  for(i = 0; i < G.vexnum; ++i)
	{
	        cout << "请输入第"<< i+1 << "个顶点:";
			scanf("%s",G.vertices[i].data);
		G.vertices[i].firstarc = NULL;
	}
  cout <<"请输入弧,例如 v1-->v2\n";
  for(k = 0; k < G.arcnum; ++k)
	{
           cout << "请输入第" << k+1 << "条弧的弧尾";
	   cin >> v1;
	   cout << "请输入第" << k+1 << "条弧的弧头";
	   cin >> v2;
           i = LocateVex(G,v1);
	   j = LocateVex(G,v2);
	   ArcNode *p;
	   p = (ArcNode *)malloc(sizeof(ArcNode));
	   if(!p)
	   {
		   cout << "Overflow";
		   return 0;
	   }
	   p->adjvex = j;
	   p->nextarc = G.vertices[i].firstarc;       //单链表的逆序构造,即输入的第一个结点会成为最后一个结点
	   G.vertices[i].firstarc  = p;
	   p->info = NULL;
	}   // for end
	  

       
   return OK;
}  // CreateDG() end

void DFS(ALGraph G, int v, int *visited)              //如果该图是连通图,只需从G.vertices[0]出发便可以遍历图中的所有节点
{                                                     
        ArcNode *p;
	int w;
	visited[v] = TRUE;
	cout << v + 1 << "->";
	for(p = G.vertices[v].firstarc; p != NULL; p = p->nextarc)
	{
		if(visited[p->adjvex] == 0)
		{
			visited[p->adjvex] = 0;
			DFS(G, p->adjvex,visited);   //不断的访问节点的邻接点
		}
	}

		       
}  // DFS() end
void DFSTraverse( ALGraph &G )
{
	int v;
	int visited[MAX_VERTEX_NUM];
	for( v = 0; v < G.vexnum; ++v )
		visited[v] = 0;                       //visited 为辅助数组用于标记顶点是否被访问
	for( v = 0; v < G.vexnum; ++v )
		if(visited[v] == 0 )
			DFS(G,v,visited); 
}//DFSTraverse() end
void DestroyALGraph(ALGraph &G)                      //销毁分配的空间
{
    ArcNode *q;
    for(int i = 0; i < G.vexnum; ++i)
	    for(ArcNode *p = G.vertices[i].firstarc; p != NULL;)
	    {
	      G.vertices[i].firstarc = NULL;
	      q = p;
              p = p->nextarc;
              free(q);
	      
	    }
}
void main()
{
	ALGraph G;
	cout << endl << "DFSTraverse.cpp";
	cout << endl << "===================" << endl;
	CreateDG(G);   
	cout <<"深度优先搜索:\n";
	DFSTraverse(G);
        DestroyALGraph(G);

}// main end

运行结果:


  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值