無向圖的深度優先搜索與廣度優先搜索

圖的簡述:

圖是一種複雜的數據結構,圖(Graph)是由頂點(Vertex)組成的非空有窮集合和頂點之間的邊(Edge)組成。

圖的邊可以由權值(weight),也可以沒有,有權值的圖稱爲網圖。

圖的邊也可以有方向,沒有方向的爲無向圖,有方向的爲有向圖。

圖很複雜,就需要複雜的方式來表示圖,一般簡單的使用鄰接矩陣和鄰接表來表示,還有十字鏈表和鄰接多重表等,這裏只介紹前兩種的實現。

無向圖的鄰接矩陣結構表示:

鄰接矩陣簡單也方便理解,即用一個一維數組儲存頂點,用另一個二維數組儲存各個頂點之間的邊的信息。

無向圖的鄰接矩陣是一個對稱矩陣,即arc[i][j]=arc

C++實現:

typedef char VertexType;        //頂點類型 ,默認爲char
typedef int EdgeType;              //邊的權值  默認int
#define MAXVERTEX 100          //最大的頂點數

//鄰接矩陣的結構
typedef struct MGraph
{
	VertexType vexs[MAXVERTEX];     //頂點數組
	EdgeType arc[MAXVERTEX][MAXVERTEX];    //鄰接矩陣  即邊數組
	int vertexNum;            //頂點數
	int edgeNum;                 //邊數
};

無向鄰接矩陣的深度優先遍歷:

深度優先所搜(DepthFirstSearch)表示用某種規則把一個頂點所連接的後面頂點都遍歷一遍,並用一個標識符來表示是否遍歷過該節點。特點是不放過任何一個節點。從一個節點出發,遍歷所有未訪問的節點,結束後如果遍歷完後仍有節點未被訪問,則換一個節點作爲起始點,重複此步驟直至所有節點都被訪問。

bool visited[MAXVERTEX];
//深度優先遍歷鄰接矩陣
void DFSTraverse(MGraph G)
{
	int i;
	for (i = 0; i < G.vertexNum; i++)
	{
		visited[i] = false;
	}
	for (i = 0; i < G.vertexNum; i++)
	{
		if (visited[i] != true)
		{
			DepthFirstSearch(G, i);  //如果該頂點延伸出去所有頂點都訪問過,則訪問下一個頂點
		}
	}
}

DepthFirstSearch函數用遞歸實現:

//深度優先搜索鄰接矩陣
void DepthFirstSearch(MGraph G,int i)
{
	int j;
	visited[i] = true;      //把該頂點標識符置爲true
	cout << G.vexs[i];      //遍歷到後打印該頂點
	for (j = 0; j < G.vertexNum; j++)
	{
		if (G.arc[i][j] == 1 && visited[j] != true)
		{
			DepthFirstSearch(G, j);      //遞歸遍歷未訪問的節點直到沒有
		}
	}
}

無向鄰接矩陣的廣度優先遍歷:

//廣度優先遍歷鄰接矩陣
void BFSTraverse(MGraph G)
{
	int i, j;
	queue<VertexType> q;              //臨時隊列
	for (i = 0; i < G.vertexNum; i++)
	{
		visited[i] = false;
	}
	for (i = 0; i < G.vertexNum; i++)
	{
		if (!visited[i])
		{
			visited[i] = true;      //標識符設爲true
			cout << G.vexs[i];       //遍歷到該頂點,打印頂點
			q.push(G.vexs[i]);         //入隊
			while (q.empty() != true)     //如果隊列不爲空
			{
				q.pop();
				for (j = 0; j < G.vertexNum; j++)
				{
					if (G.arc[i][j] == 1 && !visited[j])
					{
						visited[j] = true;
						cout << G.vexs[j];      //遍歷並打印
						q.push(G.vexs[j]);
					}
				}
			}
		}
	}
}

無向圖的鄰接表結構表示:

鄰接表類似於鏈表,存在頂點節點和邊節點,用頂點節點的指針指向該頂點所連接的邊節點。

