数据结构之拓扑排序

/*
示例数据:
4 5
a b c d
1 0 1
1 2 5
1 3 6
0 2 8
0 3 2
输出:
1 0 2 3
*/ 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
using namespace std;
#define MVNum 100   //最大顶点数 
#define OK 1
#define INIT_SIZE 100 
#define STACKINCREMENT 10 
#define Error 0 
#define True 1 
#define False 0 
typedef int SElemType;
typedef int Status;
typedef int ElemType;
typedef int OtherInfo;
typedef char VerTexType;

//邻接表存储有向图 
typedef struct ArcNode{
	int adjvex;
	struct ArcNode *nextarc;
	OtherInfo info;  //权值 
}ArcNode;

typedef struct VNode{
	VerTexType data;
	ArcNode *firstarc;
}VNode, AdjList[MVNum];

typedef struct {
	AdjList vertices;
	int vexnum, arcnum;
}ALGraph;

//定义栈 
typedef struct{
	ElemType *base;
	ElemType *top;
	int stacksize;
}SqStack;
//int topo[MVNum]; 全局变量,关键路径可用 

Status InitStack(SqStack *s);
Status ClearStack(SqStack *s);
Status StackEmpty(SqStack *s);
Status Destroy(SqStack *s);
Status GetTop(SqStack *s, SElemType &e);
Status Push(SqStack *s, SElemType e);
Status Pop(SqStack *s, SElemType *e);

Status  CreateALGraph(ALGraph &G)
{
	int i, j, k;
	ArcNode *e;
	cout << "输入顶点数和边数:" << endl;
	cin >> G.vexnum >> G.arcnum;
	cout << "输入顶点信息" << endl;
	for (i = 0; i < G.vexnum; i++) /* 读入顶点信息,建立顶点表 */
	{
		cin >> G.vertices[i].data;
		G.vertices[i].firstarc = NULL;
	}
	cout << "输入点i到点j及权值(从0开始):" << endl;
	for (k = 0; k < G.arcnum; k++)/* 建立边表 */
	{
		int quan;
		cin >> i >> j >> quan; /* 输入边(vi,vj)上的顶点序号 */
		e = new ArcNode; /* 向内存申请空间,生成边表结点 */
		e->adjvex = j; /* 邻接序号为j */
		e->info = quan;
		e->nextarc = G.vertices[i].firstarc;    /* 将e的指针指向当前顶点上指向的结点 */
		G.vertices[i].firstarc = e;   /* 将当前顶点的指针指向e */
	}
	return OK;
}

void FindInDegree(ALGraph G, int indegree[])
{
	int i;
	for (int i = 0; i < G.vexnum; i++)
	{
		indegree[i] = 0;
	}
	for (i = 0; i < G.vexnum; i++)
	{
		while (G.vertices[i].firstarc)
		{
			indegree[G.vertices[i].firstarc->adjvex]++;
			G.vertices[i].firstarc = G.vertices[i].firstarc->nextarc;
		}
	}
}

void Toposort(ALGraph G)
{
	int indegree[MVNum];
	int i , k ,b, j = 0;
	ArcNode *p;
	SqStack S;
	FindInDegree(G, indegree);
	InitStack(&S);
	for (int i = 0; i < G.vexnum; i++)
	{
		if (!indegree[i])
			Push(&S, i);
	}
	int m = 0;
	while (!StackEmpty(&S))
	{
		Pop(&S, &i);
		topo[m] = i;
		++m;
		//count++;
		p = G.vertices[i].firstarc;
		while (p != NULL)
		{
			k = p->adjvex;
			--indegree[k];
			if (indegree[k] == 0) Push(&S, k);
			p = p->nextarc;
		}
	}
	if (m < G.vexnum)
	{
		cout << "该有向图有环!" << endl;
	}
	else
	{
		cout << "拓扑排序成功,输出顺序为:";
		for (b = 0; b < m; b++)
		{
			cout << topo[b] << " ";
		}
		cout << endl;
	}
}

int  main(int argc, char **argv)
{
	ios::sync_with_stdio(false);
	ALGraph G;
	CreateALGraph(G);
	Toposort(G);
	return 0;
}


//初始化栈 
Status InitStack(SqStack *s)
{
	s->base = (SElemType *)malloc(INIT_SIZE * sizeof(SElemType));
	if (!s->base)
	{
		puts("存储空间分配失败!");
		return Error;
	}
	s->top = s->base;
	s->stacksize = INIT_SIZE;
	return OK;
}

//清空栈 
Status ClearStack(SqStack *s)
{
	s->top = s->base;
	return OK;
}

//栈是否为空 
Status StackEmpty(SqStack *s)
{
	if (s->top == s->base)
		return True;
	else
		return False;
}

//销毁栈 
Status Destroy(SqStack *s)
{
	free(s->base);
	s->base = NULL;
	s->top = NULL;
	s->stacksize = 0;
	return OK;
}

//获得栈顶元素 
Status GetTop(SqStack *s, SElemType &e)
{
	if (s->top == s->base) return Error;
	e = *(s->top - 1);
	return OK;
}

//压栈 
Status Push(SqStack *s, SElemType e)
{
	if (s->top - s->base >= s->stacksize)//栈满 
	{
		s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!s->base)
		{
			puts("存储空间分配失败!");
			return Error;
		}
		s->top = s->base + s->stacksize;//修改栈顶位置 
		s->stacksize += STACKINCREMENT;//修改栈长度 

	}
	*s->top++ = e;
	return OK;
}

//弹栈 
Status Pop(SqStack *s, SElemType *e)
{
	if (s->top == s->base) return Error;
	--s->top;
	*e = *(s->top);
	return OK;
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值