1. 程式人生 > >無向圖的深度優先遍歷

無向圖的深度優先遍歷

描述

    簡單介紹一下圖,圖就是由一些小圓點(稱為頂點)和連線這些小圓點的直線(稱為邊)組成的。例如下圖的由五個頂點(編號1、2、3、4、5)和五條邊(1-2、1-3、1-5、2-4、3-5)組成

    現在從1號頂點開始遍歷這個圖,遍歷是指把圖的每一個頂點都訪問一次。使用深度有限搜尋來遍歷這個圖將會得到如下結果。

    這五個頂點的訪問順序如下圖

    使用深度優先搜尋來遍歷這個圖的過程具體是:首先以一個未被訪問過的頂點為起始頂點,沿當前頂點的邊走到未訪問過的頂點:當沒有未訪問的頂點時,則回到上一個頂點,繼續試探訪問別的頂點,直到所有的頂點都被訪問過。顯然,深度優先遍歷是沿著圖的某一條分支遍歷直到末端,然後回溯,在沿著另一條進行同樣的遍歷,直到所有的頂點都被訪問過為止。

思路

    首先用一個二維陣列e來儲存無向圖,如下

    上圖中第 i 行 j 列表示頂點 i 到頂點 j 是否有邊。1 表示有邊,正無窮表示沒有邊,0 表示自己到自己。

    這種儲存方法為鄰接矩陣的儲存方法

    因為是無向圖,所以上面的二維陣列是沿對角線堆成的

程式碼塊

深度優先演算法程式碼

void dfs(int cur)
{
	int i = 0;
	printf("%d ", cur);//輸出當前點

	sum++;
	if (sum == n)//如果訪問完所有的點則返回
	{
		return;
	}

	for (i = 1; i <= n; i++)
	{
		if (e[cur][i] == 1 && book[i] == 0)//如果cur結點到i結點可以連線則標記為已經訪問
		{									//且遞迴訪問i結點
			book[i] = 1;
			dfs(i);
		}
	}
	return;
}

     cur 儲存的是當前正在遍歷的頂點,二維陣列 e 儲存的就是鄰接矩陣,陣列 book 用來記錄哪些頂點是遍歷過的,sum 用來記錄遍歷了多少個頂點,n 為頂點的總個數

原始碼

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>

/*
* 使用深度優先搜尋來遍歷一個無向圖
* 郭文峰
* 2018/10/17
*/
int n, m, sum;
int book[101], e[101][101];

void dfs(int cur)
{
	int i = 0;
	printf("%d ", cur);//輸出當前點

	sum++;
	if (sum == n)//如果訪問完所有的點則返回
	{
		return;
	}

	for (i = 1; i <= n; i++)
	{
		if (e[cur][i] == 1 && book[i] == 0)//如果cur結點到i結點可以連線則標記為已經訪問
		{									//且遞迴訪問i結點
			book[i] = 1;
			dfs(i);
		}
	}
	return;
}

int main(void)
{
	int i = 0;
	int j = 0;
	int a = 0;
	int b = 0;
	
	//用一個二維陣列e[][]來儲存一個無向圖
	//輸入這個無向圖共有幾個數字
	scanf("%d%d", &n, &m);

	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= m; j++)
		{
			if (i == j)
			{
				e[i][j] = 0;		//二維陣列中用0代表自己到自己
			}
			else
			{
				e[i][j] = 999999999; //二維陣列中用999999999來表示正無窮
			}
		}
	}

	for (i = 1; i <= n; i++)
	{
		scanf("%d%d", &a, &b);
		e[a][b] = 1;
		e[b][a] = 1; //因為是無向圖,所以雙向都等於1
	}

	book[1] = 1;//1號標記已經訪問
	dfs(1);//從1號頂點開始遍歷

	system("pause");
	return 0;
}