user-0 提问: 求二维数组一列中最小元素 同时也是这一列最小元素

回复:
user: user-0
content: 引用 21 楼 拥抱Linux 的回复:[quote=引用 20 楼 marwi_study 的回复:] 不用客气，俺也同样是在坛子里向大家学习。互相学习哈～[/quote]又有新问题了 老哥 拜托拜托看看 救急https://bbs.csdn.net/topics/392640128?page=1#post-403928792

user: user-1
content: 引用 15 楼 wei xin_44706101 的回复:谢谢 脑子真的要绕晕了 今天太晚了 答主最近什么时候有空帮我看看怎么改  没空也没关系 还是谢谢啦 下面的代码，你先试试：  #include <stdio.h>  int main(void) { 	int n, m, min, i, j, t; 	int c = 0; 	int *p; 	scanf("%d%d", &n, &m); 	int a[n][m]; 	int x[n], y[m]; //数组，存放最小值的下标，考虑到有重复最小值的情况 	for (i = 0; i < n; i++) { 		for (j = 0; j < m; j++) { 			scanf("%d", &a[i][j]); 		} 	}  	for (i = 0; i < n; i++) { 		min = a[i][0]; 		x[0] = i; 		y[0] = 0; 		for (j = 0; j < m; j++) { 			if (a[i][j] < min) { 				min = a[i][j]; 				x[0] = i; 				y[0] = j; 			} 		} //先求出这一行中最小  		// 该行的最小值的个数，因为可能存在多个相等的最小值的情况 		// 整行遍历，避免重复计数，所以xcount从0开始计数 		int xcount = 0; 		for (j = 0; j < m; j++) { 			if (a[i][j] == min) { 				x[xcount] = i; 				y[xcount] = j; 				xcount++; 			} 		}  		for (int k = 0; k < xcount; k++) { 			p = &(a[0][y[k]]); //把指针移到该元素所在列首 			c = 0; 			for (t = 0; t < n; t++) { 				if (*p < min) { 					c = 1; 					break; 				} 				p = p + m; 			}  			//若无则输出 			if (c == 0) { 				printf("%d,", min); 				printf("%d,", x[k] + 1); 				printf("%d\n", y[k] + 1); 			} 		} 	} 	return 0; }  ～

user: user-1
content: 引用 15 楼 wei xin_44706101 的回复:[quote=引用 14 楼 拥抱Linux 的回复:] [quote=引用 12 楼 wei xin_44706101 的回复:] 如果这一行中有与其相等的数也同为最小数怎么办 这个代码要如何修改 一个简单的想法，找到 行 的最小值之后， 先用 行的最小值 与 该行所有值 比较一遍，并计数，如果 有两个或以上相等的 行的 最小值的话，就在 大循环 进入 下一行 之前， 对 后面的 行的最小值  进行 列 方向的 检查 。[/quote]谢谢 脑子真的要绕晕了 今天太晚了 答主最近什么时候有空帮我看看怎么改  没空也没关系 还是谢谢啦[/quote] 明天抽空吧。 还有，你刚刚发的帖子，段错误的那个， 点链接过去是404，不见了。你再看看什么情况。 ～

user: user-0
content: 引用 14 楼 拥抱Linux 的回复:[quote=引用 12 楼 wei xin_44706101 的回复:] 如果这一行中有与其相等的数也同为最小数怎么办 这个代码要如何修改 一个简单的想法，找到 行 的最小值之后， 先用 行的最小值 与 该行所有值 比较一遍，并计数，如果 有两个或以上相等的 行的 最小值的话，就在 大循环 进入 下一行 之前， 对 后面的 行的最小值  进行 列 方向的 检查 。[/quote]谢谢 脑子真的要绕晕了 今天太晚了 答主最近什么时候有空帮我看看怎么改  没空也没关系 还是谢谢啦

user: user-1
content: 引用 20 楼 marwi_study 的回复: 不用客气，俺也同样是在坛子里向大家学习。互相学习哈～

