4.1 数组的创建和使用
4.1.1 初试数组
- 如何写一个程序计算用户输入的数字的平均数,并输出所有大于平均数的数?
- 必须先记录每一个输入的数字,计算平均数之后,再检查记录下来的每一个数字,与平均数比较,决定是否输出
- 使用数组
package com.meteor.array;
import java.util.Scanner;
public class Avg {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int x;
int[] numbers = new int[100];
double sum = 0;
int cnt = 0;
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]);
}
}
System.out.println(average);
}
}
}
这个程序是危险的,因为输入的数据可能超过100个
4.1.2 创建数组
数组
- 是一种容器(放东西的东西),特点是:
- 其中所有的元素具有相同的数据类型
- 一旦创建,不能改变大小
- 数组中的每个数据叫做元素
- int[] numbers = new int[4];
- 元素个数必须是整数
- 元素个数可以是变量
- int[] a = new int[10]
- 创建了一个int型的数组
- 10个元素:a[0],a[1],…a[9]
- 每个元素是一个int的变量
- 可以读和写
4.1.3 数组的元素
- 每个元素都是那种类型的变量
- 索引或下标是从0开始的
有效的下标
- 最小的下标是0,最大的下标是数组的元素个数-1
- 可是编译器不会检查看你是否用了有效的下标
- 但是如果运行的时候出现了无效的下标,可能会导致程序终止
- ArrayIndexOutOfBoundsException
- 如果先让用户输入有多少数字要计算,就可以根据这个数字来制造数组
- int[] numbers = new int[cnt];
- 每个数组有一个内部成员length,会告诉你它的元素的数量
4.1.4 例子:投票统计
- 写一个程序,输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束
package com.meteor.array;
import java.util.Scanner;
public class VoteStatistics {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int x;
int[] numbers = new int[10];
x = in.nextInt();
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]);
}
}
}
4.2 数组变量和运算
4.2.1 数组变量
直接初始化数组
- 直接初始化数组
- new创建的数组会得到默认的0值
- int[] scores={87,9869,54,65,7687,99};
- 直接用大括号给出数组的所有兀素的初始值
- 如何得知数组的大小?length!
数组变量赋值
package com.meteor.array;
public class Main {
public static void main(String[] args) {
int[] a = new int[10];
a[0] = 5;
int[] b = a;
b[0] = 16;
System.out.println(a[0]);//16,说明数组变量是管理者,不是所有者
}
}
package com.meteor.array;
public class Main {
public static void main(String[] args) {
int[] a1 = {1,2,3,4,5};
int[] a2 = a1;
for ( int i=0; i<a2.length; ++i )
{
a2[i] ++;
}
for ( int i=0; i<a1.length; ++i )
{
System.out.println(a1[i]);//2...6
}
}
}
数组变量
- 数组变量是数组的管理者而非数组本身
- 数组必须创建出来然后交给数组变量来管理
- 数组变量之间的赋值是管理权限的赋予
- 数组变量之间的比较是判断是否管理同一个数组
复制数组
- 必须遍历源数组将每个元素逐一拷贝给目的数组
package com.meteor.array;
public class Main {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
int[] b = new int[a.length];
boolean isEqu =true;
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
isEqu = false;
break;
}
}
System.out.println(isEqu);
}
}
4.2.2 遍历数组
- 在一组给定的数据中,如何找出某个数据是否存在?
package com.meteor.array;
import java.util.Scanner;
public class Main {
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 + "不在其中");
}
}
}
- 数组的遍历通常都是使用for循环,让循环变量i从0到<数组的length,这样循环体内最大的i正好是数组最大的有效下标
for-each
package com.meteor.array;
import java.util.Scanner;
public class Main {
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 + "不在其中");
}
}
}
4.2.3 例子:素数计算
- 之前判断一个数是否是素数,从2开始到x-1测试是否可以整除
- 对于n,要循环n-2遍
- 当n很大时,就可以被看做是n遍
for (int i = 2; i < x; i++) {
if (x % i == 0) {
isPrime = false;
break;
}
}
- 除了2以外的偶数都不是素数,所以程序可以做以下改进
- 对于n,要循环(n-3)/2+1遍
- 当n很大时,就可以被看做是n/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-1,遍历到sqrt(x)就够了
- 对于n,要循环(sqrt(n)-3)/2+1遍
- 当n很大时,就可以被看做是sqrt(n)/2遍
for (int i = 3; i < Math.sqrt(x); i += 2) {
if (x % i == 0) {
isPrime = false;
break;
}
}
- 还可以判断是否能被已知的且小于x的素数整除,构造前50个素数的表
package com.meteor.array;
public class Prime {
public static void main(String[] args) {
int[] primes = new int[50];
primes[0] = 2;
int cnt = 1;
for (int i = 3; cnt < 50; i++) {
boolean flag = true;
for (int j = 0; j < cnt; j++) {
if (i % primes[j] == 0) {
flag = false;
break;
}
}
if (flag) {
primes[cnt++] = i;
}
}
for (int x : primes) {
System.out.print(x + " ");
}
}
}
- 构造100以内的素数表
- 欲构造n以内的素数表
- 令x为2
- 将2x、3x、4x直至ax
- 欲构造n以内的素数表
package com.meteor.array;
public class Prime1 {
public static void main(String[] args) {
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 j = 2;i*j<isPrime.length; j++) {
isPrime[i*j] = false;
}
}
}
for (int i = 2; i < isPrime.length; i++) {
if (isPrime[i]) {
System.out.print(i+" ");
}
}
}
}
4.3 二维数组
4.3.1 二维数组
- int[][] a = new int[3][5];
- 通常理解为a是一个3行5列的矩阵
- a[i][j]是一个int,表示第i行第j列的单元
二维数组的初始化
int[][] a = {
{1,2,3,4},
{1,2,3},
};
井字棋
- 读入个3×3的矩阵,矩阵中的数字为1表示该位置上有一个X,为0表示为O
- 程序判断这个矩阵中是否有获胜的一方(三个相同的相连),输出表示获胜一方的字符X或O,或输出无人获胜
package com.meteor.array;
import java.util.Scanner;
public class TicTacToe {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
final int SIZE = 3;
int[][] board = new int[SIZE][SIZE];
boolean gotResult = false;
int numOfX = 0;
int numOfO = 0;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
board[i][j] = in.nextInt();
}
}
//检查行
for (int i = 0; i < SIZE; i++) {
numOfX = 0;
numOfO = 0;
for (int j = 0; j < SIZE; j++) {
if (board[i][j] == 0) {
numOfO++;
} else {
numOfX++;
}
}
if (numOfX == SIZE || numOfO == SIZE) {
gotResult = true;
break;
}
}
//检查列
if (!gotResult) {
for (int i = 0; i < SIZE; i++) {
numOfO = 0;
numOfX = 0;
for (int j = 0; j < SIZE; j++) {
if (board[j][i] == 0) {
numOfO++;
} else {
numOfX++;
}
}
if (numOfO == SIZE || numOfX == SIZE) {
gotResult = true;
break;
}
}
}
//检查对角线
if (!gotResult) {
numOfO = 0;
numOfX = 0;
for (int i = 0; i < SIZE; i++) {
if (board[i][i] == 0) {
numOfO++;
} else {
numOfX++;
}
}
if (numOfO == SIZE || numOfX == SIZE) {
gotResult = true;
}
}
//检查对角线
if (!gotResult) {
numOfO = 0;
numOfX = 0;
for (int i = 0; i < SIZE; i++) {
if (board[i][SIZE-i-1] == 0) {
numOfO++;
} else {
numOfX++;
}
}
if (numOfO == SIZE || numOfX == SIZE) {
gotResult = true;
}
}
if (gotResult) {
if (numOfO == SIZE) {
System.out.println("O WIN");
} else {
System.out.println("X WIN");
}
} else {
System.out.println("无人获胜");
}
}
}