OI第二课:二维数组

二维数组的声明

“数据类型 变量名[行数] [列数]”

eg:int a[4][4]

二维数组的使用

表示如上图的五角星所在格子

“变量名文字部分[变量横坐标] [变量纵坐标]”

eg:a[2][1]

例题

0.安排方阵

题目分析

题中已经给出了数组类型为整型,同时提到需要避免不够用的情况,由于计算机从0起计数,所以在考虑到不够用的情况下,应至少声明11*11大小的数组,推荐多开5个,则应为大小15 * 15。在声明好15 *15大小的二维数组后,二维数组内每个格子的值为随机值(野值),而不是0,在没有对这个二维数组初始化为0,即没有对所占用的内存空间初始化前,内存的值仍为上一个所占用此内存的任务所用的值,因此在初始化前,每个格子的值为随机(野值)

实操代码

#include<iostream>
using namespace std;

int main(){
    int a[15][15]={};//在声明二维数组的同时,对其进行初始化为0 

    return 0;
}

1.清空场地

题目分析

根据题目,已知输入范围为n,m∈(-∞,10]则(nmax , mmax )=(10,10),因此,二维数组不能只声明10*10大小的,10 10大小的二维数组对应的(nmax , mmax )=(9,9)。因此应至少声明大小11 * 11,推荐声明大小1515,int a[15][15] 应题目要求对其进行初始化int a[15][15]={ };

实操代码

#include<iostream>
using namespace std;

int main(){
    int a[15][15]={},n,m;
    cin >> n >> m;
    cout << a[n][m] <<endl
    
    return 0;
    
    
    
}

2.展示场地

题目分析

题意为,需要开出一个最小10 * 10 大小的方阵,在方阵内,老师会随即指出一个长宽大小分别为m,n的矩形,检查对应矩形内是否被初始化。题目中提到,极限值为10,则下标最大为10,按照惯例开出15,则int array[15][15]

实操代码

#include<iostream>
using namespace std;

int main(){
    int array[15][15]={},n,m,i,j;
    cin >> m >> n;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            cout << array[i][j] <<" ";

        }
        cout << endl;
    }
    return 0;    
}

3.“最高的同学”

题目分析

据题意可知,输入分为:二维数组属性的输入,即长n宽m;以及二维数组元素(身高h)的输入。

输出分为:将输入的二维数组元素按照输入的二维数组属性进行原样输出,同时输出元素的最大值

输入的有效数据范围:n,m∈[1,10];h∈[100,200]

题目中只提到了n+1个数据,以及数据的实例为身高,但并未直接说明数据类型,考虑实际情况,身高可能为小数例如177.5,因此保险起见,数据类型写为double双精度浮点小数型

实例代码

#include<iostream>
using namespace std;

int main(){
    double array[15][15],maxnum=-1e9;
    int n,m,i,j;
    cin >> n >> m;//输入行列 
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            cin>>array[i][j];//输入二维数组的值
            if(array[i][j]>maxnum){ 
                maxnum=array[i][j];
                //将当前输入数据与最大值相比较
                //如果当前数据大于当前最大值,则将最大值赋值为当前值 
            } 
        }

    }
    //输出
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            cout<< array[i][j] << " ";//输出二维数组
        }
        cout << endl;
    } 
    cout << maxnum; //输出最高值
    return 0;

}

4.最后的请求(已解决)

题目分析

题目为上道题的变式,两题目输入的内容相同,输出略有不同

上道题中输出要求为:

  • 将输入的二维数组元素按照输入的二维数组属性进行原样输出
  • 同时输出元素的最大值

本题目中输出的第一条与上题相同;第二条,要求输出元素最小值所在二维数组中的位置,而不是元素的最大值

题目中已经说明身高为整数,则二维数组的数据类型声明为整型即可int array[15][15]

由于cin >>cout <<语句为自适应输入输出语句,因此也可将二维数组定义为double双精度浮点小数型,即double array[15][15] ,输入输出时会进行数据类型的自适应

但是,假使我们是使用scanf('')printf进行输入输出操作,就不可以将本题中的二维数组定义为double双精度浮点小数型,因为其在输入输出时无法进行自适应

根据输入样例中,最小值为134,在样例输出中对应的输出坐标为2 1即第二行第一列,因此判断,在该题目中,下标应从1开始,而不是0

实例代码

#include<iostream>
using namespace std;

int main()
{
    int array[15][15]={},minx=2e9;
    int m, n, i,j,x,y;//x,y用于存储minx坐标
    cin >> n >>m;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            cin >> array[i][j];//输入数组元素
            if(array[i][j]<minx)
            {
                minx=array[i][j];
                x=i;
                y=j;


            }
        }


    }
    //输出
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            cout<<array[i][j];
            cout << " ";
        }
        cout << endl;


    }
    cout << x <<" "<<y;

    return 0;
}

