拓扑排序只存在于有向无环图中
实际意义是:衡量任务的优先级,即任务2在做之前,要确保任务1已经完成,也就是工作的流程图,这也是为什么只存在于无环图里面
每次寻找只有出度的任务(顶点)
代码实现也主要借助两个东西,一个是一维数组用来存放某个顶点的入度,另一个就是栈,如果某个顶点入度等于0,就把它入栈,入栈之后把链结表中与这个顶点有联系的所有顶点入度减一,再次判断所有顶点是否入度等于零,重复上面操作。
还有一点就是因为连接表的顺序不同,导致入栈的顺序不同,将会导致出现不同的拓扑排序,但是这没问题哈。。。
/*
拓扑排序
*/
//建立邻接表图
#include <iostream>
#include <malloc.h>
#include <cstdio>
using namespace std;
#define MAX_SIZE 20
#define increase 10
typedef bool status;
typedef struct link
{
int data;//下标
int weiget;//权重
struct link* next;
}*enode;//表结点
typedef struct head_node
{
char data;
struct link* next;
}Head,*head;//头节点
typedef struct graph
{
int vexnum,arcnum;
Head vex[MAX_SIZE];
}*Graph;
typedef struct my_stack
{
int *base;
int *top;
int stack_size;
}*tyust;
//获取位置
int get_pos(Graph pit,char c)
{
for(int i=0;i<pit->vexnum;i++)
{
if(c==pit->vex[i].data)
{
return i;
}
}
return -1;
}
void link_last(enode &father,enode son)
{
while(father->next)
father=father->next;
father->next=son;
}
//创建邻接图
Graph creat_graph()
{
int vexnum,arcnum;
char in1,in2;
int p1,p2;
Graph pit=(Graph)malloc(sizeof(graph));
cout<<"请输入顶点数和边数:"<<endl;
cin>>vexnum>>arcnum;
pit->arcnum=arcnum;
pit->vexnum=vexnum;
cout<<"请输入所有顶点"<<endl;
for(int i=0;i<vexnum;i++)
{
cin>>pit->vex[i].data;
pit->vex[i].next=NULL;
}
for(int j=0;j<arcnum;j++)
{
cout<<"请输入弧边"<<j+1<<endl;
cin>>in1>>in2;
p1=get_pos(pit,in1);
p2=get_pos(pit,in2);
enode my_side=(enode)malloc(sizeof(link));
if(!my_side)cout<<"节点分配错误!!";
my_side->data=p2;
my_side->next=NULL;
//把新的表结点连上去
if(pit->vex[p1].next==NULL)
pit->vex[p1].next=my_side;
else
link_last(pit->vex[p1].next,my_side);
}
return pit;
}
status isempty(tyust &S)//判断是否为空,空的话返回true
{
if(S->base==S->top)return true;
else return false;
}
void stack_init(tyust &S)//栈初始化
{
S=(tyust)malloc(MAX_SIZE*sizeof(my_stack));
if(!S->base)cout<<"分配栈出错"<<endl;
S->top=S->base;
S->stack_size=MAX_SIZE;
}
void stack_push(tyust &S,int e)
{
if((S->top-S->base)==S->stack_size)//
{
S->base=(int *)realloc(S->base,(increase+S->stack_size)*sizeof(int));
if(!S->base)cout<<"栈重新分配错误!!"<<endl;
S->top=S->base+S->stack_size;
S->stack_size+=increase;
}
*S->top=e;
S->top++;
}
void stack_pop(tyust &S,int &e)
{
if(S->base==S->top)cout<<"pop Error!!"<<endl;
e=*(--S->top);
}
void find_indegree(Graph pit,int *indegree)
{
enode p;
for(int i=0;i<pit->vexnum;i++)//入度初始化为零
{
indegree[i]=0;
}
for(int j=0;j<pit->vexnum;j++)
{
p=pit->vex[j].next;
while(p)//指针非空
{
indegree[p->data]++;
p=p->next;
}
}
}
/*
利用一个一维数组和栈
寻找入度等于零的
*/
void topology(Graph pit)//拓扑排序
{
int indegree[MAX_SIZE];//入度数组
int e,k;
tyust S;
enode p;
find_indegree(pit,indegree);//初始化入度
stack_init(S);//初始化栈//这里其实错了,详情看下一篇关键路径,但是在这里却可用,不建议使用
for(int i=0;i<pit->vexnum;i++)
{
if(!indegree[i])//如果入度等于零,入栈
{
stack_push(S,i);
}
}
while(!isempty(S))//如果非空
{
stack_pop(S,e);
cout<<pit->vex[e].data<<" ";
for(p=pit->vex[e].next;p;p=p->next)
{
k=p->data;
if(!(--indegree[k]))//入度减一,若为0,则入栈
{
stack_push(S,k);
}
}
}
}
int main()
{
Graph pit=creat_graph();
topology(pit);
}