图的邻接矩阵演示

//根据网上和严蔚敏书上写的。
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define MaxVertexNum 100						//最大顶点个数
#define QM 100									//队列的最大元素个数
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

int visited[MaxVertexNum];						//用于深度优先遍历

typedef enum {DG, Dn, UDG, UDN} GraphKind;		//有向图,有向网,无向图,无向网

typedef int VertexType;							//顶点类型

typedef struct
{
	int adj;									//相邻与否,或者权值大小
}ArcCell;

typedef struct 
{
	VertexType vexs[MaxVertexNum];				//顶点向量
	ArcCell arcs[MaxVertexNum][MaxVertexNum];	//邻接矩阵
	int vexnum;									//顶点数
	int arcnum;									//弧数
	int GraphKind;								//图的种类
}MGraph;

typedef struct									//广度优先用的队列
{
	VertexType *base;
	VertexType front, rear;
}SQueue;

int LocateVex( MGraph *M,VertexType v );		//求顶点位置
int CreatGraph( MGraph *M );					//生成图
int CreatGraphDG( MGraph *M );					//创建有向图
int CreatGraphDN( MGraph *M );					//创建有向网
int CreatGraphUDG( MGraph *M );					//创建无向图
int CreatGraphUDN( MGraph *M );					//创建无向网
int FirstAdjVex( MGraph *M, int v );			//返回v的第一个邻接节点
int NextAdjVex( MGraph *M, int v , int w);		//返回v相对于w的下一个邻接节点
void PrintMatrix( MGraph *M );					//打印邻接矩阵
void InsetVex( MGraph *M, VertexType v );		//插入节点
int DelVex( MGraph *M, VertexType v );			//删除节点
void InsertArc( MGraph *M );					//添加一条弧
void DeArc( MGraph *M );						//删掉一条弧
void DFS( MGraph *M, int v );					//DFS
void DFSTraverse( MGraph *M );					//DFS深度优先遍历
void BFSTraverse( MGraph *M );					//BFS广度优先遍历
//队列函数声明
void InitQueue( SQueue *Q );					//初始化队列
void EnQueue( SQueue *Q, int e );				//入队
void OutQueue( SQueue *Q, int *e);				//出队
int QueueEmpty( SQueue *Q );					//队列是否空


int main()
{
	int time;

	printf("请输入试验次数:");
	scanf("%d", &time);

	while(time--)
	{
		MGraph M;
		M.vexnum = M.arcnum = 0;
			
		CreatGraph( &M );
		
		PrintMatrix( &M );
		DeArc( &M );
		PrintMatrix( &M );

		DFSTraverse( &M );
		printf("\n");
		getch();

		BFSTraverse( &M );
	}

	return 0;
}
 
//求顶点位置
int LocateVex( MGraph *M, VertexType v )
{
	int k;

	for(k = 0; k < M->vexnum; k++)
		if(M->vexs[k] == v)
			return k;

	return -1;
}

//创建图的选择函数
int CreatGraph( MGraph *G )
{
	printf("输入要创建图的类型\n");
	printf("0: 退出 1:有向图 2: 有向网 3: 无向图 4: 无向网 \n");

	while( scanf("%d", &G->GraphKind) )
	{
			switch (G->GraphKind)
			{
			case 0:
				exit(-1);
			case 1:
				return CreatGraphDG( G );
			case 2:
				return	CreatGraphDN( G );
			case 3:
				return CreatGraphUDG( G );
			case 4:
				return CreatGraphUDN( G );
			default:
			{
				system("cls");
				printf("输入无效,请重新输入要创建图的类型\n");
				printf("0: 退出 1:有向图 2: 有向网 3: 无向图 4: 无向网 \n");
				continue;
			}
		}
	}
}

//创建有向图
int CreatGraphDG( MGraph *M )
{
	int i, j, k;
	int weight = 1;
	VertexType v1, v2;

	printf("请输入有向图的顶点数和弧数:\n");
	scanf("%d %d", &M->vexnum, &M->arcnum);

	//初始化邻接矩阵
	for(i = 0; i < M->vexnum; i++)
		for(j = 0; j < M->vexnum; j++)
			M->arcs[i][j].adj = 0;   //初始化所有顶点不相邻

	printf("输入有向图的%d个顶点:\n", M->vexnum);
	for(i = 0; i < M->vexnum; i++)
		scanf("%d", &M->vexs[i]);

	printf("建立弧,请输入%d条弧的顶点:\n", M->arcnum);
	for(k = 0; k < M->arcnum; k++)
	{
		scanf("%d %d", &v1, &v2);

		i = LocateVex(M, v1);
		j = LocateVex(M, v2);

		if(i < 0 || j < 0)
			return ERROR;

		M->arcs[i][j].adj = weight;
	}

	return OK;
}

