Naraku--输出最大的n个值

public class
|
|--main() 从 L11 - L23
|    |
|    |--L15    创建数组
|    |
|    |--L17    输出原数组
|    |
|    |--L19    查找最值
|    |
|    |--L21    输出最值
|    
|
|--setArr() 从 L26 - L60
|    |
|    |--L33 - L34    选择随机生成还是手动输入
|    |
|    |--L36 - L40    如果是随机生成,则输入生成多少个数,系统自动生成
|    |
|    |--L43 - L48    如果是手动输入,则输入要输入的个数,用户手动输入
|    |
|    |--L52 - L53    输入要查找几个最值
|    |
|    |--L55 - L56    输入要分为几个块
|    
|
|--printArr() 从 L64 - L88
|    |
|    |--L71 - L75    对应 L17 的调用进行输出
|    |
|    |--L79 - L83    对应 L21 的调用进行输出
|    
|
|--findArr() 从 L91 - L149
     |
     |--L93 - L98    确定列数
     |
     |--L105 - L111    一维数组转二维数组
     |
     |--L115 - L145    查找最值
     |
     |--L117 - L122    查找每一行中的最大值,放入 flag[]
     |
     |--L128 - L139    查找 flag[] 中的最大值
     |
     |--L141 - L144    把最值放入 arr[]

Arr[][]    一个二维数组,里面存放转置过的数据

array[]    一个一维数组,用来存放输入或生成的数据

arr[]    一个一维数组,用来存放问题中要求的最值

flag[]    一个一维数组,用来存放 Arr[][] 中每一行的最大值

A[]    一个一维数组,用来存放 Arr[][] 中每一行最大值的列下标

 

简单说一下核心算法:

首先,输入的数据都是存放在一维数组里的吧,为了便于表示,可以将一维数组转为二维数组代码如下:

if( n % I == 0 ) {       // I是用户输入的,要分成多少个块,在这里用于定义二维数组行
	J = n / I;           // J是通过数据个数和行数计算出来的列数
}
else {
	J = n / I + 1 ;
}


for( i = 0 ; i < I && p != n ; i++ ) {
	for( j = 0 ; j < J && p != n ; j++) {
			Arr[i][j] = array[p++];
			System.out.printf("%-5d",Arr[i][j]);
	}
	System.out.println("\n");
}
z = j - 1;

其中 n 是输入了多少个数据,if -- else 就是根据输入了多少数据和要分成多少块来判断二维数组有多少列,能被行数整除则就是除出来的结果,否则还要 +1 不然放不下。i是二维数组的下标,p 是一维数组的下标,当 p == n 也就是转换结束了。

 

转换成功后,就开始找每一行的最大值嘛,前面不是说了有一个数组用来存放最值嘛,那这个数组没装满是不是就要一直找下去呢?所以这里就可以设置一个直到该数组装满数据才结束的循环 while(arr[s-1] == 0)arr 就是这个数组了,s 就是要存储多少个数据。

arr[0] = 0;
	
while( arr[s-1] == 0 ) {
	for( i = V ; i < I ; i ++ ) 
		for( j = 0 ; ( i < I-1 && j < J ) || ( i == I-1 && j < J ) || ( i == I-1 && j < z ); j++ ) {
			if( flag[i] < Arr[i][j] && Arr[i][j] != 0) {
				flag[i] = Arr[i][j];
				A[i] = j;
				}
			}
		if(o !=0) {
			i = I-1;
		}

这个 V 干什么用呢?它的初值是 0。请大家想想,这个程序的核心就是在循环中,先把每一行的最大值找出来,放到数组 flag 里存放着(这里的 flag 和 Arr 是对应的,flag 的每一个元素对应存放 Arr 中一行的最大值),然后后面会进行比较,把最大的赋值给 arr 数组,然后把那个最大数据在二维数组中赋值为 0,下次不参与比较,那么说到底,需要重新找最值得就是上一轮最大值的那一行,所以,这个 V 的作用,就是用来标志上一次的最值是哪一行,程序再次循环就直接从那一行开始,避免浪费时间。

同理,变量 o 的作用也是一样,第一轮必须把所有行的最大值找完,在已经确定了第一个最大值后,第二轮循环直接从 V 行开始,然后通过判断 o 的值,达到直接让 i循环 直接结束,不再继续往下寻找。 o 的初值是 0 ,所以第一次并不会执行语句改变 i 的值。

搞清楚了 V 和 o 的作用,就来简单看一下这段吧,while 前面说过了,i循环 控制行(也就是块),j循环 控制列,if 用来找每一行的最值,找到的最值放在 flag 中,数组 A 用来记录每一行最值得列下标,方标后面归零。

 

第一次找到所有行的最值是吧,然后把最值进行比较,比较完后,将最值中的最大值放入 arr ,并将该最值二维数组中的位置归零,避免重复比较。完后,第二次直接从上一轮的最值行中继续找,其他行因为最值还在,所以不需要重新查找。

	i = 1;
	max = flag[0];
        V = 0;
			
	while(i < I) {
			
			if ( max < flag[i] ) {
				max = flag[i];
				V = i;
			}
					
			++i;
		}
	arr[f++] = max;
	Arr[V][A[V]]=0;
	flag[V]=0;
	o ++;
}