//鄰接表的結構
typedef struct EdgeNode         //邊表節點
{
	int adjvex;               //該鄰接點對應的頂點下標
	EdgeType weight;       //頂點到該鄰接點的權值
	EdgeNode *Next;       //指向頂點的下一個鄰接點
};

typedef struct VertexNode      //頂點表節點
{
	VertexType data;            //頂點節點及信息
	EdgeNode *firstEdge;         //邊表頭指針,指向頂點的第一個邊表
}AdjList[MAXVERTEX];

typedef struct GraphAdjList          //鄰接表
{
	AdjList adjList;       //頂電錶數組
	int vertexNum;        //頂點數
	int EdgeNum;           //邊數
};
無向網圖鄰接表的創建:

//無向圖的鄰接表的創建
void CreateALGraph(GraphAdjList *G)
{
	int i, j, k;
	EdgeNode *e;
	cout << "輸入頂點數和邊數:";
	cin >> G->vertexNum >> G->EdgeNum;    //讀入頂點數和邊數
	//創建頂點表
	for (i = 0; i < G->vertexNum; i++)
	{
		cin >> G->adjList[i].data;  //讀入頂點節點信息
		G->adjList[i].firstEdge = NULL;  //邊表初始化爲NULL表
	}
	//創建邊表
	for (k = 0; k < G->EdgeNum; k++)
	{
		cout << "輸入邊(vi,vj)上的頂點序號:" << endl;
		cin >> i >> j;    //讀入邊的頂點序號
		e = new EdgeNode();      //生成邊表節點
		//無向圖,所以一條邊對應兩個節點i和j
		//頭插法
		e->adjvex = j;       //鄰接點下標爲j
		e->Next = G->adjList[i].firstEdge;     //e指向G的firstedge
		G->adjList[i].firstEdge = e;            //firstEdge指向該邊節點

		e = new EdgeNode();
		e->adjvex = i;
		e->Next = G->adjList[j].firstEdge;
		G->adjList[j].firstEdge = e;
	}
}

無向鄰接表的深度優先遍歷:

和鄰接矩陣的遍歷很相似

//深度優先遍歷鄰接表
void DepthFirstSearchAdjList(GraphAdjList GAL, int i)
{
	EdgeNode *e;
	visited[i] = true;         //標識符設爲true
	cout << GAL.adjList[i].data;        //遍歷到後打印頂點信息
	e = GAL.adjList[i].firstEdge;
	while (e)
	{
		if (!visited[e->adjvex])
		{
			DepthFirstSearchAdjList(GAL, e->adjvex);   //遞歸遍歷未訪問的鄰接點
		}
		e = e->Next;
	}
}
//深度優先搜索鄰接表
void DFSTraverse(GraphAdjList GAL)
{
	int i;
	for (i = 0; i < GAL.vertexNum; i++)
	{
		visited[i] = false;
	}
	for (i = 0; i < GAL.vertexNum; i++)
	{
		if (!visited[i])
		{
			DepthFirstSearchAdjList(GAL, i);
		}
	}
}

無向鄰接表的廣度優先遍歷:

//廣度優先遍歷鄰接表
void BFSTraverse(GraphAdjList GAL)
{
	int i;
	EdgeNode *p;
	queue<int> q;
	for (i = 0; i < GAL.vertexNum; i++)
	{
		visited[i] = false;
	}
	for (i = 0; i < GAL.vertexNum; i++)
	{
		if (!visited[i])
		{
			visited[i] = true;
			cout << GAL.adjList[i].data<< endl;
			q.push[GAL.adjList[i]];
			while (q.empty() != true)
			{
				q.pop();
				p = GAL.adjList[i].firstEdge;
				while (p)
				{
					if (!visited[p->adjvex])
					{
						visited[p->adjvex] = true;
						cout << GAL.adjList[p->adjvex].data;
						q.push(p->adjvex);
					}
					p = p->Next;
				}
			}
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章