深度優先搜索和廣度優先搜索(數據結構)

基本概念

圖的遍歷定義:

從已給的連通圖中某一頂點出發,沿着一些邊訪遍圖中所有的頂點,且使每個頂點僅被訪問一次,就叫做圖的遍歷,它是圖的基本運算。

遍歷實質:找每個頂點的鄰接點的過程。

圖的特點:

圖中可能存在迴路,且圖的任一頂點都可能與其它頂點想通,在訪問完某個頂點之後可能會沿着某些邊又回到了曾經訪問過的頂點

如何避免重複訪問?

設置輔助數組visited [n],用來標記每個被訪問過的頂點。初始爲0,被訪問過就是1

深度優先搜索

深度優先搜索的遍歷類似於樹的先序遍歷,及根左右的方式遍歷,圖的深度優先是樹的先序遍歷的推廣

廣度優先搜索

從圖的某一結點出發,首先一次訪問該結點的所有鄰接點,再按這些頂點被訪問的先後順序訪問與他們相鄰接的所有未被訪問的頂點,重複此過程。

其實類似於樹的順序遍歷。

連通圖的廣度遍歷:

在這裏插入圖片描述
遍歷順序:
在這裏插入圖片描述
非連通圖的廣度遍歷:
在這裏插入圖片描述

DFS與BFS算法效率比較

  • 空間複雜度相同,都是O(n)(DFS運用遞歸,BFS接用隊列)
  • 時間複雜度只與存儲結構(鄰接矩陣或鄰接表)有關,而與搜索路徑無關,鄰接矩陣複雜的爲O(n ^ n),鄰接表時間複雜讀爲O(n + e)

鄰接矩陣的深搜與廣搜

代碼實現:

#include <iostream>
#include <queue>
using namespace std;
#define MaxInt 0 //表示極大值,即無窮
#define MVNum 100 //最大頂點數
typedef char VerTexType; //設頂點的數據類型爲字符型
typedef int ArcType; //假設邊的權值類型爲整形

bool visited[15];

typedef struct{
 VerTexType vexs[MVNum]; //頂點表
 ArcType arcs[MVNum][MVNum]; //鄰接矩陣
 int vexnum,arcnum; //圖的當前點數和邊數
}AMGraph;//Adjacency Matrix Graph

//在圖中查找頂點
int LocateVex(AMGraph G,int u){
 //在圖G中查找頂點u,存在則返回頂點表中的下標;否則返回-1
 	int i;
 	for(i = 1;i<=G.vexnum;i++)
  	if(u==G.vexs[i])
   		return i;
  	return -1;
} 
//採用鄰接矩陣表示法,創建無向網G
bool CreateUDN(AMGraph &G) 
{
 	char v1,v2;
 	int w,i,j,k;
 	cout<<"分別輸入總頂點數、總邊數:"<<endl;
 	cin>>G.vexnum>>G.arcnum; //輸入總頂點數,總邊數 
 	cout<<"輸入點的信息:"<<endl;
 	for(i=1;i<=G.vexnum;i++)//依次輸入點的信息 
  		cin>>G.vexs[i];
 	for(i=1;i<=G.vexnum;i++)
 	 for(j=1;j<=G.vexnum;j++)
	   G.arcs[i][j]=MaxInt;//初始化鄰接矩陣,邊的權值均置爲極大值MAXInt
	   cout<<"請輸入一條邊所依附的兩個頂點、權值:"<<endl;
 	for(k=1;k<=G.arcnum;k++){//構造鄰接矩陣 
  	cin>>v1>>v2>>w;//輸入一條邊所依附的頂點及邊的權值 
  	
  	int i=LocateVex(G,v1);
  	int j=LocateVex(G,v2);//確定v1和v2在G中的位置,即頂點數組的下標
  	 
  	G.arcs[i][j]=w; //邊<v1,v2>權值置爲w 
  	G.arcs[j][i]=G.arcs[i][j];
  //邊<v1,v2>的對稱邊<v2,v1>的權值爲w 
 }//for  
  	return true; 
}//CreateUDN  

void DFS(AMGraph G, int v)
{
	cout << v << " ";
	visited[v] = true;
	for(int w = 1; w <= G.vexnum; w ++ )
		if( (G.arcs[v][w] != 0 ) && (!visited[w]))
			DFS(G, w);
			//w是v的鄰接點,如果w未訪問,則遞歸調用DFS 
}
void BFS(AMGraph G, int v)
{
	for(int i = 1; i <= G.vexnum; i ++)
		visited[i] = false;
		
		cout << v << " ";
		
		visited[v] = true;
		
		queue<int> Q;
		Q.push(v);
		while(!Q.empty())
		{
			int t = Q.front();
			Q.pop();
			for(int w = 1; w <= G.vexnum; w ++ )
			{
				if(G.arcs[t][w] == 1 && visited[w] == false)
				{
					visited[w] = true;
					cout << w << " ";
					Q.push(w);
				}
			}
		}
}
int main()
{
 	AMGraph G;
 	CreateUDN(G);
 	cout<<"鄰接矩陣爲:"<<endl;
 	for(int i = 1; i <= G.vexnum;i ++)
 	{
  
	  for(int j = 1; j <= G.vexnum; j ++){
	   cout<<G.arcs[i][j]<<" ";
  	}
 	 cout << endl;
	}//for
	cout << "DFS遍歷鄰接矩陣結果爲:" << endl;
	DFS(G, 2);
	cout << endl;
	
	cout << "BFS遍歷鄰接矩陣結果爲: " <<endl; 
	BFS(G, 1);
	a
	return 0;
}