常见问题:访问越界与死循环

如上述代码,若第29行为for(j=1;i<=m;j++)则会出现在内层循环的结束条件为外层的循环变量的情况

因此会出现访问越界,并形成死循环

5.数据魔方

题目分析

输入依次为输入二维数组n行,m列,以及二维数组内的元素

根据示例可知,要求对输入的数据进行列倒叙排序进行输出,因此,在输出到列的循环中,循环应为j初始为m,持续j--,直至j>=1而不是此前的j++到j<=n故循环操作应为for(j=m;j--;j<=1)

题目中并未说明输入的二维数组的数据类型,对于输入的数据吧,保险起见我们是用double双精度浮点小数型,并使用cincout语句进行自适应输入输出

实例代码

#include<iostream>

using namespace std;

int main() {
    double array[15][15];
    int n, m, i, j;
    cin >> n >> m;

    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            cin >> array[i][j];
        }
    }

    for (i = 1; i <= n; i++) {
        for (j = m; j >= 1; j--) {
            cout << array[i][j] << " ";

        }
        cout << endl;
    }
    return 0;
}

二维数组元素蛇形排序

#include<iostream>

using namespace std;

int main() {
    int array[15][15] = {}, n, m, i, j, cnt;
    cin >> n >> m >> cnt;
    for (i = 1; i <= n; i++)//行循环 
    {
        if (i % 2 == 0)//如果是偶数行
        {
            for (j = m; j >= 1; j--) {
                array[i][j] = cnt;
                cnt++;

            }
        } else {
            for (j = 1; j <= m; j++) {
                array[i][j] = cnt;
                cnt++;


            }
        }
    }
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            cout << array[i][j] << " ";


        }
        cout << endl;
    }
    return 0;
}

二维数组的遍历

任意二维数组的遍历

#include<iostream>
#include<cstdlib>//数学头文件,
using namespace std;
int a[100][100];//创建一个10*10的二维数组 
int main(){
 int n=10,m=30;//规定数组的有效范围为10*30 
 //cin>>n>>m;
 for(int i=0;i<n;++i){//循环条件:创建变量i=0,当i<n时,进入循环 
  for(int j=0;j<m;++j){//循环条件 : 创建变量j=0,当j<m时进入循环 
   //cin>>a[i][j];
   a[i][j]=rand()%5;//将二维数组中的i和j设为随机值,随机值取模于5 ,即随机数的值        不超过5
   
  }
 }
 for(int i=0;i<n;++i){
  for(int j=0;j<m;++j){
   cout<<a[i][j]<<"\t";
  }cout<<endl;
 }
 return 0;
}

二维数组的单行遍历

#include<iostream>
using namespace std;

int main(){
 int a[2][2]={};//声明一个2*2的二维数组
 a[0][0] = 1;
 a[0][1] = 2;

 for(int i=0;i<2; i++)
 {

  cout << a[0][i];

 }
 return 0;
}

二维数组初始化的探究——遍历法

#include<iostream>

using namespace std;

int main(){

 int arry[6][6]={{12,35}

     {33},

     {97},

     {21},

     {38},

     {75},

      };

 for(int i=0;i<=5;i++){

  for(int j=0;j<=5;j++){

   cout<<arry[i][j]<<" ";
  }

  cout << endl;

  }

 return 0;

 }

}

对于一个二维数组,在赋值时,即使任意一行没有附满,即开了3个单位,只赋值了一个单位,则视为对整行数组进行初始化操作,并对被赋值单位进行赋值,即:二维数组中,在花括号内的行,即使没有被赋值的单位也会被初始化,以此推出int array[2][2]={},花括号=初始化

从右上到左下遍历

例题

题目分析

如图,本题目实际上是一个从右上到左下的单项多条对角线的输出规律

横向共m行,与横向相连接的对角线共计m条。纵向n列,仅与纵向相连,未与横向相连的对角线共计n-1条;因此,共计有 m+n-1 条对角线

对于前m条对角线来说,对角线一定是从第一行开始,即起始点对应的行的序数一定为1;并且是从第一列分布到第1m列结束,即起始点对应的列的序数时1~m

所以剩下的n-1条对角线来说,即起始点对应的行的序数从1开始递增(++)到n-1结束;对应的列数始终为第m

因此,我们仍采用对角线区分,分为两部分,前m条对角线一部分,后n-1条对角线一部分

并且,由于关于对角线的循环次数不固定,因此我们需要使用while循环,

同时满足行最后指向的位置不能超过第一行、列最小=1,因此应该为while(h<=m && l>=1)

数字矩阵

反之字矩阵

反之字矩阵,即从下至上从右至左方向的蛇形二维矩阵

问题分析

根据本题,可以总结出主要的考察是对于反之字矩阵的输出

即从下至上从右至左方向的蛇形二维矩阵

此时,输出的两种顺序从右至左、从左至右同时出现,且与矩阵的奇数/偶数行无直接关系