user: user-2
content: 引用 19 楼 拥抱Linux 的回复:[quote=引用 18 楼 marwi_study 的回复:] [quote=引用 9 楼 拥抱Linux的回复:][quote=引用 1 楼 marwi_study 的回复:] p=p+m这一句不对，指针移动是以字节为单位的，int是四个字节 并不是，而是以数据类型的基本长度为单位来移动的，可以抽象地认为和字节无关。 p = p + m 就是 p 向后移动 m 个 p 代表的数据类型的基本长度，在这里就是 向后 移动 m 个 int 数据。 就相当于是数组的下标。[/quote] 诶，请教一下，那个内存单元不是以字节为单位吗，然后那个指针保存的内容通过输出的方式可以看到是一个内存地址呀，那直接加一个数值不是只移动了几个字节吗，为什么会是以数据类型基本长度为单位呢[/quote] 一般情况下，讨论的和应用的内存地址，确实是以单个字节来计数的，比如 0x1 就是 0x0 往后1个字节的位置。 但是，对于指针而言，指针本身的运算（当然了，只有 加 、 减 运算，表示 向后 或者 向前 移动，而没有乘、除运算，因为乘、除在这里没有意义），是表示 指针 移动 多少个 指针指向的 数据类型 的基本长度的，最简单的例子还是 数组的例子。 反过来说，假如 指针的运算 是按 一个字节一个字节 来移动的话，那么 指针就没有必要 区分何种数据类型了呀！ 简而言之就是，指针 的 加减运算，就等价于 数组的下标 运算，这样就好理解了，就是跨过多少个元素的意思。 至于说为什么这样？那当然是语言的标准规定呀！ 具体的验证，看看上面俺举的代码例子就可以了，建议自己也运行、调试看看。 ～[/quote] 多谢指教，受益匪浅

user: user-1
content: 引用 18 楼 marwi_study 的回复:[quote=引用 9 楼 拥抱Linux的回复:][quote=引用 1 楼 marwi_study 的回复:] p=p+m这一句不对，指针移动是以字节为单位的，int是四个字节 并不是，而是以数据类型的基本长度为单位来移动的，可以抽象地认为和字节无关。 p = p + m 就是 p 向后移动 m 个 p 代表的数据类型的基本长度，在这里就是 向后 移动 m 个 int 数据。 就相当于是数组的下标。[/quote] 诶，请教一下，那个内存单元不是以字节为单位吗，然后那个指针保存的内容通过输出的方式可以看到是一个内存地址呀，那直接加一个数值不是只移动了几个字节吗，为什么会是以数据类型基本长度为单位呢[/quote] 一般情况下，讨论的和应用的内存地址，确实是以单个字节来计数的，比如 0x1 就是 0x0 往后1个字节的位置。 但是，对于指针而言，指针本身的运算（当然了，只有 加 、 减 运算，表示 向后 或者 向前 移动，而没有乘、除运算，因为乘、除在这里没有意义），是表示 指针 移动 多少个 指针指向的 数据类型 的基本长度的，最简单的例子还是 数组的例子。 反过来说，假如 指针的运算 是按 一个字节一个字节 来移动的话，那么 指针就没有必要 区分何种数据类型了呀！ 简而言之就是，指针 的 加减运算，就等价于 数组的下标 运算，这样就好理解了，就是跨过多少个元素的意思。 至于说为什么这样？那当然是语言的标准规定呀！ 具体的验证，看看上面俺举的代码例子就可以了，建议自己也运行、调试看看。 ～

user: user-2
content: 引用 9 楼 拥抱Linux的回复:[quote=引用 1 楼 marwi_study 的回复:] p=p+m这一句不对，指针移动是以字节为单位的，int是四个字节 并不是，而是以数据类型的基本长度为单位来移动的，可以抽象地认为和字节无关。 p = p + m 就是 p 向后移动 m 个 p 代表的数据类型的基本长度，在这里就是 向后 移动 m 个 int 数据。 就相当于是数组的下标。[/quote] 诶，请教一下，那个内存单元不是以字节为单位吗，然后那个指针保存的内容通过输出的方式可以看到是一个内存地址呀，那直接加一个数值不是只移动了几个字节吗，为什么会是以数据类型基本长度为单位呢

