一:拓扑排序的应用: 拓扑排序在生活和社会中应用十分广泛,大多数事情的开始都要基于某些前提或事情的完成,如:在学习过程中,课程的安排就符合拓扑排序,例如我们要学离散数学前就必须有一些数学基础,所以高数的学习就安排在离散数学前。这样的事情十分常见,所以就不细细介绍了。
二:拓扑排序的算法思想:连接表方式
1:建立入度为0的顶点栈,将入度为0的顶点入栈;
2:若顶点栈不为空,重复一下操作,
A:顶点栈退出一个顶点元素,并将该点输出;
B:删除该点与其他顶点相连的有向线段,将与该点相连的所有顶点的入度减1;
C:若A,B操作后存在新的入度为0的顶点则入栈;
3:若输出的顶点数少于总的顶点数,则存在回路。
#include<iostream>
using namespace std;
#define n 9
//邻接表的建立
// 邻接表结构体定义
//表节点结构体
struct arcnode
{
int adjvex; //节点的下标
struct arcnode* next; //表节点指针
};
//表头结构体
struct node
{
int vexdata; //节点数据
int id; //入度
arcnode* fisrtarc; //表头结点指针,指向表节点
}dig[n];
//顶点栈结构体
struct stack
{
int top; //顶点指针
int a[n]; //栈内存,存放顶点的下标
};
//出栈
int pop(stack &s)
{
int t=s.top;
if(s.top>=0)
{
s.top--;
return s.a[t];//返回出栈顶点的下标
}
else
{
cout<<"error\n";
}
}
//入栈
void push(stack &s,int v)
{
if(s.top==n-1)
{
cout<<"error\n";
}
else
{
s.top++;
s.a[s.top]=v;//保存入栈顶点下标
}
}
//邻接表的初始化
void initList()
{
int i,j;
for(int k=0;k<n;k++)
{//邻接表的初始化
dig[k].fisrtarc=NULL;
dig[k].id=0;
dig[k].vexdata=k+1;
}
int f=1;
while(f)
{
cout<<"请输入起点和终点\n";
cin>>i>>j;
if(i>0 && i<=n && j>0 && j<=n)
{//节点i,节点j建立邻接关系
arcnode *arc=new arcnode;
arc->adjvex=j;
arc->next=dig[i-1].fisrtarc;
dig[i-1].fisrtarc=arc;
//表头点j入度+1
dig[j-1].id++;
}
else
{
cout<<"error\n";
}
cout<<"continue 1 break 0\n";
cin>>f;
}
}
//toposort功能实现
void toposort()
{
//初始化栈
stack *s=new stack;
s->top=-1;
//寻找入度为0的顶点并入栈
for(int i=0;i<n;i++)
{
if(dig[i].id==0)
{
push(*s,i);
}
}
int k,j;
int count=0;//计数
arcnode* p=NULL;
while(s->top!=-1)//顶点栈不为空时
{
k=pop(*s);//顶点k出栈
cout<<dig[k-1].vexdata<<" ";
count++;//出栈顶点数+1
p=dig[k-1].fisrtarc;//与顶点k邻接的顶点的下标
while(p)//把顶点k的所有邻接顶点的入度-1
{//删除与顶点k邻接的顶点
j=p->adjvex;//j:顶点k的直接后继顶点的下标
dig[j-1].id--;
//判断入度-1后是否存在入度为0的顶点
if(dig[j-1].id==0)
{//如果入度为0则入栈
push(*s,j);
}//指向顶点k的下一连接点
p=p->next;
}
}
if(count<n)
{//如果count小于n则说明存在回路
cout<<"存在回路\n";
}
}
//main
int main()
{
initList();
toposort();
system("pause");
return 0;
}