在這裏插入圖片描述

鄰接表的深搜與廣搜

#include<iostream>
#include<queue>
using namespace std; 
#define MVNum 100 //最大頂點數

bool visited[15];

typedef struct ArcNode{
 	int adjvex;  //該邊所指向的頂點的位置 
 	struct ArcNode *nextarc;//指向下一條邊的指針 
}ArcNode;

//頂點的結點結構 
typedef struct VNode{
 	char data;//頂點信息、
 	ArcNode *firstarc;//指向第一條依附該頂點的邊的指針 
}VNode,AdjList[MVNum];//AdjList表示鄰接表類型


//圖的結構定義 
typedef struct{
 	AdjList vertices; //定義一個數組vertices,是vertex的複數形式
 	int vexnum,arcnum; //圖的當前頂點數和弧數
}ALGraph;

int LocateVex(ALGraph G,int u){
 //在圖G中查找頂點u,存在則返回頂點表中的下標;否則返回-1
 	int i;
 	for(i=1;i<=G.vexnum;i++)
  	if(u == G.vertices[i].data)
   		return i;
  	return -1;
} 

//創建無向圖G 
bool CreateUDG(ALGraph &G){ 
 	

 	cout << "請輸入總結點數和總邊數:" << endl; 
 	cin>>G.vexnum>>G.arcnum;//輸入總頂點數,總邊數
 	cout << " 輸入各頂點值: " << endl; 
 	for(int i = 1;i <= G.vexnum;i++)
	{//輸入各頂點,構造表頭結點表 
  		cin>>G.vertices[i].data;//輸入頂點值 
  		G.vertices[i].firstarc=NULL;//初始化表頭結點的指針域
	}//for
	getchar();
 	//輸入各邊,構造鄰接表
 
 	cout << "輸入一條邊依附的兩個頂點值"<<endl; 
 	for(int k=1;k<=G.arcnum;k++){
 	char v1,v2;
 	cin>>v1>>v2;    //輸入一條邊依附的兩個頂點 
 	getchar();
 	
 	int i=LocateVex(G,v1);
 	int j=LocateVex(G,v2); //確定頂點在G.vertices中的序號
 	ArcNode *p1=new ArcNode;  //生成一個新的邊結點*p1
  	p1->adjvex=j;  //鄰接點序號爲j 
  //頭插法將新結點*p1插入頂點vi的邊表頭部 
 	p1->nextarc=G.vertices[i].firstarc;
 	G.vertices[i].firstarc=p1; 
 	ArcNode *p2=new ArcNode;
 	p2->adjvex=i;  //鄰接點序號爲i
 	//頭插法插入p2 ,因爲是無向網,所以是兩條 
 	p2->nextarc=G.vertices[j].firstarc;
 	G.vertices[j].firstarc=p2; 
 }//for
  return true; 
}//CreateUDG


void DFS(ALGraph G, int v)
{
	ArcNode *p;
	p = new ArcNode;
	 
	cout << v << " ";
	
	visited[v] = true;
	
	p = G.vertices[v].firstarc;
	while(p != NULL)
	{
		int w = p->adjvex;
		if(!visited[w]) 
			DFS(G, w);
		p = p->nextarc;
	}
}

void BFS(ALGraph G, int v)
{
	int i = 0;
	for(int i = 1; i <= G.vexnum; i++)
		visited[i] = false;
		
	cout << v << " ";
	visited[v] = true; 
	queue<int> Q;
	Q.push(v);
	ArcNode *p;
	p = new ArcNode;
	while(!Q.empty())
	{
		int t = Q.front();
		
		Q.pop();
		
		for(p = G.vertices[t].firstarc; p != NULL;p = p->nextarc)
		{
			if(! visited[p->adjvex])
			{
				cout << p->adjvex << " ";
				visited[p->adjvex] = true;
				Q.push(p->adjvex);
			}
		}
	}
}

int main()
{
	ALGraph G;
	ArcNode *p;
	CreateUDG(G);
	
	cout << "輸出鄰接表: " <<endl;
	
	for(int i = 1; i<= G.vexnum; i++)
	{
		cout << G.vertices[i].data;
		for(p = G.vertices[i].firstarc; p != NULL; p = p->nextarc)
			printf("->%d", p->adjvex);
		cout << endl; 
	} 
		cout << endl;
		
		cout << "DFS遍歷結果:" << endl;
		DFS(G, 2);
		cout << endl;
		
		cout << " BFS遍歷結果:" << endl;
		BFS(G, 1);
		
		return 0;
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章