因此,我们可以定义一个布尔类型的变量flag用于切换两种输出顺序

(因为布尔类型具有非真既假,非1即0的双面性,符合我们对于两种状态的切换需求,故选用布尔类型)

我们默认为最下面,即循环开始的一行所对应的状态为true,则次行的状态为false,即进行取反操作flag = !flag

实例代码

#include<iostream>
using namespace std;
int main()
{
 int array[105][105],n,m,i,j;
 int cnt=1;//填充矩阵的数字,初始值为1
 bool flag=true;
 cin >> n >> m;
 for(i=n; i>=1; i--) //共计n行,故从1开始,若从0开始,则到n-1时是n行 顺序从下到上,i--
  {
   if(flag==true)//输出顺序:右—左
    {
     for(j=m; j>=1; j--)
      {
       array[i][j]=cnt++;//输出赋值

      }
    }
   else//输出顺序:左—右
    {
     for(j=1; j<=m; j++)
      {
       array[i][j]=cnt++;
      }
     flag =!flag;
    }
  }

 for(i=1; i<=n; i++)
  {
   for(j=1; j<=m; j++)
    {
     cout << array[i][j] <<" ";
    }
   cout << endl;
  }


 return 0;
}

蛇行矩阵

问题分析

输入n,n同时表示输出矩阵的行和列,因此,输出的矩阵一定为一个正方形矩阵,1且,矩阵的输出顺序的对角线排列共有2n-1条对角线

根据实例内容,该题目实际是进行了一个斜对角线的输出排序,输出顺序如图

由图我们可知,第奇数条对角线的方向永远是左下至右上 ,第奇数条对角线的方向永远是右上至左下

  • 当对角线的方向为左下至右上时(即第奇数条对角线),行序递减,列序递增 i--;j++
  • 当对角线的方向为右上至左下时(即第偶数条对角线),行序递增,列序递减 i++;j--

因此,我们需要考虑到三个平面位置因素,行i、列j、对角线k,因此我们需要三层for循环来遍历这个二维数组

并且,由于对角线的变化是最慢的,因此,对角线k应处于最外层循环,行i应处于中层循环,列j应处于最内层循环

==Tip:

对于多层嵌套循环体来说,最内层循环变化最快,越靠外层的循环体变化速度越慢,最外层循环变化最慢==

同时,我们可以发现,对于矩阵内的一个位置的行、列、所在对角线满足i + j = k - 1的关系

实例代码

//一个数取模于2等于0,即被2整除,则说明该数字为偶数
#include<iostream>
using namespace std;
int main()
{
 int array[105][105],n,i,j,k,cnt=1;
 cin >> n;

 for(k=1;k<=2*n-1;k++) //对角线
  {
   if(k%2==0)//向下(左下)走 偶数行
    {
     for(i=0; i<n; i++)
      {
       for(j=n-1; j>=0; j--)
        {
         if(i+j==k-1)
          {
           array[i][j]=cnt++;
          }

        }
      }想·
    }
   else //奇数行 向右上走
    {
     for(i=n-1; i>=0; i--)
      {
       for(j=0; j<n; j++)
        {
         if(i+j==k-1)
          {
           array[i][j]=cnt++;
          }
        }
      }
    }
            }
  for(i=0;i<=n;i++)
  {
    for(j=0;j<=n;j++)
    {
     cout<< array[i][j]<<" ";
    }
   cout << endl;
  }
  
 return 0;
}

环形矩阵

题目分析

根据题目,输入的一个变量n代表了输出矩阵的一个圈数,每圈圈内数字相同,且数字随圈层由外到内递增

也就是说,当输入n圈时,矩阵的长和宽均为2n-1 ,因此最外层填充时i应该到2n-1 结束,随层数k增加而变化为2n-k

因此,我们需要考虑到三个平面位置因素,行i、列j、圈层k,因此我们需要三层for循环来遍历这个二维数组

并且由于圈层的变化是最慢的,因此圈层k应处于最外层循环

由于输出矩阵填充的数字和就是其圈层,因此无需设置填充的数字的变量cnt ,直接填充圈层序数k

==本题涉及到了多层嵌套循环,因此应注意避免死循环以及访问越界的问题==

实例代码

#include<iostream>
using namespace std;
int main()
{
 int array[205][205],n,i,j,k;
 cin >> n;
 for(k=1; k<=n; k++) //圈层
  {
   for(i=k; i<=2*n-k; i++)
    {
     for(j=k; j<=2*n-k; j++)
      {
       array[i][j]=k;
      }
    }
  }
 for(i=1; i<=2*n-1; i++)
  {
   for(j=1; j<=2*n-1; j++)
    {
     cout << array[i][j] << " ";
    }
   cout << endl;
  }

 return 0;
}

总结

本篇作者:Eason 审校:汐湫

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