图的邻接矩阵存储结构的实现及其遍历

图的邻接矩阵存储结构是一个很容易理解的存储结构,用一个矩阵记录两个顶点之间的关系,对于无向无权图,用0和1来表示两个顶点之间是否相邻即可,对于无向有权图,使用一个整型来表示两个顶点之间的弧的权值即可。

存储结构的定义:

typedef char VertexType ;  // 顶点类型
typedef int  EdgeType   ;  // 边类型
#define MaxVex  100       // 最大结点数
#define INFINITY 65535
#define MaxNum 100    // 队列最大元素

// 图的邻接矩阵定义
typedef struct 
{
	VertexType vexs[MaxVex] ;  // 顶点表
	EdgeType arc[MaxVex][MaxVex] ; // 邻接边表
	int numVertexes ;   // 顶点数
	int numEdges ;  // 边数
} MGraph ;

因为这个存储结构比较简单,所以可以直接看代码就比较易懂了。

///////////////////////////////////////////////////
//
//   图的邻接矩阵的实现
//
///////////////////////////////////////////////////
////////

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


typedef char VertexType ;  // 顶点类型
typedef int  EdgeType   ;  // 边类型
#define MaxVex  100       // 最大结点数
#define INFINITY 65535
#define MaxNum 100    // 队列最大元素

// 图的邻接矩阵定义
typedef struct 
{
	VertexType vexs[MaxVex] ;  // 顶点表
	EdgeType arc[MaxVex][MaxVex] ; // 邻接边
	int numVertexes ;   // 顶点数
	int numEdges ;  // 边数
} MGraph ;


typedef struct Queue   // 队列的定义
{
	int data[100] ;
	int front ;
	int rear ;
} Queue ;

typedef struct Stack
{
	int data[100] ;
	int top ;
	int base ;
} Stack ;


bool visited[MaxVex]  ;  // 针对于图的递归遍历

// 队列初始化
void InitQueue( Queue * Q )
{
	Q->front = 0 ;
	Q->rear = 0 ;
}

// 栈的初始化
void InitStack( Stack * S )
{
	S->base = 0 ;
	S->top = 0 ;
}

// 队列为空
bool is_empty( Queue * Q )
{
	if( Q->front == Q->rear )
	{
		return true ;
	}
	return false ;
}

// 队列已满
bool is_full( Queue * Q )
{
	if( ( Q->rear + 1 ) % MaxNum == Q->front )
	{
		return true ;
	}
	return false ;
}

// 判断栈为空
bool is_stack_empty( Stack * S )
{
	if( S->base == S->top )
	{
		return true ;
	}
	return false ;
}

// 判断栈已满
bool is_stack_full( Stack * S )
{
	if( S->top - S->base + 1 == MaxNum )
	{
		return true ;
	}
	return false ;
}

// 入队
void EnQueue( Queue * Q , int elem )
{
	if( !is_full( Q ) )
	{
		Q->data[Q->rear] = elem ;
		Q->rear = ( Q->rear + 1 ) % MaxNum ;
	}
}

// 出队
void DeQueue( Queue * Q , int * elem )
{
	if( !is_empty( Q ) )
	{
		*elem = Q->data[Q->front++] ;
	}
}

// 入栈
void Push( Stack * S , int elem )
{
	if( !is_stack_full( S ) )
	{
		S->data[S->top++] = elem ;
	}
}

// 出栈
void Pop( Stack * S , int * elem )
{
	if( !is_stack_empty( S ) )
	{
		*elem = S->data[--S->top] ;
	}
}

// 初始化图
void InitGraph( MGraph * G )
{
	G->numEdges = 0 ; 
	G->numVertexes = 0 ;
}

// 创建图
void CreateGraph( MGraph * G )
{
	/*
	printf("请输入顶点的数目:") ;
	scanf("%d", &G->numVertexes ) ;
	printf("请输入边的数目:") ;
	scanf("%d" , &G->numEdges ) ;

	printf("请输入顶点域的内容:") ;
	for( int i = 0 ; i < G->numVertexes ; i++ )
	{
		scanf("%c" ,&G->vexs[i] ) ;
	}

	printf("请输入各顶点之间边的关系:\n") ;
	for( i = 0 ; i < G->numVertexes ; i++ )
	{
		for( int j = 0 ; j < G->numVertexes ; j++ )
		{
			scanf("%d" , &G->arc[i][j] ) ; 
		}
	}
*/

	G->numVertexes = 6 ;
	G->numEdges = 7 ;

	G->vexs[0] = 'A' ;
	G->vexs[1] = 'B' ;
	G->vexs[2] = 'C' ;
	G->vexs[3] = 'D' ;
	G->vexs[4] = 'E' ;
	G->vexs[5] = 'F' ;

	G->arc[0][0] = 0 ;
	G->arc[0][1] = 1 ;
	G->arc[0][2] = 1 ;
	G->arc[0][3] = 0 ;
	G->arc[0][4] = 0 ;
	G->arc[0][5] = 1 ;

	G->arc[1][0] = 1 ;
	G->arc[1][1] = 0 ;
	G->arc[1][2] = 1 ;
	G->arc[1][3] = 0 ;
	G->arc[1][4] = 1 ;
	G->arc[1][5] = 0 ;

	G->arc[2][0] = 1 ;
	G->arc[2][1] = 1 ;
	G->arc[2][2] = 0 ;
	G->arc[2][3] = 1 ;
	G->arc[2][4] = 0 ;
	G->arc[2][5] = 0 ;

	G->arc[3][0] = 0 ;
	G->arc[3][1] = 0 ;
	G->arc[3][2] = 1 ;
	G->arc[3][3] = 0 ;
	G->arc[3][4] = 1 ;
	G->arc[3][5] = 0 ;

	G->arc[4][0] = 0 ;
	G->arc[4][1] = 1 ;
	G->arc[4][2] = 0 ;
	G->arc[4][3] = 1 ;
	G->arc[4][4] = 0 ;
	G->arc[4][5] = 0 ;

	G->arc[5][0] = 1 ;
	G->arc[5][1] = 0 ;
	G->arc[5][2] = 0 ;
	G->arc[5][3] = 0 ;
	G->arc[5][4] = 0 ;
	G->arc[5][5] = 0 ;
}

