二维数组的查找及向函数传递二维数组问题

简介:

问题:在一个二维数组中,每行的元素从左到右是递增的,每列元素从上到下是递增的。写一个函数,查找一给定的元素是否在此数组中

输入:一个二维数组,和一个待查找的数

输出:待查找的数在数组中输出“YES",否则输出”NO"

原始思路:最简单思路就是暴力搜索,遍历一遍数组中的元素时间复杂度为O(n2)。但是这样就没有用问题的已知条件(从左到右、从上到下递增),因此不是个好的解法

改进1:从第一行开始找,找到待查元素大的,如果还没找到,接着从第二行开始找,直到找到或到最后一个元素为止(如图),但是如果带查找的元素在最后,还得遍历到最后,时间复杂度还是O(n2)

        

改进2:上来在随机在里面挑一个,如果正好逮住,那就结束了;如果比待查找的元素大,那么他的左边和上边;否则在右边和下边。如下图。这样下来可以减少一部分元素的比较。在寻找1时,会话费反而很多时间,并不是个好的解决办法。

            

改进3:看两个比较关键的两个点——左下角和右上角。以右上角为例(如下图)。如果右上角元素等于带查找元素,那就返回真;如果右上角元素大于待查找元素,那就删除右上角元素所在列;否则删除其所在行。依次进行下去。

                  

举例说明
      

参考代码一

复制代码
#include <stdio.h>

int find_value(int a[][4], int value, int x, int y)//(x,y)表示右上角坐标
{
    if ((x >= 0) && (y < 4))
    {
        if (a[x][y] ==  value)
            return 1;
        else if (a[x][y] > value)
            return find_value(a, value, x-1, y);
        else
            return find_value(a, value, x, y+1);
    }

    return 0;
}

int main()
{
    int a[4][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
    int val;
    printf("Enter your number:");
    scanf("%d", &val);
    if(find_value(a, val, 3, 0))
        printf("Yes, find it\n");
    else
        printf("No, not find it\n");

    return 0;
}
复制代码

这里注意几个技术细节问题(c语言):

1.二维数组的定义——第二位长度必须指明

      我们知道一位数组定义可以不指名元素总的个数,例如int a[] = {1, 2, 3},编译器会自动赋值长度为3;对于字符char a[] = {'a', 'b', 'c'},自动赋值为4,(因为字符数组末尾有个默认‘\0’字符)

二维数组的本质也是一维数组,其元素是数组。是数组的数组。但是初始化是第二位必须指明int a[][3]是可以的,但是int a[][]绝对不行的。究其这样设计的原因:int a[][3]={1,2,3,4,5}是定义一个每个元素含有3和整形变量的数组的数组。编译器会自动区分为{{1,2,3},{4,5}},但是如果第二维也给省略了,这样编译器也傻眼了,到底给每个数组赋多大值,是{{1,2,3},{4,5,0}},还是{{1,2,3,4},{5,0,0,0}}还是其他......

2.向函数中传递二维数组

 方法一:形参给出第二维大小

复制代码
#include <stdio.h>
void Find(int a[][3])   //此处必须指明第二维的大小
{
    int i, j;
    for(i=0; i<3; i++)
        for (j=0; j<3; j++)
            printf("%d\n", a[i][j]);
}
int main()
{
    int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    Find(a);
    
    return 0;
}
复制代码

方法二:形参指明指向指针的 数组

复制代码
#include <stdio.h>
void Find(int (*a)[3])
{
    int i, j;
    for(i=0; i<3; i++)
        for (j=0; j<3; j++)
            printf("%d\n", a[i][j]);
}
int main()
{
    int
a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
; Find(a); return 0; }
复制代码

对于方法二:这里怎么理解int (*a)[3]? 做个类比:应该都知道int  *a指指向整形变量的指针,等价于int  (*a)[1],[1]指明个数。那么int (*a)[3]就是指明了3个指针,a指向第一个。不能去掉(),因为*的优先级小于[],对于a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},*a[2]指7。(a[2]指向第2个数组的指针,*取出第一个来)下面程序例证:

复制代码
#include <stdio.h>
void Find(int (*a)[3])
{
    int i, j;
    printf("%d\n", *a[2]);
}
int main()
{
    int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    Find(a);
    
    return 0;
}
复制代码

执行结果是7

对于方法一有个问题:怎么知道二维数组第一维是多大?对于数组是没有函数得知数组的大小,即传给函数一个数组(数组名)不能得出数组的大小,可以利用sizeof函数得出。

3.sizeof

函数是用来得出一个对象或类型名的长度,单位是字节。返回类型为long unsigned int(c语言输出格式为%lu)

语法:sizeof(object) //对象

         sizeof(type)   //类型

例如

