实验2.1 实现有向无环图的拓扑排序

// 2.1 邻接表+顺序栈 实现有向无环图的拓扑排序 
#include<iostream>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define MAXSIZE 100  //顺序栈存储空间的初始分配量
#define MAX_NODES 5  // 图的节点数

typedef int Status;
typedef int SElemType;

// 定义栈
typedef struct
{
	SElemType *base;
	SElemType *top;
	int stacksize;	
}SqStack;

// 初始化栈
Status InitStack(SqStack &S)
{  
	S.base = new SElemType[MAXSIZE];
	if(!S.base)
		exit(OVERFLOW);
	S.top=S.base;
	S.stacksize=MAXSIZE;
	return OK;
}

// 入栈
Status Push(SqStack &S,SElemType e)
{
	if(S.top-S.base==S.stacksize)
		return ERROR;
	*S.top=e;
	S.top++;
	return OK;
}

// 出栈
Status Pop(SqStack &S,SElemType &e)
{
	if(S.top==S.base)
		return ERROR;
	S.top--;
	e=*S.top;
	return OK;
}

// 栈的判空
int StackEmpty(SqStack S)
{
	if(S.top==S.base)
		return 1;
	else 
		return 0;
}

// 定义结点 
typedef struct Node 
{  
	int vertex;  
	struct Node* next;  
} Node;  
 
// 定义图 
typedef struct Graph 
{  
	Node* adjList[MAX_NODES];  // 指针数组
	int numNodes;  
} Graph;  
 
// 创建一个新节点  
Node* createNode(int v) 
{  
	Node* newNode = (Node*)malloc(sizeof(Node));  
	newNode->vertex = v;  
	newNode->next = NULL;  
	return newNode;  
}  
 
// 初始化图  
void initGraph(Graph* g, int nodes) 
{  
	g->numNodes = nodes;  
	for (int i = 0; i < nodes; i++) 
	{  
		g->adjList[i] = NULL; // 初始化邻接表  
	}  
}  
 
// 添加边  
void addEdge(Graph* g, int u, int v) 
{  
	Node* newNode = createNode(v);  
	newNode->next = g->adjList[u];  
	g->adjList[u] = newNode; // 将新节点添加到邻接表的头部,前插法 
}  

// 统计节点的入度信息
void FindInDegree(Graph* g,int indegree[])
{
	int i;
	Node* p = (Node*)malloc(sizeof(Node));
	for(i=0;i<MAX_NODES;i++)
		indegree[i]=0;
	for(i=0;i<MAX_NODES;i++)
	{
		p=g->adjList[i];
		while(p!=NULL)
		{
			indegree[p->vertex]++;
			p=p->next;
		}
	}
} 

// 拓扑排序
Status TopologicalSort(Graph* g,int topo[])
{
	int indegree[MAX_NODES],i,m,k;
	FindInDegree(g,indegree);   // indegree[MAX_NODES]数组里存放每个节点的入度信息
	SqStack S;
	InitStack(S);
	for(i=0;i<g->numNodes;i++)
		if(!indegree[i])
			Push(S,i);        // 入度为 0 的节点入栈
	m=0;
	Node* p = (Node*)malloc(sizeof(Node));
	while(!StackEmpty(S))
	{
		Pop(S,i);
		topo[m]=i;           // 排序结果保存在 topo[MAX_NODES]数组中 
		++m;
		p=g->adjList[i];
		while(p!=NULL)
		{
			k=p->vertex;
			--indegree[k];   // 节点的入度减 1
			if(indegree[k]==0)
				Push(S,k);
			p=p->next;       // 入栈节点的邻接节点的入度减 1
		}
	}
	if(m<g->numNodes)
		return ERROR;
	else return OK;
}

int main() {  
	Graph g;
	int topo[MAX_NODES],i;  
	initGraph(&g, MAX_NODES);  
	
	// 创建有向图的边  
	addEdge(&g, 0, 2);  
	addEdge(&g, 1, 2);  
	addEdge(&g, 2, 3);  
	addEdge(&g, 2, 4);  
	addEdge(&g, 3, 4); 
	 
	if(TopologicalSort(&g,topo))
	{
		cout<<"拓扑排序为:"<<endl;
		for(i=0;i<MAX_NODES;i++)
			cout<<topo[i]<<" ";
		cout<<endl;
	}
	else
		cout<<"该有向图存在回路,拓扑排序失败"<<endl;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值