您的位置:首页 > 运维架构 > Shell

Warshell's Algorithms

2016-03-29 11:21 561 查看
学习离散数学的时候遇到了这个算法,此算法用于计算闭包矩阵(closure),其复杂度较普通的直接合并的方法要简单,为O(n^3),以下简单介绍一下这个算法~

(以下介绍传递闭包矩阵,其它类型的矩阵与传递闭包思想一致,且相对简单,大家可以自己写写)

1. 思想

2. 代码实现

i) 我们最初知道的仅仅是集合之间元素的关系,那么我们需要知道这个集合内有几个元素,并将它们赋值。

cout<<"The number of element in your set: ";
int size;
cin>>size;
int mySet[size];
for (int i=0; i<size; i++) {
cout<<i+1<<". ";
cin>>mySet[i];
}


这个是非常简单的,就不作解释啦。

ii) 接下来,我们通过集合内元素的关系(relation)来生成关系矩阵,它是n*n的。

首先,我们需要user来告诉我们集合内元素的关系,我们需要定义一种表示关系的符号:

以下, 一组关系内部的两个元素用逗号(",")分隔, 关系之间用冒号(":")分隔。描述结束用q来标志结束。

如:  1,3 : 2,5 :3,2: 3,1 q

表示1到3为一组关系,2到5为一组关系(注意3到1与1到3是不同的关系),以此类推。

这是笔者自己定义的,你们可以自己定义。

这里还需要注意和说明几点:

a) 当user输入的关系中的某个元素是原来集合中没有的元素,我们就需要舍弃这组关系。

b) 这里是用new来声明二维数组,原因在于后面将要使用的函数,在后面会再提到。

bool **mat=new bool *[size];
for (int i=0; i<size; i++) {
mat[i]=new bool[size];
}

c) 这里是用布尔数组,原因是这是一个0-1数组,后面在运算时也将有所简化。

下面是具体实现:

bool **mat=new bool *[size];
for (int i=0; i<size; i++) {
mat[i]=new bool[size];
}
//preset the matrix to zero
for (int i=0; i<size; i++) {
for (int j=0; j<size; j++)
mat[i][j]=0;
}

//transfer relation to relation matrix
int temp;
char ch=0;
int li = 0,ri = 0;//to store the left value and right value in a relation
bool leftGood=false,rightGood=false,leftTurn=true;//good: the element exist;turn for left value to store->true
int index;//the index of the vl;
do {
cin>>temp;
if (cin.std::__1::ios_base::good()) {
if ((index=returnVl(temp, size, mySet))!=-1) {//if the value exist
if (leftTurn) {
li=index;
leftTurn=false;
leftGood=true;
}else if(leftGood){
ri=index;
rightGood=true;
leftTurn=true;
}
}else
{
if (leftTurn) {
leftGood=false;
}else
{
rightGood=false;
}
}
}else
{
cin.clear();
ch=cin.get();
if (ch!=',') {
if (leftGood&&rightGood) {
mat[li][ri]=1;
leftGood=rightGood=false;
}
leftTurn=true;
}
}
} while (ch!='q');

用到的检查是否含有该元素的函数定义(有则返回其index,无则返回-1,因为index不可能是-1):

int returnVl(int vl,int size,int *arr)
{
int i=0;
for (i=0; i<size&&vl!=arr[i]; i++) ;
if((i!=size)||(arr[size-1]==vl))
{
return i;
}else
return -1;
}


这样我们就完成了从关系到关系矩阵的转换。

iii) 接下来我们要计算每一个warshell 矩阵。





复杂度:



这样,我们声明一个函数,来计算Wn.

void wsMat(bool **arr,int size,int n)//to acquire the nth warshall matrix
{
for (int k=0; k<n; k++) {
for (int i=0; i<size; i++) {
for (int j=0; j<size; j++) {
//                if (arr[i][j]==1||(arr[i][k]==1&&arr[k][j]==1)) {
//                    arr[i][j]=1;
//                }
arr[i][j]=arr[i][j]+arr[i][k]*arr[k][j];
}
}
}
}
注释部分为原来的版本,因为是bool数组,修改为现有版本后变得尤为简洁。

现在来解释为什么前面要用new来声明数组,因为我们本可以使用

bool mat[size][size];

来声明。但是,在这里size作为一个variable,导致mat的类型不是bool **,所以在后面作为函数传入时IDE提示no matching function. 所以只能使用前面的方法。(这里笔者还要研究在深入一些)

iv) 输出结果



这里笔者加了3,6这组关系来测试是否会无视这对关系。

总结:

Warshell's Algorithms 的应用主要在于寻找最短路径。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 离散数学