二维数组的列排序 考虑问题的全局性 声明数组必须要分配内存并清零

3 篇文章 0 订阅

以“二维数组的列排序”为例练习“ 考虑问题的全局性"以及“ 声明数组必须要分配内存并清零”:

题目要求:

给出一个二维数组,请将这个二维数组按第i列(i从1开始)排序,如果第i列相同,则对相同的行按第i+1列的元素排序,如果第i+1列的元素也相同,则继续比较第i+2列,以此类推,直到最后一列。如果第i列到最后一列都相同,则按原序排列。 

 


实现以下接口:


输入一个m*n 的整数数组,实现按规则排列,返回排列后的数组。



比如输入数组为: 
1,2,3
2,3,4
2,3,1
1,3,1
按第二列排序: 
输出: 
1,2,3
2,3,1
1,3,1

2,3,4

一个失败的程序:

void RangeArray(int * pArray,unsigned int  m, unsigned int  n,unsigned int  i)
{	
	/*if((0 == pArray) || (i >  n) || (m <= 0) || (n <= 0)|| (i <= 0))*///i可以为0的
	if((0 == pArray) || (i >  n) || (m < 0) || (n < 0)|| (i < 0))
		return;
         //int temp_col[m] = {0};//中间数组,存储某一列的m行上的数据
	//int temp_row[n] = {0};//中间数组,存储某一行的n列上的数据
	int * temp_col;//上面的编译不通过,因为编译器把m、n认为是变量。数组的个数应该是常量的
	int * temp_row;
	temp_col = (int *)malloc(sizeof(int) * m);//必须加这个分配内存的,不然编译可以通过,但运行时异常蹦出,提示temp_col变量未定义
	temp_row = (int *)malloc(sizeof(int) * n);
	memset(temp_col,0,m);
	memset(temp_row,0,n);
	for(unsigned int cnt = 0;cnt < m;++cnt)//这一步可以省去,在下面中直接用pArray[i - 1 + cnt * n]来比较也是可以的
	{
		temp_col[cnt] = pArray[i - 1 + cnt * n];
	}
	for(unsigned int rnum = 0;rnum < m - 1;++rnum)//冒泡排序法排序
	{
		for(unsigned int j = m - 1;j > rnum;--j)
			if(temp_col[j] < temp_col[j - 1])
			{
				/*memcpy(temp_row,pArray + j * m,n);
				memcpy(pArray + j * m,pArray + (j - 1) * m,n);
				memcpy(pArray + j * m,temp_row,n);*/
				memcpy(temp_row,pArray + j * n,n * sizeof(int));
				memcpy(pArray + j * n,pArray + (j - 1) * n,n * sizeof(int));
				memcpy(pArray + j * n,temp_row,n * sizeof(int));
			}
			else if(temp_col[j] == temp_col[j - 1])
			{
				/*int cnum = i - 1;*/
				unsigned int cnum = i;//在数组中因为是从0开始,所以实际上是i的后一列,
				/*while(cnum < n - 1)*/ //最后 n-1的那列也要计算
				while(cnum < n)
				{
					if(pArray[cnum + j * n] < pArray[cnum + (j - 1) * n])
					{
						/*memcpy(temp_row,pArray + j * m,n);
						memcpy(pArray + j * m,pArray + (j - 1) * m,n);
						memcpy(pArray + j * m,temp_row,n);*/
						memcpy(temp_row,pArray + j * n,n * sizeof(int));//这样有一个大缺陷是改变了前面大循环中的顺序
						memcpy(pArray + j * n,pArray + (j - 1) * n,n * sizeof(int));//即前面的列比较的过程被打乱了。当目前的小循环结束返回前个循环时已经不是原来的循环了。
						memcpy(pArray + j * n,temp_row,n * sizeof(int));//一种比较好的方案是从最后一列排序,一直排到参考的i列。这样最后的结果时,第i列是完全排序好的
						break;
					}
					else if(pArray[cnum + j * n] == pArray[cnum + (j - 1) * n])
					{
						++cnum;
					}
				}
			}
	}
	return;
}	


上面的方法是按照题目的思路来编写的,但是这样有一个很大的问题是改变了前面大循环中的顺序,即前面的列比较的过程被打乱了。当目前的小循环结束返回前个循环时已经不是原来的循环了。

一种比较好的方案是从最后一列排序,一直排到参考的i列。这样最后的结果时,第i列是完全排序好的。代码如下:


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "oj.h"

// 功能:排列一个m行n列 大小的数组
// 输入: int * pArray 指向数组第一个元素的指针,m为行数, n为列数 ,请按第i列排列
// 输出:按第i列排序完成后的数组放到入参指定的地址中	(i的取值范围 1 - n)  
// 返回:
void RangeArray(int * pArray,unsigned int  m, unsigned int  n,unsigned int  i)
{	
	if((NULL == pArray) || (i >  n) || (m < 0) || (n < 0)|| (i < 0))
		return;
	int * temp = new int[n];//存储某行的n个数
	//int * temp ;//存储某行的n个数
	//temp = (int *)malloc(sizeof(int) * n);
	memset(temp,0,n * sizeof(int));
	unsigned int cnt = n - 1;
	while(cnt >= (i - 1))                        //冒泡排序法
	//for(;cnt >= (i - 1);--cnt)
	{
		for(unsigned int ni = 0;ni < m - 1;++ni)  //  下面用的nj与nj-1比较,就把这里ni压一个
		{
			//for(unsigned int nj = m - 2;nj >= ni;--nj)//带等号,nj == ni这种情况不可以,运行时出错;去掉等号就不是冒泡排序法了,有一例未通过
			//if(pArray[cnt + (nj + 1)  * n] < pArray[cnt + nj * n])
			//	{
			//		memcpy(temp,pArray + nj * n,sizeof(int) * n);
			//		memcpy(pArray + nj*n,pArray + (nj + 1) * n,sizeof(int) * n);
			//		memcpy(pArray + (nj + 1) *n,temp,sizeof(int) * n);
			//	}
			for(unsigned int nj = m - 1;nj > ni;--nj)//
			{
				if(pArray[cnt + nj * n] < pArray[cnt + (nj - 1) * n])
				{
					memcpy(temp,pArray + nj * n,sizeof(int) * n);
					memcpy(pArray + nj * n,pArray + (nj - 1) * n,sizeof(int) * n);
					memcpy(pArray + (nj - 1) *n,temp,sizeof(int) * n);
				}	
			}
			for(unsigned int nj = 0;nj < m - ni - 1;++nj)//这种也可以
			//{
			//	if(pArray[cnt + nj * n] < pArray[cnt + (nj - 1) * n])
			//	{
			//		memcpy(temp,pArray + nj * n,sizeof(int) * n);
			//		memcpy(pArray + nj*n,pArray + (nj + 1) * n,sizeof(int) * n);
			//		memcpy(pArray + (nj + 1) *n,temp,sizeof(int) * n);
			//	}
			//}
			
		}
		//--cnt;//这一句要放在最后,不然对cnt为0的情况严重影响
		if(cnt == 0)  //这一句必须加,不然如果i为0,cnt为0,则cnt-1后在无符号整形中是很大的数,陷入死循环
			break;
		--cnt;
	}
	return;	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值