二维数组小练习

题目描述
给定一个row行col列的整数数组array,要求从array[o][0]元素开始,按从左上到右下的对角线顺序遍历整个数组。

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

例子输入1:

3 4
1 2 4 7
3 5 8 10
6 9 11 12

例子输出1:

1
2
3
4
5
6
7
8
9
10
11
12

例子输入2:

4 5
1 2 4 7 11
3 5 8 12 15
6 9 13 16 18
10 14 17 19 20

例子输出2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

解法一:拟人法

将需要实现的部分分成两部分:

1 找到合适的起点;

2 由起点开始,向左下方向遍历数组。

#include<stdio.h>
int a[100][100];
int ROW;

void biu( int a[100][100],int col,int row){//向左下方向遍历数组,遇底边界或左边界停止
	while(col>=0 && row<ROW){
		printf("%d\n",a[row][col]);
		col--;
		row++;
	}
}
	
main(){
	int COL;

	scanf("%d %d",&ROW,&COL);//设置长宽
	for(int i=0;i<ROW;i++){//输入二维数组数据
		for(int j=0;j<COL;j++){
			scanf("%d",&(a[i][j]));
		}
	}
	
	int row=0,col=0;
	do{
		biu(a,col,row);
		col++;	
	}while(col<COL-1);
	
	do{
		biu(a,col,row);
		row++;
	}while(row<ROW);
	
	
}

其中,自定义的“biu"函数实现上述第二个部分(由起点开始,向左下方向遍历数组),并能遇底边界或左边界停止。

通过两个do-while循环结构实现起点由顶边到右侧边依次移动。起点移动过程如下图:

解法二:函数法/定值法

观察可得,遍历的每斜行row与col之和为定值(row+col=k)。即row=-col+k,整数函数。

但是,所给的数表并不一定为正方形。如何控制好边界是难点。

先放大范围,找出长边(“max”),将范围扩大至边长为max的正方形数表。

而按照和为定值的方式遍历难免再次放大范围,将范围扩大为了正方形数表面积两倍的三角形。

 那么如何缩小范围呢?

在输出时加入了输出模块,该模块会将数的坐标位置与原数表范围作比较,以此筛去无用数字。

输出有效的数字,实现功能。

#include<stdio.h>
main(){
	int ROW,COL;
	int a[100][100];
	scanf("%d %d",&ROW,&COL);//设置长宽
	for(int i=0;i<ROW;i++){//输入二维数组数据
		for(int j=0;j<COL;j++){
			scanf("%d",&(a[i][j]));
		}
	}
	
	//找出最大值
	int max;
	if(ROW>=COL) max=ROW;
	else max=COL;
	
	int col,row;
	for(int i=0;i<2*max;i++){//找出正方形数组的右下顶点的col与row的和,并遍历和
		for(row=0;row<max;row++){//以长宽中最大的一边为边长遍历正方形数组
			col=i-row;//col边由和减row边算出
			
			if(0<=row && row<ROW && col<COL && 0<=col){//输出模块;确保输出的数在范围内(即把正方形数组裁成长方形)
				printf("%d\n",a[row][col]);
			}
		}
	}
}

解法三:数学加权法

所谓遍历,讲究一个先后顺序;那么就要给数表中的数排序。我们进行一个从小到大排序。

右侧比左侧的值更晚输出,赋予更大的权。(1)

下面比上面的数更晚输出,赋予更大的权。(2)

那么右上和左下的比较呢?左下的数更晚出现!符合(2)规律,违背(1)规律。

所以向下的加权(2)要大于向右的加权(1)。

加权的实现通过简单的乘实现,向下的加权乘11,向右的加权乘10。某位置最后的权由纵向位置乘11加横向位置乘10所得,为所有数排上了不连续,但大小特征正确的序。

不采用小数加权是为了构建整数总权。因为只有整数型的总权才可以作为数组地址使用。

在输入数表的同时,程序就直接把数字存到总权值对应的地址的“num”数组中。

由于这些权不是连续分布,数字也不是在“num”数组中连续分布。故设计“index”数组辅助,“index”数组不记录具体数字,仅记录有无(有为1,无为0)。“index”数组的地址与“num”数组相同,都是数字的总权。

有了“index”数组的帮助,加以“过滤输出”(与方法二中类似),实现。

#include<stdio.h>

main(){
	int ROW,COL,site;
	int a[100][100];
	int index[10000]={0};
	int num[10000];
	scanf("%d %d",&ROW,&COL);//设置长宽
	
	int max;//算出最小的可以框住矩形数表的正方形数表的边长,即两边中较大的一边
	if(ROW>=COL) max=ROW;
	else max=COL;
	
	for(int y=1;y<=ROW;y++){//
		for(int x=1;x<=COL;x++){
			site=x*10+y*11;//加权后的数值也是位置的体现
			index[site]=1;//将索引列表中相应位置开关打开
			scanf("%d",&num[site]);//将数直接存到一维列表中,与索引位置对应
		}
	
	}
	
	for(int i=21;i<21*max;i++){
		if(index[i]==1){//通过索引开关过滤
			printf("%d\n",num[i]);
		}
	}

}

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值