1. 程式人生 > >《資料結構與演算法那》第七次 廣度、深度優先遍歷 圖及圖的遍歷(下)

《資料結構與演算法那》第七次 廣度、深度優先遍歷 圖及圖的遍歷(下)

《資料結構與演算法那》第七次課實驗內容

圖及圖的遍歷(下)

實驗目的:

  1. 熟悉圖的兩種儲存結構:鄰接矩陣和鄰接連結串列。
  2. 掌握在圖的鄰接表儲存結構上的遍歷演算法的實現。

實驗內容:

  1. 在已經開發好的c++類adjacencyGraph中,新增兩個成員函式,BFSpanningTree和DFSspanningTree分別輸出該圖的廣度優先生成樹和深度優先生成樹。
  2. 在已經開發好的c++類linkedGraph中,新增兩個成員函式,BFSpanningTree和DFSpanningTree分別輸出該圖的廣度優先生成樹和深度優先生成樹。
  3. 兩個儲存方式任選其一完成。

江米條想說的話:

(用的是臨界陣列,這個題連結串列比矩陣更簡單,矩陣都會了,還怕連結串列該幹什麼)

這次的程式碼和上次的程式碼幾乎一樣,就多了兩個函式而已。沒看明白的看我寫的《資料結構與演算法》第六次去。。。。

下面我給大家講一下這兩個演算法:BFS(廣度優先)和DFS(深度優先)

廣度優先BFS (你們記住Breadth就行):

簡單地說:廣度的意思就是一層一層的遍歷。

看圖:

從A點開始訪問順序:A->B->D->E->C->F->G

廣度遍歷是:

1:訪問A

2:訪問B,D,E(B,D,E都是A的鄰接點,按照順序訪問)

3:訪問C(訪問B的鄰接點C,訪問完了C點之後,開始從D,E找)

4:訪問F(因為D的鄰接點沒有,所以從B,D,E中的E點開始找E的下一個,即F)

5:訪問G(訪問F的下一個G)

6:G點之後沒有了,往上找發現F也沒未訪問的子節點了,在往上也發現:E也沒有未訪問的子節點了(B,D,E都沒了),所以再往上看A也沒有未訪問的子節點了,至此,訪問結束。

 

深度優先DFS (你們記住Depth就行):

簡單地說:深度就是沿著一條路走到底,走完了再折回來走其他的路。

看圖:

從A點開始訪問的順序:A->B->C->D->E->F->G

深度遍歷是:(鄰接連結串列)

1: 訪問A

2: 訪問B(在這個過程裡面,A的鄰接點有B、D、E,但是B的順序在前面,所以先訪問B)

3: 訪問C(在這個過程裡面,B的鄰接點有C、D,但是C的順序在前面,所以先訪問C)

4: 訪問D(C之後沒鄰接點了,所以往上倒一層,找B的另一個鄰接點D)

