1. 程式人生 > >圖的建立、廣度優先搜尋、深度優先搜尋

圖的建立、廣度優先搜尋、深度優先搜尋

#include <iostream>
/*圖的儲存結構:鄰接連結串列、鄰接矩陣*/
/******************圖的資料結構***************/
typedef char ElemType;
const int WHITE = 0;
const int BLACK = 1;
const int MAX_VERTEX = 30;
const int MAX_ARC = 900;
/*邊的資料結構*/
typedef struct arc_node
{
	int position;//儲存邊的另一個頂點下標
	int weight;//邊的權重
	struct arc_node *next;//指向下一條邊
}ANode, *pArc;
/*頂點的資料結構*/
typedef struct vertex_node
{
	ElemType data;
	pArc first_arc;//指向第一條弧
}VNode, *pVNode;
/*圖的資料結構*/
typedef struct graphic_node
{
	int vertex_num;//頂點數量
	int arc_num;//邊的數量
	pVNode vertex[MAX_VERTEX];//用來存放頂點的陣列
}Graphic, *pGNode;

void create_graphic(pGNode g, int direction);//建立圖,direction=0無向圖,=1有向圖
/******************圖的遍歷***************/
/*1、廣度優先搜尋(類似於樹的按層次遍歷)
基本思想:在已發現節點和未發現節點的邊界上,沿其廣度方向向外擴充套件,也就是說訪問完距離源節點
為k的節點再去訪問距離為k+1的節點
*/
void bfs(Graphic g, int source);//給定圖g和起始遍歷位置
/*2、深度優先搜尋(類似於樹的先根遍歷)
基本思想:只要可能就在圖中儘量深入,總是對最近才發現的節點v沿其出發邊進行探索
直到該節點的所有出發邊都被發現為止,搜尋則回溯到v節點的前驅節點
*/
void dfs(Graphic g);
void dfs_visit(Graphic g, int source);
int visit[MAX_VERTEX] = { WHITE };//用來記錄節點是否被訪問
/*輔助資料結構:佇列*/
struct queue_node
{
	pVNode data;
	struct queue_node *next;
};
typedef struct queue
{
	struct queue_node *front;
	struct queue_node *tail;
}Queue;
/*要想修改內容必須傳指標,要想修改內容指向的值可以不傳指標*/
void init_queue(Queue *q);
bool isempty_queue(Queue q);
void insert_queue(Queue *q, pVNode e);
bool delete_queue(Queue *q, pVNode *e);//當刪除最後一個元素的時候一定要修改尾部指標

using namespace std;
int main()
{
	Graphic undirec_g, direc_g;
	cout << "*****************建立一個無向圖*************" << endl;
	create_graphic(&undirec_g, 0);

	cout <<endl<< "廣度優先遍歷:" << endl;
	bfs(undirec_g, 0);

	cout << endl << "深度優先遍歷:" << endl;
	dfs(undirec_g);

	cout << endl << "*****************建立一個有向圖*************" << endl;
	create_graphic(&direc_g, 1);
	cout << endl << "廣度優先遍歷:" << endl;
	bfs(direc_g, 0);
	cout << endl << "深度優先遍歷:" << endl;
	dfs(direc_g);
	cout << endl;
}

void create_graphic(pGNode g, int direction)//direction = 0表示建立的是無向圖,非0值是有向圖
{
	cout << "輸入頂點數" << endl;
	cin >> g->vertex_num;
	cout << "輸入邊數" << endl;
	cin >> g->arc_num;

	int i;
	cout << "輸入" << g->vertex_num << "個頂點" << endl;
	for (i = 0; i < g->vertex_num; i++)
	{
		g->vertex[i] = (pVNode)malloc(sizeof(VNode));

		cin >> (g->vertex[i]->data);
		g->vertex[i]->first_arc = NULL;
	}
	cout << "輸入" << g->arc_num << "個邊和邊的權重(例如:輸入0 1 20表示下標為0和下標為1的頂點有一條邊且權重為20)" << endl;
	for (i = 0; i < g->arc_num; i++)
	{
		int x, y, w;
		cin >> x >> y >> w;

		pArc temp1 = (pArc)malloc(sizeof(ANode));
		temp1->position = y;
		temp1->weight = w;
		/*將邊加入到連結連結串列中*/
		temp1->next = g->vertex[x]->first_arc;
		g->vertex[x]->first_arc = temp1;

		if (direction == 0)//說明是無向圖
		{
			pArc temp2 = (pArc)malloc(sizeof(ANode));
			temp2->position = x;
			temp2->weight = w;

			temp2->next = g->vertex[y]->first_arc;
			g->vertex[y]->first_arc = temp2;
		}

	}
}

void bfs(Graphic g, int source)//給定圖g和起始遍歷位置
{
	int visit[MAX_VERTEX] = { WHITE };//初始化為白色,說明所有頂點沒有被訪問,訪問之後變為黑色

	Queue q;
	init_queue(&q);
	insert_queue(&q, g.vertex[source]);
	visit[source] = BLACK;
	/*如果佇列不為空則從佇列中取出元素*/
	while (!isempty_queue(q))
	{
		pVNode temp;
		delete_queue(&q, &temp);
		/*列印輸出該節點資料*/
		cout << temp->data << " ";
		/*如果節點所連線的其它節點沒有被訪問,則加入到佇列中*/
		pArc x = temp->first_arc;
		while (x != NULL)
		{
			int position = x->position;
			if (visit[position] == WHITE)
			{
				insert_queue(&q, g.vertex[position]);
				visit[position] = BLACK;
			}
			x = x->next;
		}
	}
}

void dfs(Graphic g)
{
	for (int i = 0; i < g.vertex_num; i++)
		visit[i] = WHITE;//初始化為白色,意味著沒有被訪問
	for (int i = 0; i < g.vertex_num; i++)
	{
		if (visit[i] == WHITE)
			dfs_visit(g, i);
	}
}

void dfs_visit(Graphic g, int source)
{
	if (visit[source] == BLACK)
		return;
	pVNode x = g.vertex[source];
	cout << x->data;
	visit[source] = BLACK;

	pArc y = x->first_arc;
	while (y != NULL)
	{
		dfs_visit(g, y->position);
		y = y->next;
	}
}

void init_queue(Queue *q)
{
	queue_node *temp = (queue_node *)malloc(sizeof(queue_node));
	temp->next = NULL;

	q->front = q->tail = temp;
}

bool isempty_queue(Queue q)
{
	if (q.front->next == NULL)
		return true;
	return false;
}

void insert_queue(Queue *q, pVNode e)
{
	/*動態分配一個佇列節點*/
	queue_node *x = (queue_node *)malloc(sizeof(queue_node));
	x->data = e;
	x->next = NULL;
	/*將節點插入到佇列的尾部*/
	q->tail->next = x;
	q->tail = x;
}

bool delete_queue(Queue *q, pVNode *e)
{
	if (isempty_queue(*q))
		return false;
	queue_node *temp = q->front->next;
	*e = temp->data;
	q->front->next = temp->next;

	if (temp->next == NULL)//到了隊尾
		q->tail = q->front;
	free(temp);
	return true;
}