图11——判断图中是否为一棵树

编写算法,判断一个无向图是否是一颗树。

【分析】
一个无向图G是一棵树的条件为:G必须是无回路的连通图或n-1条边的连通图,这里我们采用后者作为判断条件。例如下图所示:

图11——判断图中是否为一棵树

上面的无向图就是一棵树,它有6个顶点,5条边。

code:

#include<stdlib.h>
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<iostream>
using namespace std;
/*图的邻接表类型定义*/
typedef char VertexType[4];
typedef char InfoPtr;
typedef int VRType;
#define MAXSIZE 100				/*最大顶点个数*/
typedef enum { DG, DN, UG, UN }GraphKind; 	/*图的类型:有向图、有向网、无向图和无向网*/
typedef struct ArcNode			/*边结点的类型定义*/
{
	int adjvex; 				/*弧指向的顶点的位置*/
	InfoPtr *info;				/*与弧相关的信息*/
	struct ArcNode *nextarc; 	/*指示下一个与该顶点相邻接的顶点*/
}ArcNode;
typedef struct VNode			/*头结点的类型定义*/
{
	VertexType data; 			/*用于存储顶点*/
	ArcNode *firstarc; 			/*指示第一个与该顶点邻接的顶点*/
}VNode, AdjList[MAXSIZE];
typedef struct					/*图的类型定义*/
{
	AdjList vertex;
	int vexnum, arcnum;			/*图的顶点数目与弧的数目*/
	GraphKind kind; 			/*图的类型*/
}AdjGraph;
int LocateVertex(AdjGraph G, VertexType v);
void CreateGraph(AdjGraph *G);
void DisplayGraph(AdjGraph G);
void DestroyGraph(AdjGraph *G);
void DFS(AdjGraph *G, int v, int *vNum, int *eNum, int visited[]);
int LocateVertex(AdjGraph G, VertexType v)
//返回图中顶点对应的位置
{
	int i;
	for (i = 0; i < G.vexnum; i++)
		if (strcmp(G.vertex[i].data, v) == 0)
			return i;
	return -1;
}
void CreateGraph(AdjGraph *G)
//采用邻接表存储结构创建无向图G
{
	int i, j, k;
	VertexType v1, v2;		//定义两个顶点v1和v2
	ArcNode *p;
	cout << "请输入图的顶点数和边数: ";
	cin >> (*G).vexnum >> (*G).arcnum;
	cout << "请输入" << G->vexnum << "个顶点的值:" << endl;
	for (i = 0; i < G->vexnum; i++)	//将顶点存储在头结点中
	{
		cin >> G->vertex[i].data;
		G->vertex[i].firstarc = NULL;	//将相关联的顶点置为空
	}
	cout << "请输入弧尾 弧头:" << endl;
	for (k = 0; k < G->arcnum; k++)	//建立边链表
	{
		cin >> v1 >> v2;
		i = LocateVertex(*G, v1);/*确定v1对应的编号*/
		j = LocateVertex(*G, v2);/*确定v2对应的编号*/
								 //j为弧头i为弧尾创建邻接表
		p = (ArcNode*)malloc(sizeof(ArcNode));
		p->adjvex = j;
		p->info = NULL;
		p->nextarc = G->vertex[i].firstarc;
		G->vertex[i].firstarc = p;
		//i为弧头j为弧尾创建邻接表
		p = (ArcNode*)malloc(sizeof(ArcNode));
		p->adjvex = i;
		p->info = NULL;
		p->nextarc = G->vertex[j].firstarc;
		G->vertex[j].firstarc = p;
	}
	(*G).kind = UG;
}
void DestroyGraph(AdjGraph *G)
//销毁无向图G
{
	int i;
	ArcNode *p, *q;
	for (i = 0; i < (*G).vexnum; i++)	//释放图中的边表结点
	{
		p = G->vertex[i].firstarc;//p指向边表的第一个结点
		if (p != NULL)			//如果边表不为空,则释放边表的结点
		{
			q = p->nextarc;
			free(p);
			p = q;
		}
	}
	(*G).vexnum = 0;		//将顶点数置为0
	(*G).arcnum = 0;		//将边的数目置为0
}
void DisplayGraph(AdjGraph G)
//输出图的邻接矩阵G
{
	int i;
	ArcNode *p;
	cout << G.vexnum << "个顶点:" << endl;
	for (i = 0; i < G.vexnum; i++)
		cout << G.vertex[i].data << " ";
	cout << endl << G.arcnum << "条边:" << endl;
	for (i = 0; i < G.vexnum; i++)
	{
		p = G.vertex[i].firstarc;
		while (p)
		{
			cout << G.vertex[i].data << "→" << G.vertex[p->adjvex].data << " ";
			p = p->nextarc;
		}
		cout << endl;
	}
}
int IsTree(AdjGraph *G)
{
	int vNum = 0, eNum = 0, i, visited[MAXSIZE];
	for (i = 0; i < G->vexnum; i++)
		visited[i] = 0;
	DFS(G, 0, &vNum, &eNum, visited);
	if (vNum == G->vexnum && eNum == 2 * (G->vexnum - 1))
		return 1;
	else
		return 0;
}
void DFS(AdjGraph *G, int v, int *vNum, int *eNum, int visited[])
{
	ArcNode *p;
	visited[v] = 1;
	(*vNum)++;
	p = G->vertex[v].firstarc;
	while (p != NULL)
	{
		(*eNum)++;
		if (visited[p->adjvex] == 0)
			DFS(G, p->adjvex, vNum, eNum, visited);
		p = p->nextarc;
	}
}
void main()
{
	AdjGraph G;
	cout << "采用邻接表创建无向图G:" << endl;
	CreateGraph(&G);
	cout << "输出无向图G的邻接表:" << endl;
	DisplayGraph(G);
	if (IsTree(&G))
		cout << "无向图G是一棵树!" << endl;
	else
		cout << "无向图G不是一棵树!" << endl;
	DestroyGraph(&G);

	system("pause");
}

结果:

图11——判断图中是否为一棵树


采用邻接表创建无向图G:
请输入图的顶点数和边数: 6 5
请输入6个顶点的值:
A B C D E F
请输入弧尾 弧头:
A B
A C
B E
C D
C F
输出无向图G的邻接表:
6个顶点:
A B C D E F
5条边:
A→C A→B
B→E B→A
C→F C→D C→A
D→C
E→B
F→C
无向图G是一棵树!

 

上一篇:洛谷P1346 电车 dijkstra求最短路


下一篇:细数 C++ 那些比起 C语言 更爽的特性