java基础_ week 5 数组

week 5 数组

5.1 数组
初试数组

用我们以前学过的知识来设想一个问题:如何写一个程序计算用户输入的数字的平均数?

在不需要记录输入的每一个数的前提下,我们很容易就可以得到下面的类似代码:

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int x = 0;
		double sum = 0.0;
		int cnt = 0;
		x = in.nextInt();
		while (x != -1) {
			sum += x;
			cnt++;
			x = in.nextInt();
		}
		if( cnt > 0) {
			System.out.println(sum/cnt);
		}		
	}

代码5-1


(cnt是count的缩写,常用来做计数器;-1也是我们常用的标志。)

但是这是在不需要记录输入的每一个的数的情况下,如果我们有更多的要求呢?

  • 比如如何写一个程序计算用户输入的数字的平均数,并输出所有大于平均数的数?
  • 必须先记录每一个输入的数字,计算平均数以后,再检查记录下来的每一个数字,与平均数做比较,决定是否输出。

那么?如果记录很多数呢?

  • 采用变量命名,如int num1,num 2,num3…当然是可以的,但是肯定有更高效率的做法,这就是我们接下来要说的数组。

对代码5-1稍作修改可以得到代码5-2(此代码存在安全隐患,具体情况会在后说明)

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int x = 0;
		double sum = 0.0;
		int cnt = 0;
		int[] numbers = new int[100];			//定义数组
		x = in.nextInt();
		
		while(x != -1) {
			numbers[cnt] = x;
			sum += x;
			cnt++;
			x = in.nextInt();
		}
		if(cnt > 0) {
			double average = sum/cnt;
			for(int i = 0; i < cnt ; i++ ) {	//遍历数组
				if(numbers[i] > average) {
					System.out.println(numbers[i]);
				}
			}
		}
		
	}
												**代码 5-2**

创建数组

数组: 是一种 容器(放东西的东西),特点是:

  • 其中所有的元素都具有相同的数据类型;;
  • 一旦创建,不能改变大小。

数组中的每个数据叫做元素。

定义数组变量:

类型 [] 名字 = new 类型 [元素个数]

e.g.: int[] grades = new int[100];

double[] averages = new double [20];

几个要注意的点:

  • 元素个数必须是整数;
  • 元素个数必须给出;
  • 元素个数可以是变量。
数组的元素

对于代码 int[] a = new int[10];,创建了一个int型的数组,数组里有10个元素:a[0],a[1],a[2],a[3]…a[9],每个元素是一个int的变量,可以像使用普通变量一样对其进行基础操作。

对于数组的元素:

  • 每个元素都是它定义的数据类型的变量
  • 索引或者下标都是从0开始的

在这里插入图片描述

有效的下标:

  • 最小的下标是0,最大的下标是 数组的元素个数-1;
  • 可是编译器不会检查你是否用了有效的下标;
  • 但是如果运行的时候出现了无效的下标,可能会导致程序终止。

代码5-2存在安全隐患,因为我们并不知道具体会输入多少数据,输入的数据可能超过100个。对于此种情况,又该如何解决呢?

联系到上面所说,元素的个数可以是变量,我们不妨用变量代替具体的数字100,先让用户输入一个数cnt来表示需要多少个数据,再输入具体的数据,可以得到如下代码:

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		double sum = 0;
		int cnt = in.nextInt();

		if( cnt > 0) {
			int[] numbers = new int [cnt];
			for(int i =0; i<cnt ; i++ ) {
				numbers[i] = in.nextInt();
				sum += numbers[i];
			}
			double average = sum/cnt;
			for(int i = 0; i < cnt; i++) {
				if(numbers[i] > average) {
					System.out.println(numbers[i]);
				}
			}
		}
		
	}

**length:**每个数组都有一个内部成员length,会告诉你它的元素的数量。

比如对于代码,for(i=0;i<100;++i)这种形式,最好改写成for(i=0;i<grade.length;++i)的形式,这有利于代码的可扩展性。

