AOV网与拓扑排序

2021-04-01 16:51:12 浏览数 (1)

图解演示拓扑排序的过程

不是AOV网的情况

由下可知,当前图中存在回路,不是AOV网

拓扑排序的数据结构

编程流程

拓扑排序算法伪代码

完整代码

代码语言:javascript复制
#include<iostream>
using namespace std;
#include<stack>
#define MAX 10//最大顶点数为10
//边表结构体
typedef struct EdgeNode
{
	int agjvex;//邻接点域,存储顶点对应的下标
	//int weight;//用来存储权值,对于非网图这里可以不需要
	struct EdgeNode* next;//链域,指向下一个邻接点
}EdgeNode;
//顶点表结构体
typedef struct VertexNode 
{
	int in;//顶点入度
	int data;//顶点域,存储顶点信息
	EdgeNode* firstedge;//边表头指针
}VertexNode,AdjList[MAX];//顶点结构体数组最大长度为10
//图
class Graph 
{
private:
	int verNum;//顶点个数
	int arcNum;//边的个数
public:
	AdjList adjlist;//顶点结构体数组
	Graph(int v[], int n, int e);
	void display();
	int getVerNum()
	{
		return verNum;
	}
};
Graph::Graph(int v[], int n, int e)
{
	verNum = n;
	arcNum = e;
	//初始化顶点数组
	for (int i = 0; i < verNum; i  )
	{
		adjlist[i].data = v[i];
		adjlist[i].firstedge = NULL;
		adjlist[i].in = 0;
	}
	//建立边的关系
	int vi, vj;
	for (int i = 0; i < arcNum; i  )
	{
		cin >> vi >> vj;
		EdgeNode* s = new EdgeNode;
		s->agjvex = vj;
		//头插法
		s->next = adjlist[vi].firstedge;
		adjlist[vi].firstedge = s;
	}
	//计算每个顶点的入度
	for (int i = 0; i < verNum; i  )
	{
		for (int j = 0; j < verNum; j  )
		{
			EdgeNode* edge = adjlist[j].firstedge;
			while (edge)
			{
				if (edge->agjvex == i)
				{
					adjlist[i].in  ;
				  }
				edge = edge->next;
			}
		}
	}
}
//打印顶点表和边表
void Graph::display()
{
	for (int i = 0; i < verNum; i  )
	{
		cout <<"当前顶点的入度:"<<adjlist[i].in<<"  当前顶点信息为:" <<adjlist[i].data << "-->";
		EdgeNode* move = adjlist[i].firstedge;
		while (move)
		{
			cout << move->agjvex << " ";
			move = move->next;
		}
		cout << endl;
	}
}
//拓扑排序
void TopologicalSort(Graph g)
{
	//1.栈s初始化,累加器count初始化
	stack<VertexNode> s;
	int count = 0;
	//2.扫描顶点表,将没有前驱的顶点入栈
	for (int i = 0; i < g.getVerNum(); i  )
	{
		if (g.adjlist[i].in == 0)
		{
			s.push(g.adjlist[i]);
			//入完栈之后,把该节点的in设置为-1,防止下次重复入栈
			g.adjlist[i].in = -1;
		}
	}
	//3.当栈s非空时循环
	while (!s.empty())
	{
		//3.1 Vj=退出栈顶的元素,输出Vj,累加器加1
		VertexNode Vj = s.top();   
		s.pop();
		cout << Vj.data << " ";
		count  ;
		//3.2  将顶点Vj的各个邻接点的入度减一
		EdgeNode* move = Vj.firstedge;
		while (move)
		{
			g.adjlist[move->agjvex].in--;
			move = move->next;
		}
		//3.3 将新的入度为0的顶点入栈(这里注意,之前入过栈的元素不能再次入栈,不然会造成死循环)
		for (int i = 0; i < g.getVerNum(); i  )
		{
			if (g.adjlist[i].in == 0)
			{
				s.push(g.adjlist[i]);
				//入完栈之后,把该节点的in设置为-1,防止下次重复入栈
				g.adjlist[i].in = -1;
			}
		}
	}
	//4.if(count<vertexNum)输出有回路信息
	cout << endl;
	if (count < g.getVerNum())
	{
		cout << "有回路" << endl;
	}
}
void test()
{
	int v[6] = { 0,1,2,3,4,5 };
	Graph g(v,6,9);
	cout << "打印顶点表和边表" << endl;
	g.display();
	cout << "拓扑序列: " << endl;
	TopologicalSort(g);
}
int main()
{

	test();
	system("pause");
	return 0;
}

0 人点赞