到了这里就简单明了了,max 最大值,先存放 flag[0] 的值,然后依次比较,新的最大值赋给 max ,而新的最大值对应的行数赋给 V ,然后 i 自增,把最值往 arr 里放,A[V] 里本来存放了各行最大值的列下标,那么 Arr[ V ][ A[V] ] 就可以定位到最值在二维数组中的位置,将值归零。还不要忘了 flag 里也要归零,不然查找的时候就找不到比 flag [V] 更大的了。o++ 使得之后查找完一行后直接结束 i循环

 

附上完整程序:

setArr() : 用来生成数据,在方法中,会先问用户,是随机生成啊,还是手动输入啊。然后随机会问用户,随机生成多少个数啊?手动输入会问用户,手动输入多少个数啊?这个还是很重要的,关系到数组长度。

printArr() : 用来输出,我懒得写两个方法,于是就用了一个 switch() 

findArr() : 这个是核心方法,在上面已经说过了,看不懂的话,,,有问题就问我吧

package Experiment;

import java.util.Scanner;

import Naraku.Nara;    // 导入我自己的方法库;

public class tallestPerson{
	
	static int n,s,i, j, f=0,o=0,V=0,p=0,max,I,J,z;
	
	public static void main(String args[]) {
		
		int[] Arr, find;
		
		Arr = setArr();
		
		printArr(Arr);
		
		find = findArr(Arr);
		
		printArr(find);
		
	}
	
	
	public static int[] setArr() { // 建立一维数组,确定建立数据的个数,确定要找多少个最值,确定要分多少块;
		
		int[] Arr;
		String IO;
		int i = 0;
		Scanner input = new Scanner(System.in);
		
		System.out.println("Do you wanna random or input ?");    //确定是随机还是输入;
		IO = input.nextLine();
		
		if(IO.equals("random")) {
			System.out.println("How many number do you wanna setup ?");    // 随机生成多少;
			n = input.nextInt();
			Arr = new int[n];
			Arr = Nara.setRandom(n,100);
		}
		
		else {
			System.out.println("How many number do you wanna input ?");    // 输入多少个值;
			n = input.nextInt();
			Arr = new int[n];
			while(n > i) {
				Arr[i++] = input.nextInt();
			}
		}
		
		System.out.printf("How many number do you wanna find ?\n");    // 要找几个最值;
		s = input.nextInt();
		
		System.out.printf("How many block do you wanna divide ?\n");    //要分几个块;
		I = input.nextInt();
		
		return Arr;
		
	}
	
	static int abc=0;    // 标志第几次输出;
		
	public static void printArr(int[] a) {
		
		 int i = 0;
		
		switch (abc++) {

			case 0 :{    
					System.out.println("The array are : ");
					for( ; i < n; i++ )
						System.out.printf("%-5d",a[i]);
					System.out.printf("\n");
					break;
			}    // 第一次输出原一维数组;

			case 1 :{    
					System.out.println("The biggest " + s + " numbers are : ");
					for( ; i < s; i++ )
						System.out.printf("%-5d",a[i]);
					System.out.printf("\n");
					break;
			}    // 第二次输出最值数组;

		}

	}
		
	
	public static int[] findArr(int[] array) {
		
		if( n % I == 0 ) {
			J = n / I;
		}
		else {
			J = n / I + 1 ;
		}    // 根据输入数据个数和要分的块数,确定每一行多少列;
		
		int[] arr = new int[s], flag = new int[I], A = new int [I];
		int[][] Arr= new int[I][J];
		
		System.out.println("\nYour array has been divided into " + I + " blocks with " + J + " cols\n");
		
		for( i = 0 ; i < I && p != n ; i++ ) {
			for( j = 0 ; j < J && p != n ; j++) {
					Arr[i][j] = array[p++];
					System.out.printf("%-5d",Arr[i][j]);
			}
			System.out.println("\n");
		}    //将原一维数组转换成二维数组,并输出;
		z = j - 1;
		
		arr[0] = 0;
		
		while( arr[s-1] == 0 ) {    // while() 里的判断式,意思为只有把最值找完,才;

			for( i = V ; i < I ; i ++ ) 
				for( j = 0 ; ( i < I-1 && j < J ) || ( i == I-1 && j < J ) || ( i == I-1 && j < z ); j++ ) {
					if( flag[i] < Arr[i][j] && Arr[i][j] != 0) {
						flag[i] = Arr[i][j];
						A[i] = j;
						}    // 找出每一行最大值放到 flag[] 里,列下标放到 A[] 里;
					}
				if(o !=0) {
					i = I-1;
				}    // 第一轮找最值不影响,第二轮执行,找完第 V 行后直接结束 i循环;
			
			i = 1;
			max = flag[0];
                        V = 0;
			
			while(i < I) {
			
					if ( max < flag[i] ) {
						max = flag[i];
						V = i;
					}
					
					++i;
				}    // 查找 flag 里的最大值;

			arr[f++] = max;
			Arr[ V ][ A[V] ]=0;
			flag[V]=0;
			o++;
		}    // 把最大值放入 arr ,Arr[][] 和 flag[] 中对应位置归零,防止最值再次参与比较;
		
		return arr;
		
	}
		
}    // 这里面有 1/3 的行数是空格

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值