1. 程式人生 > >有向圖(網)、無向圖(網)的構造以及遍歷

有向圖(網)、無向圖(網)的構造以及遍歷

構造圖採用的是鄰接表的方法,然後採用深度和廣度優先進行遍歷。(博主第一次寫構造方法的時候花了很久寫的很冗雜,雖然也實現了,但是感覺到處都在打補丁,拼拼湊湊寫出來的,後來用了一分鐘重寫了一個,秒通過!!!欲哭無淚啊~原因主要是因為不同的輸入格式導致的,以後些其他程式碼的時候要慎重考慮輸入的格式問題)

下面貼程式碼!

根據書上的虛擬碼,寫出定義的結構

const int MAX_VERTEX_NUM = 20;
bool visited[MAX_VERTEX_NUM];    //遍歷訪問標誌

typedef struct ArcNode{
	int adjvex;    //該弧所指向的頂點的位置
	struct ArcNode *nextarc;    //指向下一條弧(邊)的指標
	int weight;    //該弧(邊)的權值
}ArcNode;

typedef struct VNode{
	char data;    //頂點資訊
	ArcNode *firstarc;    //指向第一條依附該頂點的弧(邊)的指標
}VNode,AdjList[MAX_VERTEX_NUM];

typedef struct{
	AdjList vertices;    
	int vexnum, arcnum;    //圖的當前頂點數和弧(邊)數
	int kind;
}ALGraph;

根據書上的虛擬碼,寫出三個要用到的方法
//返回頂點v在圖G中的位置
int LocateVex(ALGraph G, char v)
{
	for (int i = 0; i < G.vexnum; i++){
		if (v == G.vertices[i].data)
			return i;
	}
	return -1;
}

//返回v的第一個鄰接頂點
int FirstAdjVex(ALGraph G, int v)
{
	if (G.vertices[v].firstarc)
		return G.vertices[v].firstarc->adjvex;
	return -1;
}

//返回頂點v相對於鄰接點w的下一個鄰接點
int NextAdjVex(ALGraph G, int v, int w)
{
	ArcNode *p;
	p = G.vertices[v].firstarc;
	if (p){
		while (p){
			if (w == p->adjvex){
				if (nullptr == p->nextarc)
					return -1;
				else
					return p->nextarc->adjvex;
			}
			p = p->nextarc;
		}
	}
	return -1;
}

下面是本體,一分鐘改寫出的構造圖的方法!
//採用鄰接表構造圖G
void CreateGraph(ALGraph &G)
{
	int i, j, weight;
	char v, v1, v2;
	ArcNode *p, *q = nullptr;
	cout << "請輸入圖型別的序號:\n1.DG(有向圖)\n2.DN(有向網\n3.UDG(無向圖)\n4.UDN(無向網)" << endl;
	cin >> G.kind;
	cout << "請輸入圖G的頂點數和弧(邊)數:";
	cin >> G.vexnum >> G.arcnum;
	//構造鄰接表
	for (i = 0; i < G.vexnum; i++){
		cout << "請輸入頂點vex[" << i << "]的值:";
		cin >> G.vertices[i].data;
		G.vertices[i].firstarc = nullptr;
	}
	cout << endl;
	for (j = 0; j < G.arcnum; j++){
		cout << "請輸入第" << j << "條弧(邊)的兩個端點:";
		cin >> v1 >> v2;
		q = G.vertices[LocateVex(G, v1)].firstarc;
		p = new ArcNode;
		p->adjvex = LocateVex(G, v2);
		p->nextarc = nullptr;
		if (1 == G.kind || 3 == G.kind)
			p->weight = 1;
		else{
			cout << "請輸入該弧(邊)的權值:";
			cin >> weight;
			p->weight = weight;
		}

		if (q){
			while (q->nextarc)
				q = q->nextarc;
			q->nextarc = p;
		}
		else
			G.vertices[LocateVex(G, v1)].firstarc = p;

		if (3 == G.kind || 4 == G.kind){
			q = G.vertices[LocateVex(G, v2)].firstarc;
			p = new ArcNode;
			p->adjvex = LocateVex(G, v1);
			p->nextarc = nullptr;
			if (1 == G.kind || 3 == G.kind)
				p->weight = 1;
			else{
				p->weight = weight;
			}

			if (q){
				while (q->nextarc)
					q = q->nextarc;
				q->nextarc = p;
			}
			else
				G.vertices[LocateVex(G, v2)].firstarc = p;
		}
	}
}

根據書上的虛擬碼,寫出深度優先遍歷的遞迴方法
//深度優先遍歷(遞迴)
void DFS(ALGraph G, int v)
{
	visited[v] = true;
	cout << G.vertices[v].data << " ";
	for (int i = FirstAdjVex(G, v); i >= 0; i = NextAdjVex(G, v, i)){
		if (!visited[i])
			DFS(G, i);
	}
}

void DFSTraverse(ALGraph G)
{
	int i;
	cout << "深度優先結果:" << endl;
	for (i = 0; i < G.vexnum; i++)
		visited[i] = false;
	for (i = 0; i < G.vexnum; i++){
		if (!visited[i])
			DFS(G, i);
	}
	cout << endl;
}

列印函式在測試的時候不可少
//列印鄰接表
void PrintALGraph(ALGraph G)
{
	ArcNode *p;
	for (int i = 0; i < G.vexnum; i++){
		cout << G.vertices[i].data;
		if (G.vertices[i].firstarc){
			p = G.vertices[i].firstarc;
			while (p){
				if (3 == G.kind || 4 == G.kind)
					cout << " - " << G.vertices[p->adjvex].data;
				else
					cout << "→" << G.vertices[p->adjvex].data;
				p = p->nextarc;
			}
		}
		cout << endl;
	}
}

最後配上主函式
int main()
{
	ALGraph graph;
	CreateGraph(graph);
	PrintALGraph(graph);
	DFSTraverse(graph);

	system("pause");
	return 0;
}