user: user-1
content: 引用 12 楼 wei xin_44706101 的回复:如果这一行中有与其相等的数也同为最小数怎么办 这个代码要如何修改 一个简单的想法，找到 行 的最小值之后， 先用 行的最小值 与 该行所有值 比较一遍，并计数，如果 有两个或以上相等的 行的 最小值的话，就在 大循环 进入 下一行 之前， 对 后面的 行的最小值  进行 列 方向的 检查 。

user: user-1
content: 引用 10 楼 wei xin_44706101 的回复:[quote=引用 9 楼 拥抱Linux 的回复:] [quote=引用 1 楼 marwi_study 的回复:] p=p+m这一句不对，指针移动是以字节为单位的，int是四个字节 并不是，而是以数据类型的基本长度为单位来移动的，可以抽象地认为和字节无关。 p = p + m 就是 p 向后移动 m 个 p 代表的数据类型的基本长度，在这里就是 向后 移动 m 个 int 数据。 就相当于是数组的下标。[/quote]谢了老哥[/quote]  不用客气，互相探讨、学习也是乐趣。晚上搞了几把CS：GO，睡觉之前说上坛子里面再逛逛才看到帖子。

user: user-0
content: 引用 11 楼 拥抱Linux 的回复:看了上面朋友的发言，小可不才，斗胆多说两句。  （1）首先，此题目，不是找整个二维数组的最小元素，虽然看起来「好像」是一回事，但是确实不是一回事。 具体，可以看看楼主提供的输入数据和输出数据期望值就知道了。  （2）指针的移动，不是按字节移动的，举个最简单的例子就是，数组名本身可以看作一个数组，而获取数组元素的时候，一般是用数组名加上下标运算符的方式，比如有数组 int a[10]，要获得第5个元素就是通过 a[4] 来获取，或者也可以用 *(a+4) ，对吧？ 总不能说，a + 4 的意思是 从 a 的地址算起，向后移动 4个 字节吧？ 换成 普通的指针不是一回事儿么？ 而 一个字节一个字节移动的指针也有， 字符指针嘛！  代码举例：  #include <stdio.h>  int main(void) { 	int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 	int *p = a; 	printf("address of p = %p\n", p); 	printf("address of p + 2 = %p\n", p + 2); 	printf("address of p + 5 = %p\n", p + 5); 	for (int i = 0; i < 5; i++) { 		printf("a[%d] = %d\t | addr of a[%d] \t= %p\n", i, a[i], i, 		       &a[i]); 		printf("*(a+%d) = %d\t | addr of *(a+%d) \t= %p\n", i, *(a + i), 		       i, a + i); 		printf("*p = %d\t\t | addr of *p \t\t= %p\n", *p, p); 		p++; 	} 	return 0; }  运行结果是：  address of p = 0x7ffe96ef0160 address of p + 2 = 0x7ffe96ef0168 address of p + 5 = 0x7ffe96ef0174 a[0] = 0         | addr of a[0]         = 0x7ffe96ef0160 *(a+0) = 0       | addr of *(a+0)       = 0x7ffe96ef0160 *p = 0           | addr of *p           = 0x7ffe96ef0160 a[1] = 1         | addr of a[1]         = 0x7ffe96ef0164 *(a+1) = 1       | addr of *(a+1)       = 0x7ffe96ef0164 *p = 1           | addr of *p           = 0x7ffe96ef0164 a[2] = 2         | addr of a[2]         = 0x7ffe96ef0168 *(a+2) = 2       | addr of *(a+2)       = 0x7ffe96ef0168 *p = 2           | addr of *p           = 0x7ffe96ef0168 a[3] = 3         | addr of a[3]         = 0x7ffe96ef016c *(a+3) = 3       | addr of *(a+3)       = 0x7ffe96ef016c *p = 3           | addr of *p           = 0x7ffe96ef016c a[4] = 4         | addr of a[4]         = 0x7ffe96ef0170 *(a+4) = 4       | addr of *(a+4)       = 0x7ffe96ef0170 *p = 4           | addr of *p           = 0x7ffe96ef0170  以上。如有错漏，还请批评指正。 ～如果这一行中有与其相等的数也同为最小数怎么办 这个代码要如何修改

