鞍点,二维数组、降维处理、列指针、行指针

PS:以下四种方法都是经过测试AC的,在格式上、运行上、结果上没有问题。但要问我具体的原理,我现在学的还不过关,讲不清楚

【问题描述】

找一个 n* n 的二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小(也可能没有鞍点,若有则仅有一个鞍点)。

请设计函数int Andian(int a[][30], int n)实现之,其中n代表二维数组的行列数,返回值为鞍点,若返回值为0则代表没有鞍点。

【输入形式】

二维数组的行数n,以及每一个数据元素值

【输出形式】

鞍点值或者NO,NO代表没有鞍点

【样例输入】

4

1 7 4 1

4 8 3 6

1 6 1 2

0 7 8 9

【样例输出】

6

【提示】

(1)请将函数定义为int Andian(int * p, int n),那么调用语句为Andian( * a,n),在该函数内部访问具体的数据时,应该用 * (p+i * n+j)的形式。p是列指针。

(2)或者将函数定义为int Andian(int (* p )[30], int n),那么调用语句为Andian(a,n),在该函数内部访问具体的数据时,可以用 * ( * (p+i)+j)的形式。p是行指针。

(3)请编写输入函数进行二维数组数据元素的录入:

void InputArray(int *p, int n);

1. 二维数组方法实现

#include <iostream>
using namespace std;
void InputArray(int a[][30], int n);//二维数组做参数声明时一定要声明列元素个数
int Andian(int a[][30], int n);

int main()
{
    int a[30][30], n, outcome;
    cin >> n;
    InputArray( a, n);//调用时,二维数组直接用数组名调用
    outcome = Andian( a,n);
    if( outcome ) cout << outcome << endl;
    else cout << "NO" << endl;
    return 0;
}

void InputArray(int a[][30], int n)//二维数组录入
{
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)
            cin >> a[i][j];
}

int Andian(int a[][30], int n)
{
    for(int i=0;i<n;++i)//先找每一行的最大值
    {
        int columnIndex=0,rowIndex=0;
        for(int j=columnIndex+1;j<n;++j)//固定行,找列
            if( a[i][j] > a[i][columnIndex] )
                columnIndex=j;//找到第i行的最大值在第columnIndex列

        for(int k=rowIndex+1;k<n;++k)//固定columnIndex列,再找行
            if( a[k][columnIndex] < a[rowIndex][columnIndex] )
                rowIndex=k;//找到第columnIndex列的最小值在第rowIndex行

        if( rowIndex == i )//如果columnIndex列的最小值所在的rowIndex行和大循环的第i行相等,则找到鞍点
            return a[rowIndex][columnIndex];//返回鞍点的值
    }
    return 0;
}

2. 数组降维方法实现

#include <iostream>
using namespace std;
void InputArray(int a[], int n);//做参数传递的时候把数组降维
int Andian(int a[], int n);

int main()
{
    int a[30][30], n, outcome;//定义的时候还是二维的数组
    cin >> n;
    InputArray( &a[0][0], n);//函数调用的时候传递第一个元素地址和每行或每列元素个数
    outcome = Andian( &a[0][0], n);
    if( outcome ) cout << outcome << endl;
    else cout << "NO" << endl;
    return 0;
}

void InputArray(int a[], int n)//降维录入
{
    for(int i=0;i<n*n;++i)//要实现全部数据的录入则循环要执行n*n次
        cin >> a[i];
}

int Andian(int a[], int n)
{
    for(int i=0;i<n;++i)//先找每一行的最大值
    {
        int columnIndex=0,rowIndex=0;
        for(int j=columnIndex+1;j<n;++j)//固定行,找列
            if( a[i*n+j] > a[i*n+columnIndex] )
                columnIndex=j;//找到第i行的最大值在第columnIndex列

        for(int k=rowIndex+1;k<n;++k)//固定columnIndex列,再找行
            if( a[k*n+columnIndex] < a[rowIndex*n+columnIndex] )
                rowIndex=k;//找到第columnIndex列的最小值在第rowIndex行

        if( rowIndex == i )//如果columnIndex列的最小值所在的rowIndex行和大循环的第i行相等,则找到鞍点
            return a[rowIndex*n+columnIndex];//返回鞍点的值
    }
    return 0;
}

3. 列指针方法实现

#include <iostream>
using namespace std;
void InputArray(int *p, int n);
int Andian(int *p, int n);

int main()
{
    int a[30][30], n, outcome;
    cin >> n;
    InputArray( *a, n);
    outcome = Andian( *a,n);
    if( outcome ) cout << outcome << endl;
    else cout << "NO" << endl;
    return 0;
}

void InputArray(int *p, int n)//二维数组录入
{
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)
            cin >> *(p+i*n+j);
}

int Andian(int *p, int n)
{
    for(int i=0;i<n;++i)//先找每一行的最大值
    {
        int columnIndex=0,rowIndex=0;
        for(int j=columnIndex+1;j<n;++j)//固定行,找列
            if( *(p+i*n+j) > *(p+i*n+columnIndex) )
                columnIndex=j;//找到第i行的最大值在第columnIndex列

        for(int k=rowIndex+1;k<n;++k)//固定columnIndex列,再找行
            if( *(p+k*n+columnIndex) < *(p+rowIndex*n+columnIndex) )
                rowIndex=k;//找到第columnIndex列的最小值在第rowIndex行

        if( rowIndex == i )//如果columnIndex列的最小值所在的rowIndex行和大循环的第i行相等,则找到鞍点
            return *(p+rowIndex*n+columnIndex);//返回鞍点的值
    }
    return 0;
}

4. 行指针方法实现

#include <iostream>
using namespace std;
void InputArray(int (*p)[30], int n);
int Andian(int (*p)[30], int n);

int main()
{
    int a[30][30], n, outcome;
    cin >> n;
    InputArray( a, n);
    outcome = Andian( a,n);
    if( outcome ) cout << outcome << endl;
    else cout << "NO" << endl;
    return 0;
}

void InputArray(int (*p)[30], int n)//二维数组录入
{
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)
            cin >> *(*(p+i)+j);
}

int Andian(int (*p)[30], int n)
{
    for(int i=0;i<n;++i)//先找每一行的最大值
    {
        int columnIndex=0,rowIndex=0;
        for(int j=columnIndex+1;j<n;++j)//固定行,找列
            if( *(*(p+i)+j) > *(*(p+i)+columnIndex) )
                columnIndex=j;//找到第i行的最大值在第columnIndex列

        for(int k=rowIndex+1;k<n;++k)//固定columnIndex列,再找行
            if( *(*(p+k)+columnIndex) < *(*(p+rowIndex)+columnIndex) )
                rowIndex=k;//找到第columnIndex列的最小值在第rowIndex行

        if( rowIndex == i )//如果columnIndex列的最小值所在的rowIndex行和大循环的第i行相等,则找到鞍点
            return *(*(p+rowIndex)+columnIndex);//返回鞍点的值
    }
    return 0;
}