圖的鄰接表創建及深度優先遍歷和廣度優先遍歷

最近在學圖,寫個筆記。
圖的創建一般有鄰接矩陣和鄰接表兩種方法,鄰接矩陣對於邊數相對於頂點較少的圖會有極大的浪費,所以用鄰接表,用數組與鏈表相配合
頂點用一維數組儲存
所有頂點的鄰接點構成一個線性表,因爲鄰接點的個數不確定,所以用單鏈表
在這裏插入圖片描述
圖的深度優先搜索是對先序遍歷的推廣 一個遞歸的過程,沿着一個方向遍歷,一直到最後,然後再回來到另一個結點沿着一個方向。
廣度優先遍歷就是一層一層的遍歷。如上圖
上代碼:

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

#define MAXVEX 7   //代表最大頂點數
#define INFINITY 65535 //代表無窮大

typedef struct GraphNode
{
	int index;    //下標
	struct GraphNode *next;  //指向下一個的指針
}GraphNode;

typedef struct Gra
{
	char c;  //頂點元素
	GraphNode *first ;
}Gra;

typedef struct Graph
{
	Gra vex[MAXVEX];
	int numvex,edge;  //頂點元素和邊的數量
}Graph;

//創建一個隊列,用來廣度優先遍歷
typedef struct QNode
{
	int data;
	struct QNode *next;
}QNode,*Queueprt;

typedef struct
{
	Queueprt front,rear;   
}LinkQueue;

//隊列的初始化
void InitQueue(LinkQueue *q)
{
	q->front=q->rear=(Queueprt)malloc(sizeof(QNode));
	q->front->next=NULL;
}

//入隊列
void EnQueue(LinkQueue *q,int e)
{
	Queueprt p;
	p=(Queueprt)malloc(sizeof(QNode));
	p->data=e;
	q->rear->next=p;
	p->next=NULL;
	q->rear=p;
}

//出隊列
void DeQueue(LinkQueue *q,int *e)
{
	if(q->front==q->rear)
	{
		return;
	}
	Queueprt p;
	p=q->front->next;
	*e = p->data;             
	q->front->next=p->next;
	if(p==q->rear)
	{
		q->rear=q->front;
	}
	free(p);
}

//判斷隊列是否爲空
int QueueEmpty(LinkQueue *q)
{
	if(q->front==q->rear)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
//創建圖
void create(Graph *g)
{
	int i,j,m,n;
	GraphNode *p,*q;
	printf("輸入頂點元素的數量和邊的數量:\n");
	scanf("%d %d",&(g->numvex),&(g->edge));
	printf("輸入頂點元素:\n");
	for(i=0;i<g->numvex;i++)
	{
		getchar();
		scanf("%c",&(g->vex[i].c) );
		g->vex[i].first=NULL;
	}
	//建立邊集
	printf("輸入邊兩邊頂點的下標:\n");
	for(j=0;j<g->edge;j++)
	{
		scanf("%d %d",&m,&n);
		p=(GraphNode *)malloc(sizeof(GraphNode));
		p->index=m;
		p->next=g->vex[n].first;
		g->vex[n].first=p;          //這裏是把first移到p


		q=(GraphNode *)malloc(sizeof(GraphNode));
		q->index=n;
		q->next=g->vex[m].first;       
		g->vex[m].first=q;
	}	
}

void print(Graph *g)
{
	int i;
	GraphNode *p;
	for(i=0;i<g->numvex;i++)
	{
		p=g->vex[i].first;
		while(p)
		{
			printf("(%c,%c)",g->vex[i].c,g->vex[p->index].c);
			p=p->next;
		}
		printf("\n");
	}
}

//DFS遍歷

void DFS(Graph *g,int i,int *visited)
{
	GraphNode *p;
	visited[i]=1;
	printf("%c ",g->vex[i].c);
	p=g->vex[i].first;
	while( p )
	{
		if(!visited[p->index])
		{
			DFS(g,p->index,visited);
		}
		p=p->next;
	}

}

void TraDFS(Graph *g)
{
	int i;
	int visited[MAXVEX];
	for(i=0;i<MAXVEX;i++)
	{
		visited[i]=0;
	}
	for(i=0;i<g->numvex;i++)
	{
		if(!visited[i])
		{
			DFS(g,i,visited);
		}
	}

}

//BFS遍歷
void TraBFS(Graph *g)
{
	int i,j;
	LinkQueue q;
	int visited[MAXVEX];
	for(i=0;i<MAXVEX;i++)
	{
		visited[i]=0;
	}
	InitQueue(&q);
	for(i=0;i<g->numvex;i++)
	{
		if(!visited[i])
		{
			printf("%c ",g->vex[i].c);
			visited[i]=1;
			EnQueue(&q, i);
			while(!QueueEmpty(&q))
			{
				DeQueue(&q,&i);
				GraphNode *p = g->vex[i].first;
				while( p )
				{
					if(!visited[p->index])
					{
						printf("%c ",g->vex[p->index].c);
						visited[p->index]=1;
						EnQueue(&q,p->index);
					}
					p=p->next;
				}
			}

		}
	}

}

int main(){
	
	Graph g;
	create(&g);
	print(&g);
	printf("DFS遍歷結果:\n");
	TraDFS(&g);
	printf("\nBFS遍歷結果爲:\n");
	TraBFS(&g);
	printf("\n");
	return 0;
}

在這裏插入圖片描述
一開始出隊列寫錯了,廣度遍歷不對,找了好久的原因。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章