user: user-1
content: 看了上面朋友的发言，小可不才，斗胆多说两句。  （1）首先，此题目，不是找整个二维数组的最小元素，虽然看起来「好像」是一回事，但是确实不是一回事。 具体，可以看看楼主提供的输入数据和输出数据期望值就知道了。  （2）指针的移动，不是按字节移动的，举个最简单的例子就是，数组名本身可以看作一个数组，而获取数组元素的时候，一般是用数组名加上下标运算符的方式，比如有数组 int a[10]，要获得第5个元素就是通过 a[4] 来获取，或者也可以用 *(a+4) ，对吧？ 总不能说，a + 4 的意思是 从 a 的地址算起，向后移动 4个 字节吧？ 换成 普通的指针不是一回事儿么？ 而 一个字节一个字节移动的指针也有， 字符指针嘛！  代码举例：  #include <stdio.h>  int main(void) { 	int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 	int *p = a; 	printf("address of p = %p\n", p); 	printf("address of p + 2 = %p\n", p + 2); 	printf("address of p + 5 = %p\n", p + 5); 	for (int i = 0; i < 5; i++) { 		printf("a[%d] = %d\t | addr of a[%d] \t= %p\n", i, a[i], i, 		       &a[i]); 		printf("*(a+%d) = %d\t | addr of *(a+%d) \t= %p\n", i, *(a + i), 		       i, a + i); 		printf("*p = %d\t\t | addr of *p \t\t= %p\n", *p, p); 		p++; 	} 	return 0; }  运行结果是：  address of p = 0x7ffe96ef0160 address of p + 2 = 0x7ffe96ef0168 address of p + 5 = 0x7ffe96ef0174 a[0] = 0         | addr of a[0]         = 0x7ffe96ef0160 *(a+0) = 0       | addr of *(a+0)       = 0x7ffe96ef0160 *p = 0           | addr of *p           = 0x7ffe96ef0160 a[1] = 1         | addr of a[1]         = 0x7ffe96ef0164 *(a+1) = 1       | addr of *(a+1)       = 0x7ffe96ef0164 *p = 1           | addr of *p           = 0x7ffe96ef0164 a[2] = 2         | addr of a[2]         = 0x7ffe96ef0168 *(a+2) = 2       | addr of *(a+2)       = 0x7ffe96ef0168 *p = 2           | addr of *p           = 0x7ffe96ef0168 a[3] = 3         | addr of a[3]         = 0x7ffe96ef016c *(a+3) = 3       | addr of *(a+3)       = 0x7ffe96ef016c *p = 3           | addr of *p           = 0x7ffe96ef016c a[4] = 4         | addr of a[4]         = 0x7ffe96ef0170 *(a+4) = 4       | addr of *(a+4)       = 0x7ffe96ef0170 *p = 4           | addr of *p           = 0x7ffe96ef0170  以上。如有错漏，还请批评指正。 ～

user: user-0
content: 引用 9 楼 拥抱Linux 的回复:[quote=引用 1 楼 marwi_study 的回复:] p=p+m这一句不对，指针移动是以字节为单位的，int是四个字节 并不是，而是以数据类型的基本长度为单位来移动的，可以抽象地认为和字节无关。 p = p + m 就是 p 向后移动 m 个 p 代表的数据类型的基本长度，在这里就是 向后 移动 m 个 int 数据。 就相当于是数组的下标。[/quote]谢了老哥

user: user-1
content: 引用 1 楼 marwi_study 的回复:p=p+m这一句不对，指针移动是以字节为单位的，int是四个字节 并不是，而是以数据类型的基本长度为单位来移动的，可以抽象地认为和字节无关。 p = p + m 就是 p 向后移动 m 个 p 代表的数据类型的基本长度，在这里就是 向后 移动 m 个 int 数据。 就相当于是数组的下标。

