杨氏矩阵。

我们仔细分析,不难发现,对于杨氏矩阵老说,右上角和左下角的元素是有特点的。右上角的元素是一行中最大的,一列中最小的。左下角的元素是一行中最小的,是一列中最大的。所以我们可以从右上角或者左下角开始查找。比如:从右上角开始查找的时候,右上角的元素比我们要查找元素小,我们就可以去掉右上角元素所在的这一行;右上角的元素比我们要查找的元素大,我们就可以去掉右上角元素所在的这一列。然后依然找右上角的元素继续和要查找的元素与比较。这样每一次比较去掉一行或者去掉一列。这个查找效率是高于遍历数组元素的,所以时间复杂度是小于O(N),也满足题目要求。

最终效果:

初步代码实现:

#include <stdio.h>
 
int findnum(int a[][3], int x, int y, int f) //第一个参数的类型需要调整,因为二维数组的行可以省略,列不能省略。
{
    int i = 0, j = y - 1; //从右上角开始遍历
    while (j >= 0 && i < x)
    {
        if (a[i][j] < f) //比我大就向下
        {
            i++;
        }
        else if (a[i][j] > f) //比我小就向左
        {
            j--;
        }
        else//如果不大不小那就是找到了

        {
            return 1;//找到了就返回1
        }
    }
    return 0;//没找到就返回0
}
 
int main()
{
    int a[][3] = { {1, 3, 5},//一个二维数组
                  {3, 5, 7}, 
                  {5, 7, 9} }; //一个示例
 
    if (findnum(a, 3, 3, 2)==1)//a是二维数组首元素地址,实际上就是a[0][0]a,3,3是3行3列,2是我们要在矩阵中查找的值
    {
        printf("It has been found!\n");//如果返回1的话就显示找到
    }
    else
    {
        printf("It hasn't been found!\n");//否则返回0的话就显示没有找到;
    }
 
    return 0;
}

运行结果:

因为我们的这个数组里没有2

int a[][3] = { {1, 3, 5},//一个二维数组
{3, 5, 7},
{5, 7, 9} }; //一个示例

假设我们把要查找的值换成数组里面存在的值:3

if (findnum(a, 3, 3, 3)==1)//a是二维数组首元素地址,实际上就是a[0][0]a,3,3是3行3列,2是我们要在矩阵中查找的值
{
printf("It has been found!\n");//如果返回1的话就显示找到
}
else
{
printf("It hasn't been found!\n");//否则返回0的话就显示没有找到;
}

运行结果:

显示找到了。


但是这样我们发现还是不方便,假如我们想换数组,就需要我们重新设置数组的值,想要更换查询的数字也需要更换,比较麻烦。干脆直接用scanf去输入算了。

for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
scanf("%d",&a[i][j]);//输入二维数组

printf("%d ",a[i][j]);//把我们输入的二维数组打印成矩阵
}printf("\n");
}
int n=0;
 printf("请输入一个数:");
 scanf("%d",&n);//输入我们的n值
    if (findnum(a, 3, 3, n))//直接传过去一个n值,n就是我们要查找的数字。
    {
        printf("It has been found!\n");
    }
    else
    {
        printf("It hasn't been found!\n");
  
    }
 
    return 0;
}

运行结果:


但是,实际上这个代码还是存在问题的,比如说我们这样输入会怎么样:9 8 7 6 5 4 3 2 1

我们发现4明明是存在于矩阵中的,但是运行结果却显示没有找到。

这是因为我们杨氏矩阵的前提是:右上角和左下角的元素是有特点的。右上角的元素是一行中最大的,一列中最小的。左下角的元素是一行中最小的,是一列中最大的。

而如果是逆序打印矩阵的话就不能按这种查找方式了。

所以我们需要对矩阵进行升序排序,让它升序方式打印输出.为了方便,我们直接qsort快排。

qsort(a,9,sizeof(int),cmpunc);
 int cmpunc(const void* a,const void* b)
{
return (*(int*)a-*(int*)b);

}

看一下运行效果:

可以正常找到n值了。

然后我们再设置一个goto 语句,假如矩阵里没有我们输入的n值,那么就让我们重新输入n,直到找到n值为止。

again:
 printf("请输入一个数:");
 scanf("%d",&n);
    if (findnum(a, 3, 3, n))
    {
        printf("It has been found!\n");
    }
    else
    {
        printf("It hasn't been found!\n");
        goto again;
    }
 
    return 0;
}

最终代码:

#include <stdio.h>
 #include<stdlib.h>
int findnum(int a[][3], int x, int y, int f) //第一个参数的类型需要调整,因为二维数组的行可以省略,列不能省略。
{
    int i = 0, j = y - 1; //从右上角开始遍历
    while (j >= 0 && i < x)
    {
        if (a[i][j] < f) //比我大就向下
        {
            i++;
        }
        else if (a[i][j] > f) //比我小就向左
        {
            j--;
        }
        else//如果不大不小那就是找到了

        {
            return 1;//找到了就返回1
        }
    }
    return 0;//没找到就返回0
}
 
 int cmpunc(const void* a,const void* b)
{
return (*(int*)a-*(int*)b);//(*(int*)a-*(int*)b)就是升序。(*(int*)b-*(int*)a)就是降序

}
int main()
{
int i=0;
int j=0;
int n=0;
int a[3][3];
printf("请输入一组数字:");

for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
scanf("%d",&a[i][j]);//输入一个二维数组


}printf("\n");
}
qsort(a,9,sizeof(int),cmpunc);//qsort快排


for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%d ",a[i][j]);//把升序之后的矩阵打印出来
}printf("\n");//i执行一次,j执行5次就换行一次,i执行3次,j执行15次就是个矩阵
}
again://again重新输入n值
 printf("请输入一个数:");
 scanf("%d",&n);
      if (findnum(a, 3, 3, 2)==1)//a是二维数组首元素地址,实际上就是a[0][0]a,3,3是3行3列,2是我们要在矩阵中查找的值
    {
        printf("It has been found!\n");//如果返回1的话就显示找到
    }
    else
    {
        printf("It hasn't been found!\n");//否则返回0的话就显示没有找到;
goto again;//如果没有找到,就跳到again
    }
 
    return 0;
}

最终运行结果:

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙鹏宇.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值