1. 程式人生 > >圖——鄰接表表示(實現深度優先遍歷、廣度優先遍歷)

圖——鄰接表表示(實現深度優先遍歷、廣度優先遍歷)

程式碼有部分解析:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<iomanip>
using namespace std;

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAX_VERTEX_NUM 20//最大頂點個數

typedef int Status;
typedef int InfoType;
typedef char VertexType;

bool visited[MAX_VERTEX_NUM];

typedef struct ArcNode {
	int adjvex;//該弧所指向的頂點位置
	struct ArcNode *nextarc;//指向下一條弧的指標
	InfoType info;//該弧相關資訊的指標
}ArcNode;


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

typedef struct {
	AdjList vertices;
	int vexnum, arcnum;//圖的當前頂點數和弧數
	int kind;//圖的種類標誌
}ALGraph;

int LocateVex(ALGraph G, char v)
{
	int i;
	for (i = 0; i < G.vexnum; i++)
	{
		if (G.vertices[i].data == v)
			return i;
	}
	return -1;
}
/*
   採用鄰接表儲存表示,構造無向圖G
*/
Status CreateUDG(ALGraph &G)
{
	int i, j, k, IncInfo;
	ArcNode *pi, *pj;
	char v1, v2;
	cout << "輸入頂點數G.vexnum:";
	cin >> G.vexnum;
	cout << "輸入邊數G.arcnum:";
	cin >> G.arcnum;
	getchar();
	for (i = 0; i < G.vexnum; ++i)
	{
		cout << "輸入頂點G.vertices[" << i << "].data:";
		cin >> G.vertices[i].data;
		getchar();
		//初始化連結串列頭指標為空
		G.vertices[i].firstarc = NULL;
	}
	/*
	   輸入各邊並構造鄰接表
	*/
	for (k = 0; k < G.arcnum; ++k)
	{
		cout << "請輸入第" << k + 1 << "條邊的兩個頂點:"<<endl;
		//輸入一條邊的起點和終點
		cin >> v1;
		cin >> v2;
		getchar();
		//確定V1和V2在G中的位置
		i = LocateVex(G, v1);
		j = LocateVex(G, v2);
		if (!(pi = (ArcNode *)malloc(sizeof(ArcNode))))
			exit(OVERFLOW);
		//對弧結點賦鄰接點"位置"資訊
		pi->adjvex = j;
		pi->info = 0;
		//插入連結串列G.vertices[i]
		pi->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = pi;
		
		if (!(pj = (ArcNode *)malloc(sizeof(ArcNode))))
			exit(OVERFLOW);
		//對弧結點賦鄰接點"位置"資訊
		//插入連結串列G.vertices[j]
		pj->adjvex = i;
		pj->info = 0;
		pj->nextarc = G.vertices[j].firstarc;
		G.vertices[j].firstarc = pj;
	}//for
	return OK;
}//CreateUDG

//有向圖
Status CreateDG(ALGraph &G)
{
	int i, j, k, IncInfo;
	ArcNode *pi, *pj;
	char v1, v2;
	cout << "輸入頂點數G.vexnum:";
	cin >> G.vexnum;
	cout << "輸入邊數G.arcnum:";
	cin >> G.arcnum;
	getchar();
	for (i = 0; i < G.vexnum; ++i)
	{
		cout << "輸入頂點G.vertices[" << i << "].data:";
		cin >> G.vertices[i].data;
		getchar();
		//初始化連結串列頭指標為空
		G.vertices[i].firstarc = NULL;
	}
	/*
	輸入各邊並構造鄰接表
	*/
	for (k = 0; k < G.arcnum; ++k)
	{
		cout << "請輸入第" << k + 1 << "條邊的兩個頂點:" << endl;
		//輸入一條邊的起點和終點
		cin >> v1;
		cin >> v2;
		getchar();
		//確定V1和V2在G中的位置
		i = LocateVex(G, v1);
		j = LocateVex(G, v2);
		if (!(pi = (ArcNode *)malloc(sizeof(ArcNode))))
			exit(OVERFLOW);
		//對弧結點賦鄰接點"位置"資訊
		pi->adjvex = j;
		pi->info = 0;
		//插入連結串列G.vertices[i]
		pi->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = pi;
	}//for
	return OK;
}//CreateDG
//有向網
Status CreateDN(ALGraph &G)
{
	int i, j, k, IncInfo;
	ArcNode *pi, *pj;
	char v1, v2;
	cout << "輸入頂點數G.vexnum:";
	cin >> G.vexnum;
	cout << "輸入邊數G.arcnum:";
	cin >> G.arcnum;
	cout << "輸入是否有Info資訊(0、沒有,1、有)";
	cin >> IncInfo;
	getchar();
	for (i = 0; i < G.vexnum; ++i)
	{
		cout << "輸入頂點G.vertices[" << i << "].data:";
		cin >> G.vertices[i].data;
		getchar();
		//初始化連結串列頭指標為空
		G.vertices[i].firstarc = NULL;
	}
	/*
	輸入各邊並構造鄰接表
	*/
	for (k = 0; k < G.arcnum; ++k)
	{
		cout << "請輸入第" << k + 1 << "條邊的兩個頂點和相連邊的權值:" << endl;
		//輸入一條邊的起點和終點
		cin >> v1;
		cin >> v2;
		cin >> IncInfo;
		getchar();
		//確定V1和V2在G中的位置
		i = LocateVex(G, v1);
		j = LocateVex(G, v2);
		if (!(pi = (ArcNode *)malloc(sizeof(ArcNode))))
			exit(OVERFLOW);
		//對弧結點賦鄰接點"位置"資訊
		pi->adjvex = j;
		//插入連結串列G.vertices[i]
		pi->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = pi;
		
		pi->info = IncInfo;
	}//for
	return OK;
}//CreateDN
//無向網
Status CreateUDN(ALGraph &G)
{
	int i, j, k, IncInfo;
	ArcNode *pi, *pj;
	char v1, v2;
	cout << "輸入頂點數G.vexnum:";
	cin >> G.vexnum;
	cout << "輸入邊數G.arcnum:";
	cin >> G.arcnum;
	cout << "輸入是否有Info資訊(0、沒有,1、有)";
	cin >> IncInfo;
	getchar();
	for (i = 0; i < G.vexnum; ++i)
	{
		cout << "輸入頂點G.vertices[" << i << "].data:";
		cin >> G.vertices[i].data;
		getchar();
		//初始化連結串列頭指標為空
		G.vertices[i].firstarc = NULL;
	}
	/*
	輸入各邊並構造鄰接表
	*/
	for (k = 0; k < G.arcnum; ++k)
	{
		cout << "請輸入第" << k + 1 << "條邊的兩個頂點和相連邊的權值:" << endl;
		//輸入一條邊的起點和終點
		cin >> v1;
		cin >> v2;
		cin >> IncInfo;
		getchar();
		//確定V1和V2在G中的位置
		i = LocateVex(G, v1);
		j = LocateVex(G, v2);
		if (!(pi = (ArcNode *)malloc(sizeof(ArcNode))))
			exit(OVERFLOW);
		//對弧結點賦鄰接點"位置"資訊
		pi->adjvex = j;
		//插入連結串列G.vertices[i]
		pi->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = pi;
		pi->info = IncInfo;
		if (!(pj = (ArcNode *)malloc(sizeof(ArcNode))))
			exit(OVERFLOW);
		//對弧結點賦鄰接點"位置"資訊
		pj->adjvex = i;
		//插入連結串列G.vertices[i]
		pj->nextarc = G.vertices[j].firstarc;
		G.vertices[j].firstarc = pi;
		pj->info = IncInfo;
	}//for
	return OK;
}//CreateUDN


