关于一道教材题的讲解
前几天上机实验时,做了一道这样的题,感觉还是蛮有趣的,如下所示
也是引发了自己一点小小的思考,以下是我自己的图解:>
#define ROW 4
#define COL 4
int main()
{
int arr[ROW][COL];
int bigger[ROW];//用来储存每一行的最大值.
int putcol[ROW];//用来储存最大值的行数
int putrow[ROW];//用来储存最大值的列数
int tmp1 = 0;//用来获取一行中最大值的那个列数
int tmp2 = 0;//用来获取一行中最大值的那个行数
int i = 0;
int j = 0;
int max = 0;//获取每一行中的最大值.
int count = 0;//用来判断当这个二维数组没有鞍点.
int flag = 1;//用来判断这个二维数组有鞍点
//初始化二维数组
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
scanf("%d", &arr[i][j]);
}
}
//获取每一行的最大值,所在的列数,所在的行数,并将其储存
for (i = 0; i < ROW; i++)
{
max = arr[i][0];
for (j = 0; j < COL; j++)
{
if (max < arr[i][j])
{
max = arr[i][j];
tmp1 = j;
}
}
bigger[i] = max;
putcol[i] = tmp1;
putrow[i] = i;
}
//用来判断这个点是不是鞍点,因为我们刚才已经按照顺序存储了每一行中最大值的列数,将其与那一列的每一个值进行比较。
//第一层for循环是循环每一个最大值的.
for (i = 0; i < ROW; i++)
{
max = bigger[i];
tmp1 = putcol[i];
tmp2 = putrow[i];
flag = 1;//用来判断每一行中的最大值是不是鞍点
for (j = 0; j < ROW; j++)
{
if (max == arr[j][tmp1])// 因为要比较那一列的每一个数,因此难免会与其自身进行比较,因此,当这两个数相等的时候,就什么都不做。
{
;
}
if (max > arr[j][tmp1])
{
flag = 0;//一列中只要有比max还小的值,证明其一定不是鞍点,直接跳出内层循环
break;
}
if(max < arr[j][tmp1])
{
flag = 1;//当每一行中的最大值都是其列上的最小值时,flag为1,证明其有鞍点
}
}
if (flag == 1)
{
count = 1;//有鞍点,令count = 1;没有鞍点的话,count就为0,下面可以直接打印
printf("该二维数组有鞍点\n行数为:>%d\n列数为:%d\n", putrow[i], putcol[i]);
}
}
if (count == 0)
{
printf("该二维数组没有鞍点\n");
}
return 0;
}
首先阐明以下自己的思路,对于本题,我是这样想的,首先求出每一行的最大值,也就是这样子:
然后,我将这三个数放到我们创建的bigger[]数组中,用来对后续其与整列的比较
不仅如此,我还将最大值的列记录下来,放到我们创建的putcol数组中,也是以便用来对后续其一列中的比较。
那么我们为什么要创建putrow数组呢,其实也只是为了方便后面保存并展开循环罢了,因为一行中只有一个最大值,而行的数ROW
由我们界定,因此putrow数组也即为每一行的数字.
我们设置出flag是为了记录此时每一行的最大值是否是鞍点,如果是的话我们赋值为1,如果不是的话我们赋值其为0.
count也是同样道理,如果最终count = 0的话,证明数组没有鞍点,因此我们按照题目要求输出其没有鞍点即可。
思路讲完了,现在来讲一下代码是如何实现的。首先是输入部分
因为设定二维数组,所以需要一个嵌套循环来实现初始化部分,如上图所示。
接下来是重点部分,也即求每一行中的最大值,我们先把max赋值为每一行的第一个数,让其与每一行中的每一个数来进行比较,同时,在求出最大值的时候,记录列数的值
记录到每一行的最大值后,我们将其存储到我们的数组里面去,也即
将max的值存储到bigger数组,将此时最大值的列数存储的putcol数组,将此时的行数存储到putrow数组,为我们后续比大小提供了一定的铺垫。
这些条件准备好之后,也即我们接下来的每一列比大小部分,我是这样子做的
外面一层循环是用来刚才将我们每一行存储的最大值拿出来,里层循环是用来把最大值与那一列的数进行比较,要注意的是,如果max已经比其中一列数大了,那么我们可以直接跳出循环,并且令flag = 0;也即该数不是鞍点。
还有就是,我们与那一列的每一个数进行比较,也就会让它与其本身进行比较,因此,当这个数与其自身进行比较时,我们什么也不干
程序运行的结果为:
下面是对程序进行的改进:
要是在每一行求出的最大值中,在那一列上有与其相等的数呢?,这个时候并不满足鞍点的定义,同时,我认为在其有鞍点的时候令flag = 1 是对余的,因此,我们对程序进行以下改进:
可以看到的是,我对几处进行了改动:
我们知道,当每一行的最大值与其进行比较时,会与它自身进行比较,但我们要怎么区分是他本身,还是与它相等但不同行的数呢?,我们刚才已经将其行号存储到putrow数组中,并且率先将tmp2里面的值放置了其行号,因此,我们可以将行号进行比较,如果行号相同,那么也即为自己与其本身进行比较,我们什么也不干。
这里将每一行的最大值与其每一列的数进行比较,如果有两个数相等并且这两个数在不同的行号,那么这个数必然不是鞍点。
如果大家对代码有什么改进的建议欢迎提出噢!!
下面是改进后的源代码
#define ROW 3
#define COL 4
int main()
{
int arr[ROW][COL];
int bigger[ROW];//用来储存每一行的最大值.
int putcol[ROW];//用来储存最大值的行数
int putrow[ROW];//用来储存最大值的列数
int tmp1 = 0;//用来获取一行中最大值的那个列数
int tmp2 = 0;//用来获取一行中最大值的那个行数
int i = 0;
int j = 0;
int max = 0;//获取每一行中的最大值.
int count = 0;//用来判断当这个二维数组没有鞍点.
int flag = 1;//用来判断这个二维数组有鞍点
//初始化二维数组
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
scanf("%d", &arr[i][j]);
}
}
//获取每一行的最大值,所在的列数,所在的行数,并将其储存
for (i = 0; i < ROW; i++)
{
max = arr[i][0];
for (j = 0; j < COL; j++)
{
if (max < arr[i][j])
{
max = arr[i][j];
tmp1 = j;
}
}
bigger[i] = max;
putcol[i] = tmp1;
putrow[i] = i;
}
用来判断这个点是不是鞍点,因为我们刚才已经按照顺序存储了每一行中最大值的列数,将其与那一列的每一个值进行比较。
//第一层for循环是循环每一个最大值的.
for (i = 0; i < ROW; i++)
{
max = bigger[i];
tmp1 = putcol[i];
tmp2 = putrow[i];
flag = 1;//用来判断每一行中的最大值是不是鞍点
for (j = 0; j < ROW; j++)
{
if (max == arr[j][tmp1] && j == tmp2)// 因为要比较那一列的每一个数,因此难免会与其自身进行比较,因此,当这两个数相等的时候,就什么都不做。
{
;
}
if (max >= arr[j][tmp1]&& j!=tmp2)
{
flag = 0;//一列中只要有比max还小的值,证明其一定不是鞍点,直接跳出内层循环
break;
}
if (max < arr[j][tmp1])
{
flag = 1;//当每一行中的最大值都是其列上的最小值时,flag为1,证明其有鞍点
}
}
if (flag == 1)
{
count = 1;//有鞍点,令count = 1;没有鞍点的话,count就为0,下面可以直接打印
printf("该二维数组有鞍点\n行数为:>%d\n列数为:%d\n", putrow[i], putcol[i]);
}
}
if (count == 0)
{
printf("该二维数组没有鞍点\n");
}
return 0;
}