NOI OJ 1.8 23:二维数组回形遍历(多维数组的遍历) C语言

描述

给定一个row行col列的整数数组array,要求从array[0][0]元素开始,按回形从外向内顺时针顺序遍历整个数组。如图所示:

NOI OJ 1.8 23:二维数组回形遍历(多维数组的遍历) C语言_第1张图片

输入

输入的第一行上有两个整数,依次为row和col
余下有row行,每行包含col个整数,构成一个二维整数数组。
(注:输入的row和col保证0 < row < 100, 0 < col < 100)

输出

按遍历顺序输出每个整数。每个整数占一行。

(作为一个水娃,总算更新了,给大伙来个好玩的题)

有人问我这道题,说是找不到做这题的思路,即使经过我的提示后还是一筹莫展,我感觉这题是二维数组遍历的好题,所以更新一下(才不是因为我懒,才不更新)

那我们就从思路开始吧

经过本人比较笨拙的观察,找到了以下的规律: 

1、从左往右,直到边界(边界的概念是可能超出行和列的范围,或者已经遍历过的格子,被默认为超出行和列的范围(下文我会详细介绍如何进行边界的限定))   我把这种情况定义为set1

2、从上到下,直到边界   我把这种情况定义为set2

 

 

3、从右到左,直到边界     我把这种情况定义为set3

 

 

4、从下到上,直到边界     我把这种情况定义为set4

从这里我们可以惊喜的发现,下一个情况就是set1,这四个状态形成了一个循环,我们只要重复这个循环直到循环遍历完毕就行了(是不是听起来十分轻松恰意,你可以看到这里自己先去尝试以下,如果代码实现失败再接着来看我的文章,毕竟我的代码肯定不是最好的)

 细心的小伙伴一定可以发现我们每个情况的开始都是删去了上一个情况的最后一个,这是为了防止重复输出(详情见之后的代码解析)

 

从这张图我们可以明显发现边界的定义更新了,这是怎么回事呢,我们从边界的更新开始。

难点一 : 我们改如何定义边界呢(实际上我的代码有个bug,但是这道题并没有考虑到这个点,所以我边界定义的方法过了,有可以改进的方法,但我懒得提了,基本看完我这篇文章,并理解它的话,自己就可以想出来)

别小看这个边界定义问题,因为这个问题,我从输入就开始考虑了。

int row,col;
	int x[101][101]={0};  //题目说row和col<100所以就都定义了101(这个应该不用解释了吧)
	scanf("%d %d",&row,&col);
	for(int i=1;i<=row;i++){      //注意,我的row是从1开始输入的
		for(int j=1;j<=col;j++){   //我的col也是从1开始输入的,并不像题目里那样从0开始
			scanf("%d",&x[i][j]);
		}
	}

这里开始就有小细节了,也可以发现我定义边界的方法。

就是如果我们在循环我们4个set时,当发现我们set的下一个情况出现的数是0时(我数组进行了初始化,所以除了我们输入的位置,其他地方都是0),我们就跳到下一个set(事实上题目定义的是输入整数,0严格意义上算整数,但是样例里好像并没有,如果有小伙伴需要我把包括0的情况的正确代码发出的话,请在评论区发出你的声音,并给本水娃点个赞,使我拥有更新的动力)

因为题目要求是按照遍历输出每一个整数,重点来了:我们要做到边输出,边更新我们的这个多维数组,来实现我们的边界要求,所以我们要在输出多维数组中这个数后,用0来填充这个位置,形成新的边界(是不是有点懵逼,我们结合代码从set1开始)

等等,我好像漏讲一个点,set都有了,但我们改如何判断结束set的条件呢。很简单,因为数组都要遍历一遍,我们又直到它的长和宽,直接求出他的面积,然后从1开始循环直到它面积的大小即可(总共输出col*row个数,即面积大小)

int height=1,lenth=1,set=1;   //这个会结合set讲
for(int i=1;i<=row*col;i++){  //结合了我之前的讲解应该都听懂了吧

}

set1:(前情提要见上代码,我们定义了height=1和lenth=1,表示初始状态)

所以我们这里的思路什么?