// 邻接矩阵的广度优先遍历算法 
void BFS( MGraph * G )
{
	bool visited[MaxVex] ;   // 表示该顶点是否被访问过
	int i , j ;
	Queue Q ;

	for( i = 0 ; i < G->numVertexes ; i++ )   // 初始化
	{
		visited[i] = false ;  // 最开始所有顶点都未被访问
	}

	InitQueue( &Q ) ;   // 初始化队列

	for( i = 0 ; i < G->numVertexes ; i++ )
	{
		if( !visited[i] )
		{
			EnQueue( &Q , i ) ;   // 入队
			printf("%c " , G->vexs[i] ) ;   // 访问该顶点
            visited[i] = true ;             // 标记为已访问
		    
			while( !is_empty( &Q ) )
			{
				DeQueue( &Q , &i ) ;    // 出队,并将出队的元素返回到变量i中

				for( j = 0 ; j < G->numVertexes ; j++ )   // 遍历与顶点i相邻的顶点
				{
					if( G->arc[i][j] == 1 && visited[j] == false )
					{
						EnQueue( &Q , j ) ;   // 与顶点i相邻的顶点j入队
						printf("%c " , G->vexs[j] ) ;  // 访问该顶点
						visited[j] = true ;
					}
				}
			}
		}
	}
}

// 邻接矩阵的深度优先遍历 非递归实现
void DFS( MGraph * G )
{
	int i = 0 ; 
	int j = 0 ;
	int k = 0 ;
	bool visited[MaxVex] ;

	Stack S ;

	InitStack( &S ) ;  // 初始化栈

	for( i = 0 ; i < G->numVertexes ; i++ )
	{
		visited[i] = false ;  // 初始化为未访问
	}

	for( i = 0 ; i < G->numVertexes ; i++ )   // 这个循环主要是针对非连通图,若是连通图则可以省去这个顶点 
	{
		if( visited[i] == false )  // 未访问
		{
			Push( &S , i ) ;

			while( !is_stack_empty( &S ) )
			{
				Pop( &S , &i ) ;
				if( visited[i] == false )
				{
					printf("%c " , G->vexs[i] ) ;  // 访问该顶点
					visited[i] = true ;   // 标记为已访问
				}

				for( j = 0 ; j < G->numVertexes ; j++ )   // 遍历与当前顶点相邻的顶点
				{
					if( G->arc[i][j] == 1 && visited[j] == false )  
					{
						Push( &S , j ) ;
					}
				}
			}
		}
	}
}

// 初始化全局变量visited[MaxVex]
void InitVisit( MGraph * G , bool * visited )
{
	for( int i = 0 ; i < G->numVertexes ; i++ )
	{
		visited[i] = false ;
	}
}


// 存储结构为邻接矩阵的图的遍历的递归实现
void DFS_Recursion( MGraph * G , int v )
{
	if( visited[v] == false )
	{
		printf("%c " , G->vexs[v] ) ;
		visited[v] = true ;
	}

	for( int k = 0 ; k < G->numVertexes ; k++ )
	{
		if( G->arc[v][k] == 1 && visited[k] == false )
		{
			DFS_Recursion( G , k ) ;
		}
	}
}

void DFS_Traverse_Recursion( MGraph * G )
{
	for( int i = 0 ; i < G->numVertexes ; i++ )
	{
		DFS_Recursion( G , i ) ;
	}
}

// 测试
int main()
{
	MGraph G ;
	InitGraph( &G ) ;   // 初始化图

	CreateGraph( &G ) ;  // 创建图

	BFS( &G ) ;   // 宽度优先遍历图

	printf("\n") ;

	DFS( &G ) ;  // 广度优先遍历

	printf("\n") ;

	InitVisit( &G , visited ) ;

	DFS_Traverse_Recursion( &G ) ;

	printf("\n") ;

	return 0 ;
}








    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/junbopengpeng/article/details/13022065
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