图(有向图)的应用——拓扑排序

1、基本概念:

有序图,每个顶点都有前驱和后继的关系。

现实生活中我们可以用一个有向图来表示一个工程,顶点表是活动,有向边A———->B表示:A必须先于活动B进行。这种有向图叫做“  顶表示活动的网络(activity  on  vertices)”

——记作AOV网络。

将全部顶点都排在一个线性有序的序列中。这种构造AOV网络全部顶点的拓扑有序序列的运算就叫做拓扑排序(topological  sorting)

2、步骤:

(1)选择一个没有直接前驱的顶点,并输出;

(2)从图中删除该顶点,同时删去所有它发出的有向边;

(3)依次循环以上两步,直到:全部顶点已经输出(排序结束),或被迫跳出循环(图中存在环)

(注意理解代码中有个模仿栈结构的top“指针”和count入度数组)

	void TopologicalSort()
	{
		int i,top=-1;
		for(i = 0;i<numVertexs;++i)
		{
			if(count[i] == 0)
			{
				count[i] = top;
				top = i;//top是用下标表示
			}
		}
		for(i = 0;i<numVertexs;++i)
		{


			if(top == -1)
				cout<<"Have a circle..."<<endl;
			else
			{
				int j = top;
				top = count[j];
				cout<<myv[j].data<<"-->";
				EdgeNode *l = myv[j].link;
				while(l)
				{
					int k = l->dest;
					if(--count[k] == 0)//这里的--是将l所指出去相连的边都删掉。
					{
						count[k] = top;
						top = k;	
					}	
					l = l->next;
				}
			}
		}
	}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once
#include"AllHead.h"
#define MAXSIZE 20
//单向图。
class EdgeNode;

template<class T>
class GrapHVec;

template<class T>
class VertexList
{
	friend class GrapHVec<T>;
private:
	T data;
	EdgeNode *link;
public:
	VertexList():link(NULL)
	{}
	~VertexList(){}
};
class EdgeNode
{
public:
	int dest;
	EdgeNode *next;
public:
	EdgeNode()
	{
		next = NULL;
	}
	~EdgeNode(){}
};
template<class T>
class GrapHVec
{
private:
	VertexList<T> *myv;
	int maxSize;//最大
	int numVertexs;
	int numEdges;
	int *count;//建立一个入度数组
public:
	GrapHVec(int sz=MAXSIZE)
	{
		maxSize = sz<=MAXSIZE?MAXSIZE:sz;
		myv = new VertexList<T>[maxSize];
		count = new int[maxSize];
		for(int i=0;i<maxSize;++i)
			count[i] = 0;
		numVertexs = 0;
		numEdges = 0;
	}
	~GrapHVec(){}
public:
	int GetNextNeighbor(T x1,T x2)
	{
		if(numVertexs == 0)
		{
			cout<<"空(GetFirstNeighbor)...";
			return ERROR;
		}
		int v1 = GetVerticespos(x1);
		int v2 = GetVerticespos(x2);
		EdgeNode *fp = myv[v1].link;
		while(fp!=NULL && (*fp).dest != v2)
			fp = (*fp).next;
		if(fp == NULL)
		{
			//cout<<"不存在有过链接.....";
			return -1;
		}
		fp = (*fp).next;
		if(fp != NULL)
			return (*fp).dest;
		else
		{
			//cout<<"没有下一个结点....";
			return -1;
		}
	}
	int GetFirstNeighbor(T x)
	{
		if(numVertexs == 0)
		{
			cout<<"空(GetFirstNeighbor)...";
			return ERROR;
		}
		int v = GetVerticespos(x);
		EdgeNode *fp = myv[v].link;
		if(fp != NULL)
			return (*fp).dest;
		else
		{
			cout<<x<<" :没有链接的结点....";
			return ERROR;
		}
	}
	int GetVerticespos(T x)
	{
		if(numVertexs == 0)
		{
			cout<<"空(Getpos)....";
			return FALSE;
		}
		int i;
		for(i=0;i<numVertexs;i++)
		{
			if(myv[i].data == x)
				return i;
		}
		return -1;
	}
public:
	int NumOfVertices(){return numVertexs;}
	int NumOfEdge(){return numEdges;}
	int InsertVertex(T x)
	{
		if(numVertexs >= maxSize)
		{
			cout<<"空间已满不能插入...."<<endl;
			return ERROR;
		}
		myv[numVertexs++].data = x;
		return TRUE;
	}
	int InsertEdge(T x1,T x2)//A,B:A-->B
	{
		int v1 = GetVerticespos(x1);//A
		int v2 = GetVerticespos(x2);//B
		if(v1 == -1||v2 == -1)
		{
			cout<<"有一个节点不存在"<<endl;
			return ERROR;
		}
		EdgeNode *p1 = new EdgeNode;
		(*p1).dest = v2;
		(*p1).next = myv[v1].link;
		myv[v1].link = p1;
		count[v2]++;
		++numEdges;
	}
	void showVecGrap()
	{
		for(int i=0; i<numVertexs; ++i)
		{
			cout<<i<<":>"<<myv[i].data<<"-->";
			EdgeNode *e = myv[i].link;
			while(e != NULL)
			{
				cout<<e->dest<<"-->";
				e = e->next;
			}
			cout<<"Nul."<<endl;
		}
	}
public:
	void TopologicalSort()
	{
		int i,top=-1;
		for(i = 0;i<numVertexs;++i)
		{
			if(count[i] == 0)
			{
				count[i] = top;
				top = i;//top是用下标表示
			}
		}
		for(i = 0;i<numVertexs;++i)
		{


			if(top == -1)
				cout<<"Have a circle..."<<endl;
			else
			{
				int j = top;
				top = count[j];
				cout<<myv[j].data<<"-->";
				EdgeNode *l = myv[j].link;
				while(l)
				{
					int k = l->dest;
					if(--count[k] == 0)//这里的--是将l所指出去相连的边都删掉。
					{
						count[k] = top;
						top = k;	
					}	
					l = l->next;
				}
			}
		}
	}
};
#include"graphvec.h"
int main()
{
	GrapHVec<char> tp;
	tp.InsertVertex('A');
	tp.InsertVertex('B');
	tp.InsertVertex('C');
	tp.InsertVertex('D');
	tp.InsertVertex('E');
	tp.InsertVertex('F');
	tp.InsertEdge('A','B');
	tp.InsertEdge('A','C');
	tp.InsertEdge('A','D');
	tp.InsertEdge('C','F');
	tp.InsertEdge('D','F');
	tp.InsertEdge('D','B');
	tp.InsertEdge('E','C');
	tp.InsertEdge('E','F');
	tp.showVecGrap();
	cout<<"========================="<<endl;
	tp.TopologicalSort();
	return 0;
}

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/weixin_35909255/article/details/57088256
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