这是最后一篇将机械专业知识与计算机算法结合的博客,觉得这很有意思。而且这个算法与图论有关,图论方面的算法多如牛毛,研究应用数学、拓扑学,计算机等的人一定会对图论有所感知,他也在计算法算法方面占了很大的比重,保罗各种竞赛中也有身影。
图是一种模型,所谓模型就是拿来建模用的。假设我们想要知道某一个工艺流程中设定的各道工序是否会出现死锁,就可以使用图来建模。当然,关于工艺流程、工序时序等知识属于机械专业,有兴趣也可了解了解,毕竟知识多多益善。
当我们把每个工序作为图的点来建模之后,工序与工序之间使用有向线段链接,这就构成了有向图。但是是有向无环图还是有向有环图,这就需要采用线性代数和计算机的知识了。计算机存储图模型多为二维数组或链表结构,而矩阵是可以进行矩阵运算的,这给我们提供了强大的支撑。按照计算机图论的知识将图转化为二维数组M,之后对该矩阵求其n次幂,m从2开始。如果至某个n时矩阵变为0矩阵则该图为无环图。另一方面,如果至某一n时矩阵与M等价(即每个位置上的数对应相等)则为有环图。
无环图对应的生产工序中是没有死锁的,可以正常进行加工。而有环图则会出现死锁,不能加工。
在单纯的计算机算法方面,判断一个有向图是否有环,有拓扑排序可以借用,也可以直接根据图中点和线的对应关系来判断。方法之多,仅举一例:
#include<iostream>
#include <string>
using namespace std;
#define MAX 1024
class Stack //自定义栈
{
string str[10000];
int statop; //最顶元素下标加1
public:
Stack();
void push(string &); // 进栈
void pop();
int getsize(){return statop;} //得到元素个数
};
Stack::Stack()
{
statop=0;
}
void Stack::pop()
{
if(statop!=0)
{
statop--;
cout<<str[statop];
}
}
void Stack::push(string & te)
{
if(statop!=10000)
{
str[statop]=te;
statop++;
}
}
Stack mystack;
int indegree[MAX]; //外面关联图中的入度
struct node
{
int adjvex;
string data;
node* first; //前驱个数(入度)
node* next; //后继,用来减少后面顶点的入度
}adj[MAX];
void Create(node adj[],int n) //建邻接表,n点数
{
int i,j;
for(i=1;i<=n;i++)
{
adj[i].adjvex=i;
cin>>adj[i].data;
adj[i].first=NULL;
adj[i].next=NULL;
}
int u,v,t;
node *p,*pp;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
cin>>t;
if(t==1)
{
u=j;
v=i;
pp=new node;
pp->adjvex=u;
pp->data=adj[u].data;
pp->next=adj[v].next;
adj[v].next=pp;
p=new node;
p->adjvex=v;
p->data=adj[v].data;
p->first=adj[u].first;
adj[u].first=p;
}
}
}
void print(int n)
{
int i;
node *p;
cout<<"前驱:";
for(i=1;i<=n;i++)
{
p=&adj[i];
while(p!=NULL)
{
cout<<p->data<<' ';
p=p->first;
}
cout<<endl;
}
cout<<"后继:";
for(i=1;i<=n;i++)
{
p=&adj[i];
while(p!=NULL)
{
cout<<p->data<<' ';
p=p->next;
}
cout<<endl;
}
}
void topsort(node adj[],int n) //拓扑排序
{
int i,pkm;
node *p,*q;
memset(indegree,0,sizeof(indegree));
for(i=1;i<=n;i++)
{
q=&adj[i];
p=q->first;
while(p!=NULL)
{
indegree[q->adjvex]++;
p=p->first;
}
}
for(i=1;i<=n;i++)
{
if(indegree[i]==0)
{
mystack.push(adj[i].data);
pkm=adj[i].adjvex;
indegree[i]--;
break;
}
}
int count=0;
while(mystack.getsize()!=0)
{
mystack.pop();
cout<<' ';
count++;
for(p=adj[pkm].next;p!=NULL;p=p->next)
indegree[p->adjvex]--;
for(i=1;i<=n;i++)
if(indegree[i]==0)
{
mystack.push(adj[i].data);
pkm=adj[i].adjvex;
indegree[i]--;
break;
}
}
cout<<endl;
if(count<n) cout<<"有回路"<<endl;
}
int main()
{
int n;
cin>>n;
Create(adj,n);
// cout<<"输入的邻接表为:"<<endl;
// print(n);
// cout<<"拓扑排序结果为:"<<endl;
topsort(adj,n);
return 0;
}