从初始位置开始,我们从左往右开始输出(即保持height不变,length++即可),直到检测此时数组的内容为0,我们把set2的第一个状态传过去传给set2,结束set1。(别忘了随时更新边界哦)(是不是还是比较抽象,我们结合代码分析,一定要仔细看代码后面的注释yo

if(set==1){
			printf("%d\n",x[height][lenth]);  //先输出当前数组的值,因为根据我下面的代码,不会出现越界的问题,所以每个set干的第一件事就是先输出

			x[height][lenth]=0;   //在我们输出数组这个位置的数字后,数组的这个位置就失去意义了,我们就把这里定义成边界

			if(x[height][lenth+1]==0){  //如果发现我们的下一个情况越界了
				set=2;             //首先改变set
				height++;          //然后把改变数据,使set2的第一个情况不是set1的最后一个情况,导致重复输出
				continue;          //一定得加,因为set2定义在下面,如果我们不加,前面定义结束set的循环就是摆设
			}
			else{                //如果下一个情况没有越界
				lenth++;        //set1继续,即height不变,lenth++
				set=1;          //这里加不加都无所谓,但我个人加了感觉会使代码思路更清晰
				continue;       //这里的continue同样可加可不加
			}
		}

set2:

从set1给予的初始位置开始,我们从上往下开始输出(即保持lenth不变,height++即可),直到检测此时数组的内容为0,我们把set3的第一个状态传过去传给set3,结束set2。

f(set==2){    //基本和set1差不多,有些重复的我就不讲了
			printf("%d\n",x[height][lenth]);
			x[height][lenth]=0;
			if(x[height+1][lenth]==0){   //判断set2情况时,下一个数据是否越界
				set=3;            //改变set
				lenth--;          //set3的一个情况要保持height不变,lenth--
				continue;
			}
			else{
				height++;
				set=2;
				continue;
			}
		}

set3:

从set2给予的初始位置开始,我们从右往左开始输出(即保持height不变,len--即可),直到检测此时数组的内容为0,我们把set4的第一个状态传过去传给set4,结束set3。

if(set==3){
			printf("%d\n",x[height][lenth]);
			x[height][lenth]=0;
			if(x[height][lenth-1]==0){  //判断set3情况下,下一个数据是否越界
				set=4;
				height--;     //把set4的第一个情况传下去
				continue;
			}
			else{
				lenth--;
				set=3;
				continue;
			}
		}

set4:

从set3给予的初始位置开始,我们从下往上开始输出(即保持lenth不变,height--即可),直到检测此时数组的内容为0,我们把set1的第一个状态传过去传给set1,结束set4。(到这里我们就完成了set的一次循环,重复这个循环即可)

if(set==4){
			printf("%d\n",x[height][lenth]);
			x[height][lenth]=0;
			if(x[height-1][lenth]==0){  //set4情况下进行判断,因为边界的更新,我们可以很轻松的进行判断
				set=1;              //set的循环
				lenth++;
				continue;
			}
			else{
				height--;    //set1的第一种情况传过去
				set=4;
				continue;
			}
		}

由此我基本把代码的逻辑过了一遍,为了更具体的展示一下思路,我用样例进行一次set的循环

NOI OJ 1.8 23:二维数组回形遍历(多维数组的遍历) C语言_第2张图片

set1:

set2:

set3:

set4:

set1:

set2:

 

set3:

set4:

完整的一套思路已经展示了一遍,相信大家至少有点思考了,下面我把完整的代码发出来,不懂得部分大家边看边往上翻,如果认为我讲的还不错的话,请点个赞支持一下啊!!!!!!!!

 

#include
int main(){
	int row,col;
	int x[101][101]={0};
	scanf("%d %d",&row,&col);
	for(int i=1;i<=row;i++){
		for(int j=1;j<=col;j++){
			scanf("%d",&x[i][j]);
		}
	}
	int height=1,lenth=1,set=1;
	for(int i=1;i<=row*col;i++){
		if(set==1){
			printf("%d\n",x[height][lenth]);
			x[height][lenth]=0;
			if(x[height][lenth+1]==0){
				set=2;
				height++;
				continue;
			}
			else{
				lenth++;
				set=1;
				continue;
			}
		}
		if(set==2){
			printf("%d\n",x[height][lenth]);
			x[height][lenth]=0;
			if(x[height+1][lenth]==0){
				set=3;
				lenth--;
				continue;
			}
			else{
				height++;
				set=2;
				continue;
			}
		}
		if(set==3){
			printf("%d\n",x[height][lenth]);
			x[height][lenth]=0;
			if(x[height][lenth-1]==0){
				set=4;
				height--;
				continue;
			}
			else{
				lenth--;
				set=3;
				continue;
			}
		}
		if(set==4){
			printf("%d\n",x[height][lenth]);
			x[height][lenth]=0;
			if(x[height-1][lenth]==0){
				set=1;
				lenth++;
				continue;
			}
			else{
				height--;
				set=4;
				continue;
			}
		}
	}
	return 0;
}

感谢您的观看(浪费您不少时间)

你可能感兴趣的:(c语言,蓝桥杯,多维数组)