//创建有向网
int CreatGraphDN( MGraph *M )
{
	int i, j, k;
	int weight;
	VertexType v1, v2;

	printf("输入有向网的顶点数和弧数:\n");
	scanf("%d %d", &M->vexnum, &M->arcnum);

	for(i = 0; i < M->vexnum; i++)
		for(j = 0; j < M->vexnum; j++)
			M->arcs[i][j].adj = 0;  //初始化所有顶点不相邻

	printf("输入网的%d个顶点:\n", M->vexnum);
	for(i = 0; i < M->vexnum; i++)
		scanf("%d", &M->vexs[i]);

	printf("输入网的%d条弧的顶点和权值:\n", M->arcnum);
	for(k = 0; k < M->arcnum; k++)
	{
		scanf("%d %d %d", &v1, &v2, &weight);
		
		i = LocateVex(M, v1);
		j = LocateVex(M, v2);

		if(i < 0 || j < 0)
			return ERROR;
		
		M->arcs[i][j].adj = weight;
	}

	return OK;
}

//创建无向图
int CreatGraphUDG( MGraph *M )
{
	int i, j, k;
	int weight = 1;
	VertexType v1, v2;

	printf("输入无向图的顶点数和弧数:\n");
	scanf("%d %d", &M->vexnum, &M->arcnum);

	for(i = 0; i < M->vexnum; i++)
		for(j = 0; j < M->vexnum; j++)
			M->arcs[i][j].adj = 0;   //初始化所有顶点不相邻

	printf("输入无向图的%d个顶点:\n", M->vexnum);
	for(i = 0; i < M->vexnum; i++)
		scanf("%d", &M->vexs[i]);

	printf("建立弧,请输入无向图的%d条弧的顶点:\n", M->arcnum);
	for(k = 0; k < M->arcnum; k++)
	{
		scanf("%d %d", &v1, &v2);

		i = LocateVex(M, v1);
		j = LocateVex(M, v2);

		if(v1 < 0 || v2 < 0)
			return ERROR;

		M->arcs[j][i].adj =M->arcs[i][j].adj = weight;
	}

	return OK;
}

//创建无向网
int CreatGraphUDN( MGraph *M )
{
	int i, j, k;
	int weight;
	VertexType v1, v2;

	printf("输入无向网的顶点数和弧数:\n");
	scanf("%d %d", &M->vexnum, &M->arcnum);

	for(i = 0; i < M->vexnum; i++)
		for(j = 0; j < M->arcnum; j++)
			M->arcs[i][j].adj = 0;

	printf("输入无向网的%d个顶点:\n", M->vexnum);
	for(i = 0; i < M->vexnum; i++)
		scanf("%d", &M->vexs[i]);

	printf("建立弧,请输入无向网%d条弧的顶点和权值:\n", M->arcnum);
	for(k = 0; k < M->arcnum; k++)
	{
		scanf("%d %d %d", &v1, &v2, &weight);
		
		 i = LocateVex(M, v1);
		 j = LocateVex(M, v2);

		 if(v1 < 0 || v2 < 0)
			 return ERROR;

		 M->arcs[i][j].adj = M->arcs[j][i].adj = weight;
	}

	return OK;
}

//打印邻接矩阵
void PrintMatrix( MGraph *M)
{
	int i, j;

	for(i = 0; i < M->vexnum; i++)
	{
		for(j = 0; j < M->vexnum; j++)
			printf("%d\t", M->arcs[i][j].adj);
		printf("\n");
	}
}

//返回v的第一个邻接节点
int FirstAdjVex( MGraph *M, int v )
{
	int i;

	for(i = 0; i < M->vexnum; i++)
		if( M->arcs[v][i].adj != 0 )
			return i;

	return -1;
}

//返回v相对于w的下一个邻接节点
int NextAdjVex( MGraph *M, int v, int w )
{
	int i;

	for(i = w+1; i < M->vexnum; i++)
		if( M->arcs[v][i].adj != 0 )
			return i;

	return -1;
}

//插入节点v
void InsertVex( MGraph *M, VertexType v )
{
	int i, j;

	printf("插入一个顶点:\n");
	M->vexs[M->vexnum++] = v;
	i = LocateVex( M, v );

	for(j = 0; j < M->vexnum; j++)
		M->arcs[i][j].adj = M->arcs[j][i].adj = 0;			//默认添加顶点和其他顶点都不相邻
}

//删除一个节点
int DelVertex( MGraph *M, VertexType v )
{
	int i, j;

	i = LocateVex( M, v );

	if( i == -1 )
	{
		printf("该节点不存在\n");
		return ERROR;
	}

	for(j = 0; j < M->vexnum; j++)
		M->arcs[i][j].adj = M->arcs[j][i].adj = 0;			//删除与该顶点邻接的弧

	for(j = i; j < M->vexnum - 1; j++)
		M->vexs[j] = M->vexs[j+1];

	M->vexnum--;

	return OK;
}

