图的存储与拓扑排序

本文介绍了一种使用邻接矩阵和邻接表实现图的方法,并提供了具体的C++代码示例。文中详细解释了如何创建不同类型的图(如有向图和无向图),并展示了如何进行拓扑排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// Graph.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#include "iostream"
#include "stack"
#include "vector"

const int INFINITY = 9999;
const int MAX_VERTEX_NUM = 20;
const int ERROR = -1;

using namespace std;

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

typedef char VertexData;

typedef struct ArcNode
{
	int Value;		// 邻接矩阵,通过数量表示两个顶点之间是否相连
	char * info;	// 其他信息
}ArcNode, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];  // 邻接矩阵中的元素

typedef struct ArcNode_AdjList
{
	int adjvex; // 邻接点的索引
	struct ArcNode_AdjList *nextarc;
	char* info;
}ArcNode_AdjList;

typedef struct VertexNode
{
	VertexData data;
	int inDegree;				// 顶点的入读
	ArcNode_AdjList * firstArc; // 记录头结点
};

typedef struct 
{
	VertexNode vertexList[MAX_VERTEX_NUM]; // 各个图结点的邻接表
	int vexnum;
	int arcnum;
	GraphKind kind;
}ALGraph;

typedef struct MGraph
{
	VertexData vertex[MAX_VERTEX_NUM];				// 记录顶点数组
	AdjMatrix arcs;	// 邻接矩阵,是一个结构体的二维数组,结构体用来存储每一个边的信息
	int vexnum;										// 顶点的数量
	int arcnum;										// 边的数量
	GraphKind kind;
}MGraph;

int LocateVertex(MGraph *G, VertexData v);
int CreateGraph(MGraph &G);
int CreateUDN(MGraph &G);
int CreateUDG(MGraph &G);
int CreateDN(MGraph &G);
int CreateDG(MGraph &G);
int CreateALGraph(ALGraph &ALG);
void FindInDegree(ALGraph &G, int indegree[]);
int TopoSort(ALGraph &G);
int TopoSortDFS(ALGraph &G);
void DFS(ALGraph &G, int indegree[]);

int _tmain(int argc, _TCHAR* argv[])
{
	// 创建邻接矩阵图
	/*MGraph graph;
	CreateGraph(graph);
	for (int i = 0; i < graph.vexnum;i++)
	{
	for (int j=0;j<graph.vexnum;j++)
	{
	printf("%5d",graph.arcs[i][j].Value);
	}
	printf("\n");
	}*/

	// 创建邻接表图
	ALGraph G;
	CreateALGraph(G);
	for(int i = 0; i<G.vexnum; i++)
	{
		printf("node:%c",G.vertexList[i].data);
		// 打印邻接表
		ArcNode_AdjList *p = G.vertexList[i].firstArc;
		while(p!=NULL)
		{
			printf("%d", p->adjvex);
			p=p->nextarc;
		}
		printf("\n");
	}

	printf("Topo Sort ***************\n");
	TopoSort(G);
	// 遍历所有的可能的拓扑排序的结果
	//TopoSortDFS(G);
	printf("\n");

	system("pause");
	return 0;
}

int CreateGraph(MGraph &G)
{
	printf("pls input the kind of the Graph! \n");
	scanf("%d",&G.kind);
	switch(G.kind)
	{
	case DG:return CreateDG(G);
	case DN:return CreateDN(G);
	case UDG:return CreateUDG(G);
	case UDN:return CreateUDN(G);
	default: return 0;
	}
}

// 定位顶点的位置
int LocateVertex(MGraph *G, VertexData v)
{
	int j = ERROR;
	int k = 0;
	for (k=0; k < G->vexnum; k++)
	{
		if (G->vertex[k] == v)
		{
			j = k;
			break;
		}
	}
	return j;
}

int CreateDG(MGraph &G)
{
	//
	return 0;
}

int CreateDN(MGraph &G)
{
	//
	int i,j,weight;
	VertexData v1,v2;
	printf("pls input arc num, vex num ('%%d,%%d')\n");
	scanf("%d,%d",&G.arcnum,&G.vexnum);
	fflush(stdin);
	// 初始化邻接矩阵
	for (int i = 0; i < G.vexnum; i++)
	{
		for (int j = 0; j < G.vexnum; j++)
		{
			G.arcs[i][j].Value = INFINITY;
		}
	}
	// 输入图的顶点
	printf("input graph vertex\n");
	fflush(stdin);
	for (int i = 0; i < G.vexnum; i++)
	{
		scanf("%c",&G.vertex[i]);
	}
	// 输入图的边
	fflush(stdin);
	printf("input graph edges %%c,%%c,%%d\n");
	for (int k = 0; k<G.arcnum; k++)
	{
		scanf("%c,%c,%d",&v1,&v2,&weight);
		i = LocateVertex(&G,v1);
		j = LocateVertex(&G,v2);
		G.arcs[i][j].Value = weight;
		fflush(stdin);
	}
	return 1;
}