复制代码
#include <stdio.h>
int main()
{
    //bool aa;
    char a;
    int c;

    int *i;
    char *j;

    printf("int_c:%lu**type_int:%lu\n", sizeof(c), sizeof(int));
    printf("char_a:%lu**type_char:%lu\n", sizeof(char), sizeof(char));

    printf("int *i:%lu**%lu\n", sizeof(i), sizeof(int));
    printf("char *j:%lu**%lu\n", sizeof(j), sizeof(int));

    return 0;
}
复制代码

通过运行结果分析:

下面看一维数组

复制代码
#include <stdio.h>
int main()
{
    int array[] = {1, 2, 3};

    printf("array:%lu  ###*array:%lu  ###array+0:%lu\n", sizeof(array), sizeof(*array), sizeof(array+0));
    printf("size1:%lu\n", sizeof(array) / sizeof(*array));
    printf("size2:%lu\n", sizeof(array) / sizeof(array[0]));

    return 0;
}
复制代码

运行结果:

 下面看二位数组

复制代码
#include <stdio.h>
int main()
{
    int array[][2] = {1, 2, 3, 4, 5};

    printf("array:%lu  ###*array:%lu  ###array+0:%lu  ##**array:%lu\n", sizeof(array), sizeof(*array), sizeof(array+0), sizeof(**array));
    printf("size1:%lu\n", sizeof(array) / sizeof(*array));
    printf("size2:%lu\n", sizeof(array) / sizeof(array[0]));

    return 0;
}
复制代码

执行结果:

现在回顾先写到程序,貌似不完全符合题意,题目是传入一个二维数组,但是现在能做的的必须是传入第二维的大小,可不可以直接往函数中直接传二位数组呢

4.二维数组传给函数当一维数组用——利用下标转换成一维数组的下标

复制代码
#include <stdio.h>
void Find(int *a, int num)
{
    int i = 0;
    for(; i< num; i++)
        printf("%d\n", a[i]);
}
int main()
{
    int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    Find((int*)a, 9);
    
    return 0;
}
复制代码

*********************好了,修改下思路三***********************

参考代码二:

复制代码
#include <stdio.h>

int  find_value(int *a, int val, int rows, int cols) //val是待查元素。rows是二维数组行数,cols是列数
{
    int row = 0;
    int col = cols-1;
    while(row < rows && col >= 0)
    {
        if (a[row * cols + col] ==  val)
            return 1;
        else if (a[row * cols + col] > val)
            col--;
        else
            row++;
    }

    return 0;
}

int main()
{
    int a[][4] = {1, 2, 8, 9, 2, 4, 9, 12, 4, 7, 10, 13,6, 8, 11, 15};
    int val;
    printf("Enter your number:");
    scanf("%d", &val);
    if(find_value((int*)a, val, 4, 4))
        printf("Yes, find it\n");
    else
        printf("No, not find it\n");

    return 0;
}
复制代码

 




本文转自jihite博客园博客,原文链接:http://www.cnblogs.com/kaituorensheng/archive/2013/04/21/3033284.html,如需转载请自行联系原作者

相关文章
|
29天前
|
存储 编译器 C语言
定义二维数组
定义二维数组
14 1
|
29天前
|
存储 算法 C语言
引用二维数组的元素
引用二维数组的元素
16 1
|
1月前
|
存储 Java C++
如何引用二维数组的元素
在编程中,二维数组是一个非常重要的数据结构,它允许我们在一个单一的变量中存储多个值的集合。二维数组可以看作是数组的数组,即每个元素都是一个数组。这种结构特别适用于存储表格数据,如矩阵、棋盘布局等。
12 0
|
4月前
用几种方法输出二维数组各元素的值。
用几种方法输出二维数组各元素的值。
48 4
|
4月前
二维数组传参的本质
二维数组传参的本质
24 0
二维数组传参的本质
|
5月前
二维数组中的查找
二维数组中的查找
|
8月前
|
存储 索引
函数与数组
函数(function),数学术语。其定义通常分为传统定义和近代定义,函数的两个定义本质是相同的,只是叙述概念的出发点不同,传统定义是从运动变化的观点出发,而近代定义是从集合、映射的观点出发。
|
10月前
|
C语言
函数+数组
c语言学习第四弹
|
11月前
|
索引
labview数组数据一维数组二维数组索引行列元素替换子数组排序
labview数组数据一维数组二维数组索引行列元素替换子数组排序
136 0
|
12月前
二维数组的初始化,下标,遍历,及数组间的赋值
下标: 行下标与列下标都是从0开始。 例如:int a[3][2] = { { 1,2 } , { 3,4 } , { 5,6 } }; 行下标:0 1 2 列下标:0 1 元素表现为: a [0][0] a [0][1] a [1][0] a [1][1] a [2][0] a [2][1] 另一个角度:
213 0