Status CreateGraph(ALGraph &G)
{
	cout << "請輸入圖的種類:0表示DG,1表示DN,2表示UDG,3表示UDN" << endl;
	cin >> G.kind;
	switch (G.kind)
	{
	case 0:
		return CreateDG(G);
	case 1:
		return CreateDN(G);
	case 2:
		return CreateUDG(G);
	case 3:
		return CreateUDN(G);
	default:
		return ERROR;
	}
}

void list(ALGraph G)
{
	int i;
	ArcNode *p;
	cout << "輸出鄰接表((0)代表無權值):" << endl;
	for (i = 0; i < G.vexnum; ++i)
	{
		cout << i << ":" << G.vertices[i].data;
		p = G.vertices[i].firstarc;
		while (p)
		{
			cout << setw(3) << p->adjvex;
			cout << "(" <<p->info<< ")";
			p = p->nextarc;
		}
		cout << endl;
	}
}


void DFS(ALGraph G, int v)
{
	ArcNode *p;
	int w;
	visited[v] = TRUE;
	cout << G.vertices[v].data << " ";
	
	for (p = G.vertices[v].firstarc; p; p = p->nextarc)
	{
		w = p->adjvex;
		if (!visited[w])//對v的尚未訪問的鄰接頂點w遞迴呼叫DFS
			DFS(G, w);
	}
}
//深度優先遍歷
void DFSTraverse(ALGraph G)
{
	int v;
	for (v = 0; v < G.vexnum; ++v)
	{
		visited[v] = FALSE;
	}
	for (v = 0; v < G.vexnum; ++v)
	{
		if (!visited[v])
		{
			DFS(G, v);
			cout << endl;
		}
	}
}

void BFSTraverse(ALGraph G)
{
	int v,w;
	//輔助佇列
	int front=0, rear = 0;
	VNode Queue[MAX_VERTEX_NUM];
	ArcNode *p;

	//初始化標誌陣列
	for (v = 0; v < G.vexnum; ++v)
	{
		visited[v] = FALSE;
	}
	for (v = 0; v < G.vexnum; ++v)
	{
		if (!visited[v])//v尚未訪問
		{
			visited[v] =true;
			cout << G.vertices[v].data<<" ";
			Queue[++rear] = G.vertices[v];//v入佇列
			while (front != rear)//判斷佇列是否為空
			{
				VNode u = Queue[++front];//隊頭元素出佇列,並等於u
				cout << endl;
				/*
				判斷該結點的後序表結點,存在即輸出,入佇列
				*/
				for (p = u.firstarc; p; p = p->nextarc)
				{
					w = p->adjvex;
					if (!visited[w])
					{
						visited[w] = true;
						cout << G.vertices[w].data << " ";
						Queue[++rear] = G.vertices[w];
					}//if
				}//for
			}//while
		}//if
	}//for
}//BFSTraverse

void main()
{
	ALGraph G;
	CreateGraph(G);
	list(G);
	//深度優先遍歷圖
	cout << "深度優先遍歷:";
	DFSTraverse(G);
	cout << endl;
	//廣度優先遍歷
	cout << "廣度優先遍歷:";
	BFSTraverse(G);
	system("pause");
}