**代码练习:**投票统计:写一个程序,输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束。

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int x = in.nextInt();
		int[] numbers = new int[10];
		while(x != -1) {
			if(x >= 0 && x <= 9) {
				numbers[x]++;
			}
			x = in.nextInt();
		}
		for(int i = 0; i < numbers.length; i++) {
			System.out.println(i+":"+numbers[i]);
		}
	}

TIPS:没有给数组赋值时,数组里面的元素自动赋0,number[x]++时是说number数据的第x个元素+1,x代表输入的数,并不是每个数字的的计数,number[x]才是值为x的计数。

5.2数组计算

数组变量:

直接初始化数组:

  • new创建的数组会得到默认的0值
  • 可以直接用大括号给i出数组的所有元素的初始值
  • 不需要给出数组的大小,编译器替你数数
  • 如何得知数组的大小? length。

数组变量:

  • 数组变量时数组的管理者,而非数组本身;
  • 数组必须创建出来然后交给数组变量来管理;
  • 数组变量之间的赋值是管理权限的赋予;
  • 数组变量之间的比较是判断是否管理同一个数组。

复制数组:

  • 必须遍历源数组,将每个元素逐一拷贝给目的数组。

遍历数组:

在一组给定的数据中,如何找出某个数据是否存在?

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int[] data = {2,3,5,7,4,9,11,34,12,28};
		int x = in.nextInt();
		int loc = -1;
		
		for(int i = 0; i < data.length; i++) {
			if(x == data[i]) {
				loc = i;
					break;
			}			
		}
		if( loc > -1) {
			System.out.println(x+"是第"+(loc+1)+"个");
		}
		else {
			System.out.println(x+"不在其中");
		}

	}

tips:此种搜索方法被称作线性搜索。

代码 5-3


注意代码5-3中的第7~11行。

  • 遍历数组时,通常都是使用for循环,让循环变量i从0到<数组的length,这样循环体内最大的i正好是数组最大的有效下标。
  • 常见错误是:
    • 循环结束的条件是 <= 数组长度;
    • 离开循环后,继续用i的值来做数组元素的下标。

接下来另一种语句,for-each语句。

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int[] data = {2,3,5,7,4,9,11,34,12,28};
		int x = in.nextInt();
		boolean found = false;
		for(int k:data) {
			if(x == k) {
				found = true;
				break;
			}
		}
		if(found) {
			System.out.println(x+"在其中");
		}
		else {
			System.out.println(x+"不在其中");
		}

	}

for-each:

for(类型 变量:数组){

}

for-each适合做数组的遍历。写法是对于数组中的每一个元素取出来作为这个类型的一个变量,所以中间用的是冒号,读的时候我们要倒过来,对于数组中的每一个元素,取出来作为那一个元素的变量。

数组的例子:素数

**从2到x-1测试是否可以整除:**参考代码4-1。

对于n,要循环n-遍;当n很大的是偶,就可以被看作是n遍。

去掉偶数之后,从3到x-1,每次加2

核心代码:

if(x ==1 || x%2 ==0 && x!=2){
	isPrime = false;
}
else{
    for(int i = 3; i < x; i+=2){
        if(x %i ==0){
            isPrime == false;
            break;
        }
    }
}

如果x是偶数,立刻判断为不是素数。否则要循环(n-3)/2+1遍,当n非常大的就是n/2遍。

无须到1,到sqrt(x)就够了:

for(int i = 3; i<Math.sqtr(x);i+=2){
	if(x % i == 0){
        isPrime = false;
        break;
	}
}

具体原因参见数学证明。只需要循环sqtr(x)遍。

以上,从 n→ n/2 → sqrt(n),这是人类思维较容易理解思考到的方法。

以下提供另一种思维模式:

构造素数表:

欲构造n以内的素数表:

  1. 令x为2;
  2. 将2x、3x、4x直到ax<n的数标记为非素数
  3. 令x为下一个没有被标记为非素数的数,重复2;直到所有的数已经尝试完毕