int CreateUDG(MGraph &G)
{
	return 0;
}

int CreateUDN(MGraph &G)
{
	//
	return 0;
}

// 创建有向图的邻接表
int CreateALGraph(ALGraph &ALG)
{
	ArcNode_AdjList *p;
	int i,s,d;
	ALG.kind = DN;

	printf("pls input vertex num and edge num\n");
	scanf("%d,%d",&s,&d);
	ALG.vexnum = s;
	ALG.arcnum = d;
	fflush(stdin);

	// 邻接表顶点初始化
	for (i=0; i<ALG.vexnum;i++)
	{
		printf("第%d个顶点信息:\n",i+1);
		scanf("%c", &ALG.vertexList[i].data);
		ALG.vertexList[i].firstArc = NULL;
		ALG.vertexList[i].inDegree = 0;
		fflush(stdin);
	}

	// 每条边的信息初始化
	for (i = 0; i<ALG.arcnum;i++)
	{
		printf("第%d条边的起始顶点编号与终止顶点编号:\n",i+1);
		scanf("%d,%d",&s,&d);
		while(s<1||s>ALG.vexnum||d<1||d>ALG.vexnum)
		{
			printf("顶点编号超出范围,重新输入\n");
			scanf("%d,%d",&s,&d);
		}
		s--;
		d--;
		p = (ArcNode_AdjList*)malloc(sizeof(ArcNode_AdjList));
		p->adjvex = d;
		p->nextarc = ALG.vertexList[s].firstArc;
		ALG.vertexList[s].firstArc = p;
		ALG.vertexList[d].inDegree++;
		fflush(stdin);
	}
	return 1;
}

// 深度优先遍历,获取所有可能的拓扑排序结果
stack<int> S;
vector<int> V;
int TopoSortDFS(ALGraph &G)
{
	int indegree[MAX_VERTEX_NUM];
	int i, count, k;
	ArcNode_AdjList *p;
	FindInDegree(G, indegree);
	// 将入度为0的顶点入栈,即为拓扑排序中可以输出的顶点
	for (i=0;i<G.vexnum;i++)
	{
		if (indegree[i]==0)
		{
			S.push(i);
			V.push_back(i); // 保存到vector中
		}
	}
	// TODO
	DFS(G,indegree);
	return 1;
}

void DFS(ALGraph &G, int indegree[])
{
	if (V.size()==G.vexnum)
	{
		// 一次拓扑排序结束
		printf("\n");
	}
	else
	{
		for (int i=0;i<V.size();i++)
		{
			int t = V[i];
			printf("%c",G.vertexList[t].data);
			//V.erase(V.begin()+i);

			ArcNode_AdjList *p = G.vertexList[t].firstArc;
			while(p!=NULL)
			{
				int k = p->adjvex;
				indegree[k]--;
				if (indegree[k]==0)
				{
					V.push_back(k);
				}
				p=p->nextarc;
			}

			DFS(G,indegree);

			//V.insert(V.begin()+i,t);
			p = G.vertexList[t].firstArc;
			while(p!=NULL)
			{
				int k = p->adjvex;
				indegree[k]++;
				if (indegree[k]==0)
				{
					V.pop_back();
				}
				p=p->nextarc;
			}
		}
	}
}

// 查找所有的可能存在的拓扑排序结果,深度优先遍历
// 拓扑排序
int TopoSort(ALGraph &G)
{
	stack<int> S;
	int indegree[MAX_VERTEX_NUM];
	int i, count, k;
	ArcNode_AdjList *p;
	FindInDegree(G, indegree);
	// 将入度为0的顶点入栈,即为拓扑排序中可以输出的顶点
	for (i=0;i<G.vexnum;i++)
	{
		if (indegree[i]==0)
		{
			S.push(i);
		}
	}
	count = 0;
	while(!S.empty())
	{
		i = S.top();
		S.pop();
		printf("%c",G.vertexList[i].data); // 输出拓扑排序结果
		count++;
		p=G.vertexList[i].firstArc;
		while(p!=NULL)
		{
			k = p->adjvex;
			indegree[k]--;
			if (indegree[k]==0)
			{
				S.push(k);
			}
			p=p->nextarc;
		}
	}
	if (count<G.vexnum)
	{
		printf("网中有环,拓扑排序出错");
		return -1;
	}
	return 1;
}

// 查找所有的顶点的入度
void FindInDegree(ALGraph &G, int indegree[])
{
	int i,count,k;
	for (i=0;i<G.vexnum;i++)
	{
		indegree[i] = 0;
	}
	for (i=0;i<G.vexnum;i++)
	{
		ArcNode_AdjList *p=G.vertexList[i].firstArc;
		while(p!=NULL)
		{
			indegree[p->adjvex]++;
			p=p->nextarc;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值