精华内容
下载资源
问答
  • #编程实现以下需求定义个长度为[16][16]的整型二维数组并输入或指定所有位置的元素值,分别实现二维数组中所有和所有中所有元素的累加和并打印。再分别实现二维数组中左上角到右下角和右上角到左下角所有元素...

    #编程实现以下需求

    定义一个长度为[16][16]的整型二维数组并输入或指定所有位置的元素值,分别实现二维数组中所有行和所有列中所有元素的累加和并打印。再分别实现二维数组中左上角到右下角和右上角到左下角所有元素的累加和并打印。

    解题思路

    1. 定义长度 [16][16] 的二维数组

    2. 输入或指定所有位置的元素值(通过for循环、Random生成随机数为二维数组进行赋值)

    3. 定义行和列、分别计算行和列的累加和并打印(两层循环,外层 i for 循环,内层 j for循环;外层 j for 循环,内层 for循环)

    4. 判断行列值对两个斜对角分别进行累加和并打印(左上右下—— i==j 、右上左下—— i+j == n-1)

    具体过程及用到方法说明

    封装类

    • 私有化成员变量(private)

    cc37c2a5788584f22096b1dedc11ec58.png
    • 提供公有化get和set方法,在方法体中进行判断

    d982aa1d12550dae1c115259926437ef.png
    • 在构造方法中调用set方法

    9b7b7e16bf2e4a7f0002588d09ff4b13.png

    赋值二维数组,利用随机数进行赋值

    获取行和列值,计算各行和、列和对角线和

    9b7b7e16bf2e4a7f0002588d09ff4b13.png

    打印输出各行和、列和、对角线和、数组

    bd0d91eb10f3bc563e0931725d652a7c.png

    测试类(main方法)

    4a5f7b57acd4084977eb6f44960536c9.png

    小结

    知识点:

    1. 封装一个类的三个步骤

    2. 使用Random生成随机数,需提前声明该类

      import java.util.Random;

    展开全文
  • 接下来,为了简化问题,我用个打印字符串数组的函数来代替题目中的函数,来分析这些问题。、问题的出现先按照题目的要求编写如下的函数:#include <stdio.h> void printStr(char* str[], int n) { for ...

    54f97793eeab7b298755a119d2ac3f20.png

    前段时间,在做学校的编程题时,遇到了如上图所示的一道题。在按照题目要求写编写函数时,却发现遇到了错误。

    接下来,为了简化问题,我用一个打印字符串数组的函数来代替题目中的函数,来分析这些问题。

    一、问题的出现

    先按照题目的要求编写如下的函数:

    #include <stdio.h>
    
    void printStr(char* str[], int n) {
        for (int k = 0; k < n; k++) {
            printf("%sn", str[k]);
        }
    }
    
    int main(void) {
        char str[3][3] = {"aa", "bb", "cc"};
        printStr(str, 3);
        return 0;
    }

    当运行这段函数时,会给出如下的信息:

    ee8f0d4f25bf1a93bba6bee2e7556130.png
    并没有按照所想的那样给出输出,并且如果在C++上运行这段代码还会报错

    根据warning和note给出的信息,我们可以知道函数的形参退化成了char**,而我们传递的实参的类型是char(*)[3]与之并不匹配。所以题目出现了错误,接下来我将给出几种正确的传递方式。

    二、几种二维数组传参的常见方式

    1.传递一个二维数组

    在这种方法中,注意只有第一维可以省略。

    #include <stdio.h>
    
    void printStr(char str[][3], int n) {
        for (int k = 0; k < n; k++) {
            printf("%sn", str[k]);
        }
    }
    
    int main(void) {
        char str[3][3] = {"aa", "bb", "cc"};
        printStr(str, 3);
        return 0;
    }

    如果把str[][3]改成(*str)[3]也是可以的,因为在传参的时候多维数组的第一维会退化成指针。

    2.传递一个指针数组

    在这种方法中,我首先创建了一个char*类型的数组,这个数组的每个元素是这个字符串数组中每个字符串的地址。

    #include <stdio.h>
    
    void printStr(char *str[], int n) {
        for (int k = 0; k < n; k++) {
            printf("%sn", str[k]);
        }
    }
    
    int main(void) {
        char str[3][3] = {"aa", "bb", "cc"};
        char* pstr[3]   = {str[0], str[1], str[2]};
        printStr(pstr, 3);
        return 0;
    }

    3.用一维模拟二维

    因为在内存中,不管是几维数组,都是连续的,所以如果我们知道了每一维度的长度信息,就可以用一维数组模拟二维数组。

    #include <stdio.h>
    
    void printStr(char *str, int len, int n) {
        for (int k = 0; k < n; k++) {
            printf("%sn", str + k * len);
        }
    }
    
    int main(void) {
        char str[3][3] = {"aa", "bb", "cc"};
        printStr(str[0], 3, 3);
        return 0;
    }

    三、遇到的问题

    在研究第二种传递方式时,我曾错误地认为二维数组和二重指针是等价的,所以犯了一个如下的错误:

    #include <stdio.h>
    
    void printStr(char* str[], int n) {
        for (int k = 0; k < n; k++) {
            printf("%sn", str[k]);
        }
    }
    
    int main(void) {
        char str[3][3] = {"aa", "bb", "cc"};
        printStr((char**)str, 3);
        return 0;
    }

    运行这段代码后,会发现没有输出结果,在对这段代码进行调试时发现,函数中的*str的值莫名其妙变成了0x6363006262006161,恰好'a','b','c'的ASCII码分别是0x61,0x62,0x63,说这是巧合显然是不可能的。

    首先,我们来分析一下一个二维数组(或者多维)是怎么找到它的某个元素的。

    当我们声明一个多维数组后,它的各个元素在内存中的分布是连续的。(用上面提到的str数组为例,)当我们想要访问str[1]的值时,编译器根据str的地址和第二维的长度计算出str[1]的地址,这样我们就得到了这个字符串数组中第2个字符串的首地址,而这也正是在声明一个多维数组时只有第一维可以省略的原因。

    现在我们来看看指针的原理。

    假定我们声明了一个int*p,并让它指向某一个整形变量a的地址(假定是0x61ac10),那么p在内存中储存了些什么呢?对,就是0x61ac10这个数字。

    接下来,我们再让一个int**pp指向p的地址(假定是0x325146),那么pp里面存了写什么呢?就是0x325146。

    如果我们想要访问a的值,可以通过**pp。当我们这么调用时,系统会先看pp中存储的值,在找到0x325146后,会再次查看这个地址储存的值,接下来再找到0x61ac10就能找到a的值了。

    所以为什么函数中的*str便变成0x6363006262006161呢?假定str的地址是0x61ac10,当它转成char**后,会按照上面所述的方式找到0x61ac10这个地址储存的东西,而这个地方储存的内容是“aa0bb0cc0”,一个指针的大小是八个字节,前八个字节的ASCII码正好就是上面那串奇怪的数字。

    4.关于端序

    还有最后一个问题没解决。按照正常阅读的习惯,我们会认为高位在“左”边,如果是这样那上面那串“地址”应该是0x6161006262006363才对,但事实却与此相反,那只能说明实际储存的值和我的认知是相反的。

    引入端序的概念(感谢@Prcuvu):当我们从内存中读取多个字节组成的数值时,是低地址在低位还是高地址在低位。前者被称作小端序,后者被称作大端序。一般情况下,我们遇到的都是小端序。

    所以,当我们查看*str的值时,它会以小端序的形式读取读取str[3][3]中储存的前八个字节,恰好就是0x6363006262006161。

    5.结语

    至此,由一个二维数组传参引发的问题终于全部得到了解决,在此期间得到了许多同学或朋友的帮助,在此向他们表示感谢。相信本文肯定存在着许多疏漏或者不严谨的地方,希望大家不啬赐教。

    展开全文
  • List1、一维数组2、二维数组无论是一维数组还是二维数组都能通过 list 自带的 sort() 函数进行更新,或者直接调用sorted()方法即可。import numpy as npa = [3,4,5,1,2,3]b = [[3,4,5],[2,3,4]]c = [[3,4,5],[3,3,4]...

    List

    1、一维数组

    2、二维数组

    无论是一维数组还是二维数组都能通过 list 自带的 sort() 函数进行更新,或者直接调用sorted()方法即可。

    import numpy as np

    a = [3,4,5,1,2,3]

    b = [[3,4,5],[2,3,4]]

    c = [[3,4,5],[3,3,4]]

    a.sort()

    b.sort()

    c.sort()

    print(a) #直接调用sorted()方法,print(sorted(a))

    print(b)

    print(c)

    821ec2b6f1ed5e4f57fcebd84552dee9.png

    Array

    1、一维数组

    1)argsort()

    对一维数组进行排序可使用数组自带的a.argsort(),或者使用np.argsort(a)

    >>>np.argsort(a) #按升序排列

    >>> np.argsort(-a) #按降序排列

    另一种降序排列的方法:                                                                                                                                                                    >>> a =

    x[np.argsort(x)]

    >>> a[::-1]

    a = np.array([3,4,5,1,2,3])

    print(a.argsort())     # 同np.argsort(a)

    得到数组的排序索引

    根据索引,我们采用 a[a.argsort()]即可得到

    >>>a[np.argsort(x)] #通过索引值排序后的数组

    >>>a[np.argsort(-x)]

    a = np.array([3,4,5,1,2,3])

    print(a[a.argsort()])

    2二维数组

    1)argsort()

    >>> x = np.array([[0, 3], [2, 2]])

    >>> x

    array([[0, 3],

    [2, 2]])

    >>> np.argsort(x, axis=0) #按列排序

    array([[0, 1],

    [1, 0]])

    >>> np.argsort(x, axis=1) #按行排序

    array([[0, 1],

    [0, 1]])

    2)lexsort()

    lexsort支持对数组按指定行或列的顺序排序;是间接排序,lexsort不修改原数组,返回索引。

    (对应lexsort 一维数组的是argsort a.argsort()这么使用就可以;argsort也不修改原数组, 返回索引)

    >>> a

    array([[ 2,  7,  4,  2],

    [35,  9,  1,  5],

    [22, 12,  3,  2]])

    按最后一列顺序排序

    >>> a[np.lexsort(a.T)]

    array([[22, 12,  3,  2],

    [ 2,  7,  4,  2],

    [35,  9,  1,  5]])

    按最后一列逆序排序

    >>>a[np.lexsort(-a.T)]

    array([[35,  9,  1,  5],

    [ 2,  7,  4,  2],

    [22, 12,  3,  2]])

    按第一列顺序排序

    >>> a[np.lexsort(a.T)]

    array([[22, 12,  3,  2],

    [ 2,  7,  4,  2],

    [35,  9,  1,  5]])

    按最后一行顺序排序

    >>> a.T[np.lexsort(a)].T

    array([[ 2,  4,  7,  2],

    [ 5,  1,  9, 35],

    [ 2,  3, 12, 22]])

    按第一行顺序排序

    >>> a.T[np.lexsort(a[::-1,:])].T

    array([[ 2,  2,  4,  7],

    [ 5, 35,  1,  9],

    [ 2, 22,  3, 12]])

    参考:https://blog..net/qq_20135597/article/details/84204903

    展开全文
  • 记得刚学习C++那会这个问题曾困扰过我,后来慢慢形成了不管什么时候都用一维数组的习惯,再后来知道了在一维数组中提出首元素地址进行二维调用的办法。可从来没有细想过这个问题,最近自己写了点代码测试下,虽然...

    记得刚学习C++那会这个问题曾困扰过我,后来慢慢形成了不管什么时候都用一维数组的习惯,再后来知道了在一维数组中提出首列元素地址进行二维调用的办法。可从来没有细想过这个问题,最近自己写了点代码测试下,虽然还是有些不明就里,不过结果挺有意思。

    为了避免编译器优化过度,用的是写操作,int,测试分为不同大小的空间,同样大小空间不同的行和列数。分别记录逐行写入,逐列写入,按间隔写入,空间申请和释放的时间。

    测试代码

    一维数组的申请和释放

    1 // Create
    2 int *m = new int[n_row * n_col];
    3 
    4 // Free
    5 delete [] m;

    二维数组的申请和释放

    1 // Create
    2 int **m = new int*[n_row];
    3 for ( int i = 0; i < n_row; ++i )
    4     m[i] = new int[n_col];
    5 
    6 // Free
    7 for ( int i = 0; i < n_row; ++i )
    8     delete [] m[i];
    9 delete [] m;

    逐行写入

    1 for ( int i = 0; i < n_row; ++i )
    2 {
    3     for ( int j = 0; j < n_col; ++j )
    4     {
    5         matrix[i * n_col + j] = answer;
    6         // matrix[i][j] = answer;
    7     }        
    8 }

    逐列写入

    1 for ( int j = 0; j < n_col; ++j )
    2 {
    3     for ( int i = 0; i < n_row; ++i )
    4     {
    5         matrix[i * n_col + j] = answer;
    6         // matrix[i][j] = answer;
    7     }        
    8 }

    按间隔写入

     1 for ( int i = 0; i < n_row; ++i )
     2 {
     3     for ( int j = 0; j < n_col; ++j )
     4     {
     5         int row = i * 7 % n_row;
     6         int col = j * 11 % n_col;
     7         matrix[i * n_col + j] = answer;
     8         // matrix[i][j] = answer;
     9     }
    10 }

    不是很确定这种测试是否很合理,不过大体上能体现我要测的东西了。需要注意的是逐行写入中为了简便我用的是写入一个叫answer的变量,其实情况应该更泛化,否则用memset或者std::fill也许会更快?逐列写入的代码本科课程级别的典型反面代码例子,这里也仅仅是为了测试。

    仅仅从编译的角度来看主要的差别在下面两句:

    1 matrix[i * n_col + j] = answer;
    2 matrix[i][j] = answer;

    来看一下对应的汇编代码:

    1 ; matrix[i * n_col + j] = answer;
    2     mov    edx, DWORD PTR _i$3[ebp]
    3     imul    edx, DWORD PTR _n_col$[ebp]
    4     add    edx, DWORD PTR _j$2[ebp]
    5     mov    eax, DWORD PTR _matrix$[ebp]
    6     mov    ecx, DWORD PTR _answer$[ebp]
    7     mov    DWORD PTR [eax+edx*4], ecx
    1 ; matrix[i][j] = answer;
    2     mov    ecx, DWORD PTR _i$4[ebp]
    3     mov    edx, DWORD PTR _matrix$[ebp]
    4     mov    eax, DWORD PTR [edx+ecx*4]
    5     mov    ecx, DWORD PTR _j$3[ebp]
    6     mov    edx, DWORD PTR _answer$[ebp]
    7     mov    DWORD PTR [eax+ecx*4], edx

    都是6条指令,体系学得不好,所以也看不出哪个更快。这里用的是Visual Studio编译,因为本人gcc用得不熟,不知道怎么生成这么直观的汇编和C++对应,效率上而言Linux下还是比Windows高一些,不过为了统一,之后的测试也基于Windows。当然上面的是没有优化的编译,如果开了优化(VS /O2),汇编指令大概也都是4、5条的样子,因为/O2优化后的汇编代码结构不是很直观,这里就不贴了。(另一方面也是由于我的汇编水平很弱,看不出什么)

    除了直接使用一维和二维数组,也可以对一维数组进行二维索引,方法是把一维数组中所有对应第一列的元素的地址单独作为一个指针数组,这样本质上还是一维数组,但是实现了形式上的二维数组调用,这种办法空间申请的代码如下:

    1 // Create
    2 int **m = new int*[n_row];
    3 int *block = new int[n_row * n_col];
    4 for ( int i = 0; i < n_row; ++i )
    5     m[i] = &block[i * n_col];
    6 return m;

    释放的代码和二维数组相同。

    用一维数组模拟二维调用的优点是既保证了内存空间的连续性,又保持了二维调用的代码易维护的优点。不过需要注意的是,由于是二维索引,汇编代码和二维数组还是一样的。

    测试结果

    执行上面的代码,在不同行数和列数下,循环执行取平均值,结果如下:

    内存的申请和释放

    逐行访问

    逐列访问

    按间隔访问

    分析

    内存的连续性:一维数组显然有着比二维数组更好的连续性,我忘了以前是在哪看到的一个形象的字符画说明一维数组和二维数组的区别,大概是下面这样子:

    一维数组:

    ┌--┬--┬--┬--┬- 
    |  |  |  |  | ...
    └--┴--┴--┴--┴-

     二维数组:

    ┌--┬--┬--┬--┬- 
    |  |  |  |  | ...
    └--┴--┴--┴--┴-
      |  |  |
      |  |  V
      |  | ┌--┬--┬--┬-
      |  | |  |  |  | ...
      |  | └--┴--┴--┴-
      |  V
      | ┌--┬--┬--┬--┬-
      | |  |  |  |  | ...
      | └--┴--┴--┴--┴-
      V
     ┌--┬--┬--┬--┬--┬-
     |  |  |  |  |  | ...
     └--┴--┴--┴--┴--┴-

    缓存命中率:缓存是SRAM,内存是DRAM,效率差很多,所以如果能提高缓存中的命中率,效率能提高很多。其实这和上一条其实也有关联,显然连续的内存命中率会高,不过如果申请的内存空间非常大那具体问题得具体分析了。

    指令执行速度:由于早年体系没学好,所以我也不知道这条有多大影响,另外现在的电脑都是多核的,作为不搞多核算法的人,不太懂会有多大影响。

    对照结果可以看到基本上而言一维数组的效率完爆二维数组,尤其是内存申请和小内存访问的情况,总体而言效率上一维数组>一维数组的二维引用>二维数组。不过也有比较有意思的发现:1) 逐行访问的时候,在开辟内存空间小的时候一维数组二维索引效率高于二维数组,而大内存情况下却变慢了。2) 逐列访问基本符合预期,一维数组和一维数组二维索引效率接近,二维索引效率略低,但是都优于二维数组。3) 按间隔访问的时候一维数组大幅快于逐行访问,不太懂这是为什么,是否我电脑是多核的影响?还是说VS的O2编译的作用?

    纯属蛋疼的测试,也相当不严谨,希望有体系知识比较丰富的大拿指点一二。

    转载于:https://www.cnblogs.com/frombeijingwithlove/p/3763250.html

    展开全文
  • 无论是一维数组还是二维数组都能通过 list 自带的 sort() 函数进行更新,或者直接调用sorted()方法即可。 import numpy as np a = [3,4,5,1,2,3] b = [[3,4,5],[2,3,4]] c = [[3,4,5],[3,3,4]] a.sort() b.sort...
  • 大致就是把个我们脑海里的二维数组集合,按照一定的顺序排成一列存储在内存中。这一点比较简单了,如果还是有和我一样的不熟悉的初学者,建议翻翻书、多加巩固。知识的遗忘正常的,多加巩固就好。确定了这一点,...
  • 无论二维数组,还是多维数组,它们本身就是一个一维数组;尤其对于二维数组而言,无非就是一个一维数组,只不过该一维数组中的每一个元素另一个一维数组罢了! int[][] matrix=new int[m]...
  • 稀疏数组本质上还是一个二维数组,属于有序数列,只不过其存放数据的位置有其特殊的意义。稀疏数组可以看作对二维数组一种压缩后的描述,极大的节省了数据存放空间和数据读取时间。 稀疏数组的定义: 稀疏数组...
  • 曾经以为排序只能使用list的...无论是一维数组还是二维数组都能通过 list 自带的 sort() 函数进行更新,或者直接调用sorted()方法即可。 import numpy as np a = [3,4,5,1,2,3] b = [[3,4,5],[2,3,4]] c = [[3,4,...
  • 如何获取二维数组

    千次阅读 2018-01-23 10:25:27
    答案还是Length属性,因为二维数组的每一维都可以看做一个一维数组,而一维数组的长度可以使用Length属性获得。例如,下面代码定义一个不规则二维数组,并通过遍历其行数、数,输出二维数组中的内容,代码如下:...
  • 既然要在个二维数组中找数,那么就要将需要寻找的数字与二维数组中的数字进行比较,又因为该二维数组是有序排列的,所以我们为了在这个二维数组中寻找个数,一定要知道在比较完大小之后,下来需要同哪个数作比较. ...
  • Java二维数组

    2020-02-20 10:33:58
    维数组是一个特殊的一维数组,是由一个由组成的一个表格,矩阵Matrix其每一个元素都是一个一维数组,例如: String str[][] = new String[3][4]; 我们在这个矩阵中访问元素的话,是根据元素的角标和...
  • 维数组的结构为array[][行]array.size代表的是行。这个要看array的定义了。array直接指的外面层,则为行数。array[0].size代表的是,这个好理解2.搜寻思路:从最后一行还是搜寻,查找,从而调整数和行数。...
  • 二维数组中的查找题目描述:在一个二维数组中(每个一维数组的长度相同),每一都按照从左到右递增的顺序排序,每一都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组...
  • 关于二维数组

    2020-02-20 10:43:15
    二维数组:其实就是一个由的表格,我们也称之为...无论二维还是多维数组,其本身就是一个一维数组。尤其对于二维数组而言,无非就是一个一维数组,只不过,该一维数组的每一个元素,又一个一维数组 举...
  • Java 二维数组

    2020-02-20 19:55:25
    无论二维数组,还是多维数组,其实它们本身就是一个一维数组;尤其对于二维数组而言,无非就是一个一维数组,只不过该一维数组中的每一个元素另一个一维数组罢了! 二维数组:二维数组行列组成的表格,格子中...
  • 参数:1)(x,y)为一维数组要变为xy的二维数组,也可以(x,y,z)的三位数组 返回值:数组。将一维的数组变为多维的数组。 注意:reshape函数生成的新数组和原始数组公用一个内存,也就是说,不管改变新数组...
  • 二维数组 ...无论二维数组,还是多维数组,它们本身就是一个一维数组 尤其对于二维数组而言,无非就是一个一维数组,只不过该一维数组中的每一个元素另一个一维数组罢了! 二维数组: 二...
  • Lei ❤ 二维数组

    2020-02-21 20:31:43
    二维数组就是在一位数组上多加了维度,把一位数组比作直线,那么二维数组就是面,由组成的表格,也可以把它看成一个矩阵,所以访问二维数组的...数组是存储在堆内存中的,那么二维数组就是把多个一维数组拼接...
  • python中如何使用二维数组在Python中,个像这样的多维表格可以通过“序列的序列”实现。...python 如何定义动态二维数组Python中创建二维列表/数组,即创建个list,并且这个list的元素还是list。可以用...
  • 维数组旋转

    2021-01-18 10:00:17
    这个题我可想了好久,第一想法直接用另一个二维数组把旋转后的数放在新的数组中,但是要求不能用新数组,后来我又想用一个一维数组做暂存数组用来实现每一每一的数组交换,如果实现,虽然用了一维数组但比二维...
  • 维数组及相关习题

    2020-02-23 16:05:24
    无论二维数组,还是多维数组,它们本身就是一个一维数组 尤其对于二维数组而言,无非就是一个一维数组,只不过该一维数组中的每一个元素另一个一维数组罢了! 用图来具体解释一下 : 如何创...
  • 个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成个函数,输入这样的个二维数组个整数,判断数组中是否含有该整数。 1 2 8 9 2 4 9 12 4 7 10 13 6 8...
  • 二维数组:其实与一维数组类似,不过一维数组是吧许多个单个元素加上标号,比如a[0],a[1],a[2]…,我们使用时可以直接通过控制标号来实现对于数组中元素的控制,二维数组是将很多一维数组标号,比如我们定义a[3][10]...
  • 老是记不住, 还是转载一下网上的吧.//定义二维数组写法1class numthree{public static void main(String[] args){float[][] numthree;//定义个float类型的2维数组numthree=new float[5][5];//为它分配55的...
  • C语言之二维数组

    2016-11-03 21:18:00
    维数组 还是一个数组,只不过数组中得每个元素又是一个数组 ...//23的二维数组,保存的数据类型int类型 char chs[3][5];//35的二维数组,保存的数据类型char类型 2). 初始化...
  • 使用、二维数组格式相关说明源码运行结果 格式 int a[][]=new int[4][5];//四 int b[]=new int[3];//三个元素 错误用法:int a[4][5]; 创建指定范围的数组如此用 相关说明 指定范围的数组,终究还是一个元素...
  • 维数组与指针

    2019-12-07 19:37:09
    一般来说我们在学习一维数组的时候常常对应的就是一维指针 但二维数组的对应关系则要复杂的多 按照老师的说法就是对应的就是一个二级指针 而对应的就是一个一级指针 下面我们用一些实例来进一步说明` #include...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 262
精华内容 104
关键字:

一维数组是行还是列