欲构造n以内(不含)的素数表:

  1. 创建prime为boolean[n],初始化其所有元素为true,prime[x]为true表示x是素数。
  2. 令x=2
  3. 如果x是素数,则对于(i=2;x*i<n;i++)令prime[i * x]=false。
  4. 令x++,如果x<n,重复3,否则结束。

核心代码:

boolean[] isPrime = new boolean[100];
for(int i =2; i <isPrime.length; i++){
    isPrime[i] = true;
}

for(int i =2; i<isPrime.length; i++){
    if(isPrime[i]){
        for(int k=2;i*k<isPrime.length; k++){
			isPrime[i*k] = false;
        }
    }
}
for(int i =0; i < isPrime.length;i++){
	if(isPrime[i]){
        System.out.println(i+" ");
    }
}
System.out.println();

算法不一定和人的思考方式相同。

5.3 二维数组

int[][]a =new int[3][5];,通常理解为a是一个3行5列的矩阵。如图所示:

在这里插入图片描述

二维数组的遍历:

for(i=0;i<3;i++){
    for(j=0;j<5;j++){
        a[i][j] = i*j;
    }
}
  • a[i] [j]是一个int

  • 表示第i行第j列上的单元

  • a[i,j]这种并不存在

二维数组的初始化:

int[][] a={
    {1,2,3,4};
    {1,2,3};
}
  • 编译器来数数
  • 每行一个{},用逗号分隔,最后的都好可以存在(有古老的传统)
  • 如果省略,表示补0。
tic-tac-toe游戏

读入一个3x3的矩阵,矩阵中的数字1表示该位置上有一个x,为0表示为o。程序判断这个矩阵中是否有获胜的一方,输出表示获胜一方的字符x或o,或输出无人获胜。

		public static void main(String[] args) {

		 Scanner in = new Scanner(System.in);
		//int[] number = new int[10];
		//int a;
		int i,j;
		final int SIZE = 3;//the size of SIZE is three
		//tic-tac-toe
		int[][] board = new int[SIZE][SIZE];
		System.out.println("Gameplayer_1 input 1 and Gameplayer_2 input 0");
		for(i=0;i<board.length;i++)//Input the element,1 representative x,0 representative o;
		{
			for(j=0;j<board[i].length;j++)
			{
				board[i][j] = in.nextInt();
			}
		}
		boolean GotResult = false;
		//Jude row column Diagonal diagonal line
		int cnt = 0;
		int num1 = 0;
		int num2 = 0;
		//Judge row and column
		for(i=0;i<board.length;i++)
		{
			 num1 = 0;
			 num2 = 0;
			for(j=0;j<board[i].length;j++)//row
			{
				if(board[i][j]==1) {
					num1++;
				}
			}
			for(j=0;j<board[i].length;j++)//column
			{
				if(board[j][i]==1) {
					num2++;
				}
			}
			if(num1 == SIZE || num2 == SIZE)
			{
				System.out.println("Gameplayer_1 win!");
				GotResult = true;
				break;
			}
		    if(num2 == 0 || num1 == 0)
			{
		    	System.out.println("Gameplayer_2 win!");
		    	GotResult = true;
		    	break;
			}
		}
		
		if(GotResult == false){ 
			 num1 = 0;
			 num2 = 0;
			//Judge diagonal diagonal line
			for(i=0;i<board.length;i++)
			{
				if(board[i][i] == 1) {
					num1++;
				}
				if(board[i][2-i] == 1) {
					num2++;
				}
			}
			if(num1==3 || num2 ==3) {
				System.out.println("Gameplayer_1 win!");
//				GotResult = true;
			}
			else if(num2 == 0 || num1 == 0) {
				System.out.println("Gameplayer_2 win!");
//				GotResult = true;
			}
			else {
				System.out.println("Draw!");
			}
			
		}
	  }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值