5: 訪問E(D之後沒鄰接點了,所以往上倒一層,B之後的點都被訪問了,再往上倒一層,找A的另一個鄰接點E

6: 訪問F(E的下一個是F)

7: 訪問G(F的下一個是G)

8: G訪問沒了,往上倒一層到了F,F的鄰接點都被訪問了,再往上倒一層到了E,E的鄰接點都被訪問了,再再往上倒一層到了A,A的鄰接點也都被訪問了,至此,訪問結束

 

標頭檔案:

#include<iostream>
using namespace std;

class adjacencyGraph
{
public:
	adjacencyGraph(int n, int e);
	void setElement(int n, int value);
	int getIndex(int value);
	void insertEdge(int vertex1, int vertex2);
	void eraseEdge(int vertex1, int vertex2);
	void BFSpanningTree(int v);
	void DFSpanningTree(int v);
	void dfs(int v);
	void outputGraph();
private:
	int **matrix;
	int *element;
	int numberOfVertices;
	int numberOfEdges;
	int *reach = new int[numberOfVertices];
	int count = 0;
};
adjacencyGraph::adjacencyGraph(int n, int e)
{
	numberOfVertices = n;
	numberOfEdges = e;
	matrix = new int *[numberOfVertices];
	for (int i = 0; i < numberOfVertices; i++)
		matrix[i] = new int[numberOfVertices];
	for (int i = 0; i < numberOfVertices; i++)
		for (int j = 0; j < numberOfVertices; j++)
			matrix[i][j] = 0;
	element = new int[numberOfVertices];
}
void adjacencyGraph::setElement(int n, int value)
{
	element[n - 1] = value;
}
int adjacencyGraph::getIndex(int value)
{
	for (int i = 0; i < numberOfVertices; i++)
		if (element[i] == value)
			return i;
}
void adjacencyGraph::insertEdge(int vertex1, int vertex2)
{
	matrix[vertex1][vertex2] = 1;
	matrix[vertex2][vertex1] = 1;
}
void adjacencyGraph::eraseEdge(int vertex1, int vertex2)
{
	matrix[vertex1][vertex2] = 0;
	matrix[vertex2][vertex1] = 0;
}
void adjacencyGraph::BFSpanningTree(int v)
{
	int l = 0, r = 1;
	for (int i = 0; i < numberOfVertices; i++)
		reach[i] = NULL;
	reach[0] = v;
	while (reach[numberOfVertices - 1] == NULL)
	{
		int tl = l, tr = r;
		l = r;
		for (tl; tl < tr; tl++)
		{
			int index = getIndex(reach[tl]);
			for (int j = 0; j < numberOfVertices; j++)
				if (matrix[index][j] == 1)
				{
					int k;
					for (k = 0; k < r; k++)
						if (element[j] == reach[k])
							break;
					if (k == r)
					{
						reach[r] = element[j];
						r++;
					}
				}
		}
	}
	cout << "這個無向圖的廣度優先搜尋為:";
	for (int i = 0; i < numberOfVertices; i++)
		cout << reach[i];
	cout << endl;
}
void adjacencyGraph::DFSpanningTree(int v)
{
	for (int i = 0; i < numberOfVertices; i++)
		reach[i] = NULL;
	reach[0] = v;
	dfs(v);
	for (int i = 0; i < numberOfVertices; i++)
		cout << reach[i];
	cout << endl;
}
void adjacencyGraph::dfs(int v)
{
	int index = getIndex(v);
	for (int i = 0; i < numberOfVertices; i++)
		//if(reach[i]==0)
		if (matrix[index][i] == 1)
		{
			int k;
			for (k = 0; k < count; k++)
				if (element[i] == reach[k])
					break;
			if (k == count)
			{
				bool t = false;//設定這個變數是為了防止出現從父結點再次遍歷到子節點的情況,比如兩個父結點都連著一個子節點。
				for(int a=0;a<count+1;a++)
					if (element[i] == reach[a])
					{
						t = true;
						break;
					}
				if (t == false)
				{
					count++;
					reach[count] = element[i];
					dfs(reach[count]);
				}
			}
		}
}
void adjacencyGraph::outputGraph()
{
	for (int i = 0; i < numberOfVertices; i++)
	{
		for (int j = 0; j < numberOfVertices; j++)
			cout << matrix[i][j] << " ";
		cout << endl;
	}
}

主函式:

#include<iostream>
#include"adjacencyGraph.h"
using namespace std;
int main()
{
	adjacencyGraph *temp;
	temp = new adjacencyGraph(0, 0);
	while (1)
	{
		cout << "1.用鄰接矩陣描述一個無向圖" << endl;
		cout << "2.刪除無向圖的一條邊" << endl;
		cout << "3.對無向圖廣度優先搜尋"<<endl;
		cout<< "4.對無向圖深度優先搜尋"<<endl;
		cout << "0.退出" << endl;
		int option;
		cin >> option;
		switch (option)
		{
		case 1:
			{
				int n, e;
				cout << "請輸入頂點的數目:";
				cin >> n;
				cout << "請輸入邊的數目:";
				cin >> e;
				temp = new adjacencyGraph(n, e);
				for (int i = 1; i <= n; i++)
				{
					int value;
					cout << "請輸入第" << i << "個頂點";
					cin >> value;
					temp->setElement(i, value);
				}
				for (int i = 1; i <= e; i++)
				{
					int value1, value2;
					cout << "請輸入第" << i << "條邊的第1個頂點:";
					cin >> value1;
					cout << "請輸入第" << i << "條邊的第2個頂點:";
					cin >> value2;
					temp->insertEdge(temp->getIndex(value1), temp->getIndex(value2));
				}
				temp->outputGraph();
			}
			break;
		case 2:
			{
				int value1, value2;
				cout << "請輸入要刪除邊的第一個頂點:";
				cin >> value1;
				cout << "請輸入要刪除邊的第二個頂點:";
				cin >> value2;
				temp->eraseEdge(temp->getIndex(value1), temp->getIndex(value2));
				temp->outputGraph();
			}
			break;
		case 3:
			{
				int v;
				cout<< "請輸入搜尋的起點值:";
				cin>>v;
				temp->BFSpanningTree(v);
			}
			break;
		case 4:
		{
			int v;
			cout << "請輸入搜尋的起點值:";
			cin >> v;
			temp->DFSpanningTree(v);
		}
		break;
		case 0:
			return 0;
		default:
			break;
		}
	}
}

呼,結束了,打字畫圖真的好累好累的。

程式碼就這兩個檔案,上面的是標頭檔案,下面的是主函式。就不上傳連結啦!

如果有問題請聯絡我 QQ:1239825268

備註:CSDN

共勉!