//DFS
void DFS( MGraph *M , int v )
{
	int vj;

	visited[v] = TRUE;
	printf("%d ", M->vexs[v]);

/*	
	for( vj = 0; vj < M->vexnum; vj++)
		if( !visited[vj] && M->arcs[v][vj].adj )
			DFS( M, vj );
*/

	for( vj = FirstAdjVex(M, v); vj >= 0; vj = NextAdjVex(M, v, vj) )			
		if( !visited[vj] )
			DFS( M, vj);
}

//DFS深度优先遍历
void DFSTraverse( MGraph *M )
{
	int vi;

	printf("深度遍历:\n");

	for(vi = 0; vi < M->vexnum; vi++)
		visited[vi] = FALSE;

	for(vi = 0; vi < M->vexnum; vi++)
		if( !visited[vi] )
			DFS( M, vi );
}

//广度优先遍历
void BFSTraverse( MGraph *M )
{
	int v, u, w;
	SQueue Q;

	printf("广度优先遍历:\n");

	for(v = 0; v < M->vexnum; v++)
		visited[v] = FALSE;

	InitQueue( &Q );

	for(v = 0; v < M->vexnum; v++)
		if( !visited[v] )
		{
			visited[v] = TRUE;
			printf("%d ", M->vexs[v]);

			EnQueue( &Q, v );

			while( !QueueEmpty( &Q ) )
			{
				OutQueue( &Q, &u);

				for( w = FirstAdjVex( M, u ); w >= 0; w = NextAdjVex( M, u, w) )
				{
					if( !visited[w] )
					{
						visited[w] = TRUE;
						printf("%d ", M->vexs[w]);
						EnQueue( &Q, w );
					}
				}
			}
		}
	
	printf("\n");
}

//初始化队列
void InitQueue( SQueue *Q )
{
	Q->base = (VertexType * ) malloc ( sizeof(VertexType) * QM );
	
	if( Q->base == NULL )
	{
		printf("分配内存失败\n");
		exit(-1);
	}

	Q->front = Q->rear = 0;
}

//队列是否为空
int QueueEmpty( SQueue *Q )
{
	return Q->front == Q->rear;
}

//入队
void EnQueue( SQueue *Q, int e )
{
	int t = (Q->rear + 1) % QM;

	if( t == Q->front )
	{
		printf("队列已满溢出");
		exit(-1);
	}

	Q->base[t-1] = e;
	Q->rear = t;
}

//出队
void OutQueue( SQueue *Q, int *e )
{
	if( QueueEmpty(Q) )
	{
		printf("出队失败,队列为空\n");
		exit(-1);
	}

	*e = Q->base[ (Q->front)++ ];
}

//添加一条弧
void InsertArc( MGraph *M )
{
	VertexType v1, v2;
	int weight;
	int i, j;

	printf("添加一条弧\n");

	if( M->GraphKind == 1 || M->GraphKind == 3 )		//图
	{
		printf("输入要添加的弧的两个顶点: ");
		while( scanf("%d %d", &v1, &v2) )
		{

			i = LocateVex( M, v1);
			j = LocateVex( M, v2);

			if( i < 0 || j < 0 )
			{
				printf("顶点不在图中请重新输入:");
				continue;
			}

			if( M->GraphKind == 1 )						//有向图
				M->arcs[i][j].adj = 1;
			else										//无向图
				M->arcs[i][j].adj = M->arcs[j][i].adj = 1;
			break;
		}
	}
	else
	{
		printf("输入要添加的弧的两个顶点和权值: ");
		while( scanf("%d %d %d", &v1, &v2, &weight) )
		{
			i = LocateVex( M, v1);
			j = LocateVex( M, v2);

			if( i < 0 || j < 0 )
			{
				printf("顶点不在图中请重新输入:");
				continue;
			}
			
			if( M->GraphKind == 2 )						//有向网
				M->arcs[i][j].adj = weight;
			else
				M->arcs[i][j].adj = M->arcs[j][i].adj = weight;
			break;
		}
	}
}

//删掉一条弧
void DeArc( MGraph *M )
{
	int v1, v2;
	int i, j;

	printf("请输入删掉弧的两个顶点: ");
	
	while( scanf("%d %d", &v1, &v2) )
	{
		i = LocateVex( M, v1 );
		j = LocateVex( M, v2 );

		if( i < 0 || j < 0 )
		{
			printf("该节点不在图中,请重新输入: ");
			continue;
		}

		if( M->GraphKind <= 2 )
			M->arcs[i][j].adj = 0;
		else
			M->arcs[i][j].adj = M->arcs[j][i].adj = 0;
		break;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值