user: user-1
content: （1）输入数值保存到数组的时候，scanf 语句有问题 ， 不是 「&a[10][10]」，而是   scanf("%d",&a[i][j]);  （2）移动指针 p 的时候，要一行一行地移动的话， 不是 「 p = p + m ;」， 而是  p = p + 10;  因为，真正的数组是 a[10][10]，而不是 a[n][m] 。这样一来，「 p = p + m 」就并没有让指针 p 向下移动一行。 其实，也可以不定义 a[10][10] 这个数组， 而是直接 在输入 n 、m 的值之后，定义 数组 a[n][m] ，从 C99 标准之后好像就可以定义这样的数组了，这样的话 「 p = p + m ;」 就是让 指针 p 向 下移动了一行。 （3）比较 是否是 该列的最小值 的 循环 也有遗漏， 应该全部比较一遍，如下，  		for (t = 0; t < n; t++) { 			if (*p < min) { 				c = 1; 				break; 			} 			p = p + 10; 		}  目前看来就是这些吧。 ～

user: user-2
content: 上面的道友说的在理，这就是两层for循环就可以解决的问题，一般是用三目操作符？：来做的。 关于那个指针，建议对指针比较了解能用到很熟练的时候才那样用，指针是保存内存的地址的，因为int有些编译器是编成两个字节的，有一些是编成四个字节的，如果int是四个字节，也就是上面那个写法要改成p+=4*m，如果int是两个字节的，就p+=2*m咯！

user: user-3
content: 道友，你的代码写得太复杂了，当然，你的逻辑思维也是可以的，但是你的逻辑思维并不是最简单，最优的解法，可以看看我的博文：https://blog.csdn.net/weixin_43956598/article/details/90049508，对你有所帮助！ 你这个就是简单的求二维数组最小元素所在的行和列的位置，那么，简单的思维就是，分别用一个min,min_x,min_y分别表示最小元素，最小元素所在的行，最小元素所在的列，然后在两层for循环中，不断更新min,min_x,min_y的值即可！  #include<stdio.h> #define inf 0x3f3f3f3f //无穷大  int main() { 	int a[10][10]; 	int i,j,n,m,min,min_x,min_y; 	scanf("%d",&n); 	scanf("%d",&m); 	min=min_x=min_y=inf;//初始化为最大的数  	for(i=0; i<n; i++) { 		for(j=0; j<m; j++) { 			scanf("%d",&a[i][j]); 		} 	} 	for(i=0; i<n; i++) { 		for(j=0; j<m; j++) { 			if(a[i][j]<min){ //找到更小的值就更新最小元素 				min=a[i][j]; 			} 		} 	} 	for(i=0; i<n; i++) { //这种写法具备普遍性，考虑二维数组中有可能有多个最小元 		for(j=0; j<m; j++) { 			if(a[i][j]==min){ 				min_x=i; 				min_y=j; 				printf("最小元素 元素所在的行  元素所在的列：");  				printf("%d %d %d\n",min,min_x,min_y); 			} 		} 	} 	return 0; }

user: user-0
content: 引用 楼主 wei xin_44706101 的回复:先输入n，m 一个n行m列 找到  输出该元素及其所在行和列  #include<stdio.h> int main() { int n,m,min,x,y,i,j,t;   int c=0;   int *p;   int a[10][10];   scanf("%d",&n);   scanf("%d",&m); for(i=0;i<n;i++) { for(j=0;j<m;j++)  scanf("%d",&a[10][10]); }   for(i=0;i<n;i++) {  min=a[i][0];        x=i;    y=0;   for(j=0;j<m;j++)   {if(a[i][j]<min)     {min=a[i][j];     x=i;     y=j;}    }             //先求出这一行中最小     p=&(a[0][y]);//把指针移到该元素所在列首     c=0;     for(t=1;t<n;t++)     {p=p+m; //指针下移 看是否有比该元素小的元素     if(*p<min)       c=1;     }     if(c==0)//若无则输出     {printf("%d,",min);     printf("%d,",x+1);     printf("%d,",y+1);}    } }  为什么输出的是错的  例子8  60  2  100     10  498  12  49  -50  132  4  85中的-50和2

user: user-4
content: 为啥要先求每一行最小元素，再去求最小元素中的最小呢？不能直接求二维数组的最小元素呢？

user: user-4
content: 请把问题描述清楚，你的标题都不通顺，如果只是求最小元素，直接2个for循环不就好了，哪有那么麻烦