- 第6章 数组、排序和查找
-
- 数组介绍
-
- 数组的使用
-
-
- 使用方式1-动态初始化数组的定义
-
-
-
- 使用方式2-动态初始化
-
-
-
- 使用方式3-静态初始化
-
-
- 数组使用注意事项和细节
-
- 数组应用案例
-
- 数组赋值机制
-
- 数组拷贝
-
- 数组添加/扩容
-
- 多维数组 二维数组
-
-
- 动态初始化1
-
-
-
- 动态初始化2
-
-
-
- 静态初始化
-
-
- 二维数组的应用案例
-
- 二维数组使用细节和注意事项
第6章 数组、排序和查找
数组介绍
数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。
数组的使用
使用方式1-动态初始化数组的定义
数据类型数组名[]=new数据类型[大小]
int a[] = new int[5];//创建了一个数组,名字a,存放5个int
说明: 这是定义数组的一种方法。
import java.util.Scanner;
public class Array02 {
//编写一个main方法
public static void main(String[] args) {
//演示 数据类型 数组名[]=new 数据类型[大小]
//循环输入5个成绩,保存到double数组,并输出
//步骤
//1. 创建一个 double 数组,大小 5
//(1) 第一种动态分配方式
//double scores[] = new double[5];
//(2) 第2种动态分配方式, 先声明数组,再 new 分配空间
double scores[] ; //声明数组, 这时 scores 是 null
scores = new double[5]; // 分配内存空间,可以存放数据
//2. 循环输入
// scores.length 表示数组的大小/长度
//
Scanner myScanner = new Scanner(System.in);
for( int i = 0; i < scores.length; i++) {
System.out.println("请输入第"+ (i+1) +"个元素的值");
scores[i] = myScanner.nextDouble();
}
//输出,遍历数组
System.out.println("==数组的元素/值的情况如下:===");
for( int i = 0; i < scores.length; i++) {
System.out.println("第"+ (i+1) +"个元素的值=" + scores[i]);
}
}
}
使用方式2-动态初始化
1.先声明数组
语法:数据类型数组名[]; 也可以数据类型[] 数组名;
int a[]; 或者int[] a;
2.创建数组
语法: 数组名=new 数据类型[大小];
a=new int[10];
使用方式3-静态初始化
初始化数组
语法:
数据类型 数组名[]={元素值,元素值...}
int a[]={2,5,6,7,8,89,90,34,56},
数组使用注意事项和细节
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。
- 数组创建后,如果没有赋值,有默认值
int 0short 0byte 0long 0float 0.0double 0.0 char \u0000boolean falseString null
- 数组属引用类型,数组型数据是对象(object)
数组应用案例
创建一个char 类型的26 个元素的数组,分别放置'A'-'Z'。使用for 循环访问所有元素并打印出来。提示:char 类型数据运算'A'+2 -> 'C'
public class ArrayExercise01 {
//编写一个main方法
public static void main(String[] args) {
/*
创建一个char类型的26个元素的数组,分别 放置'A'-'Z'。
使用for循环访问所有元素并打印出来。
提示:char类型数据运算 'A'+1 -> 'B'
思路分析
1. 定义一个 数组 char[] chars = new char[26]
2. 因为 'A' + 1 = 'B' 类推,所以老师使用for来赋值
3. 使用for循环访问所有元素
*/
char[] chars = new char[26];
for( int i = 0; i < chars.length; i++) {//循环26次
//chars 是 char[]
//chars[i] 是 char
chars[i] = (char)('A' + i); //'A' + i 是int , 需要强制转换
}
//循环输出
System.out.println("===chars数组===");
for( int i = 0; i < chars.length; i++) {//循环26次
System.out.print(chars[i] + " ");
}
}
}
数组赋值机制
数组在默认情况下是引用传递,赋的值是地址。(相比:变量往往是值传递)
int[] arr1 = {1,2,3};
int[] arr2 = arr1;
数组拷贝
编写代码实现数组拷贝(内容复制)
int[] arr1 = {10,20,30};
int[] arr2 = new int[arr1.length];
for(int i = 0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
数组添加/扩容
要求:实现动态的给数组添加元素效果,实现对数组扩容。
- 原始数组使用静态分配 int[] arr = {1,2,3}
- 增加的元素4,直接放在数组的最后arr = {1,2,3,4}
- 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
1. 定义初始数组int[] arr = {1,2,3}//下标0-2
2. 定义一个新的数组int[] arrNew = new int[arr.length+1];
3. 遍历arr 数组,依次将arr 的元素拷贝到arrNew 数组
4. 将4 赋给arrNew[arrNew.length - 1] = 4;把4 赋给arrNew 最后一个元素
5. 让arr 指向arrNew ; arr = arrNew; 那么原来arr 数组就被销毁
6. 创建一个Scanner可以接受用户输入
7. 因为用户什么时候退出,不确定,使用do-while + break 来控制
多维数组 二维数组
动态初始化1
- 语法: 类型[][] 数组名=new 类型[大小][大小]
- 比如: int a[][]=new int[2][3]
- 二维数组在内存的存在形式(!!画图)
动态初始化2
先声明:类型数组名[][];
再定义(开辟空间) 数组名= new 类型[大小][大小]
赋值(有默认值,比如int 类型的就是0)
静态初始化
定义类型数组名[][] = {{值1,值2..},{值1,值2..},{值1,值2..}}
int[][] arr = {{1,1,1}, {8,8,9}, {100}};
二维数组的应用案例
使用二维数组打印一个10 行杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1.第一行有1个元素,第n行有n个元素
2.每一行的第一个元素和最后一个元素都是1
3.从第三行开始,对于非第一个元素和最后一个元素的元素的值.
arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
public class YangHui {
//编写一个main方法
public static void main(String[] args) {
/*
使用二维数组打印一个 10 行杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
规律
1.第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素的值. arr[i][j]
arr[i][j] = arr[i-1][j] + arr[i-1][j-1]; //必须找到这个规律
*/
int[][] yangHui = new int[12][];
for(int i = 0; i < yangHui.length; i++) {//遍历yangHui的每个元素
//给每个一维数组(行) 开空间
yangHui[i] = new int[i+1];
//给每个一维数组(行) 赋值
for(int j = 0; j < yangHui[i].length; j++){
//每一行的第一个元素和最后一个元素都是1
if(j == 0 || j == yangHui[i].length - 1) {
yangHui[i][j] = 1;
} else {//中间的元素
yangHui[i][j] = yangHui[i-1][j] + yangHui[i-1][j-1];
}
}
}
//输出杨辉三角
for(int i = 0; i < yangHui.length; i++) {
for(int j = 0; j < yangHui[i].length; j++) {//遍历输出该行
System.out.print(yangHui[i][j] + "\t");
}
System.out.println();//换行.
}
}
}
二维数组使用细节和注意事项
- 一维数组的声明方式有:
int[] x 或者int x[]
- 二维数组的声明方式有:
int[][] y 或者int[] y[] 或者int y[][]
- 二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。比如: map[][] 是一个二维数组
int map [][] = {{1,2},{3,4,5}}
由map[0] 是一个含有两个元素的一维数组,map[1] 是一个含有三个元素的一维数组构成,我们也称为列数不等的二维数组
好的,我会详细拓展每一部分,确保您能够全面理解杨辉三角的实现以及二维数组的使用细节和注意事项。
1. 二维数组的声明和初始化
一维数组的声明方式
int[] x;
或int x[];
二维数组的声明方式
int[][] y;
或int[] y[];
或int y[][];
2. 二维数组的初始化
二维数组实际上是由多个一维数组组成的。每个一维数组可以有不同的长度,这使得二维数组可以是矩形的,也可以是不规则的。
示例
int[][] map = {{1, 2}, {3, 4, 5}};
在这个例子中:
map[0]
是一个含有两个元素的一维数组{1, 2}
。map[1]
是一个含有三个元素的一维数组{3, 4, 5}
。
3. 打印杨辉三角
代码解析
public class YangHui {
public static void main(String[] args) {
/*
使用二维数组打印一个 10 行杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
规律
1. 第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素的值. arr[i][j]
arr[i][j] = arr[i-1][j] + arr[i-1][j-1]; //必须找到这个规律
*/
// 创建一个 12 行的二维数组(第 0 行不使用)
int[][] yangHui = new int[12][];
// 遍历每一行
for (int i = 0; i < yangHui.length; i++) {
// 给每个一维数组(行)分配空间
yangHui[i] = new int[i + 1];
// 给每个一维数组(行)赋值
for (int j = 0; j < yangHui[i].length; j++) {
// 每一行的第一个元素和最后一个元素都是 1
if (j == 0 || j == yangHui[i].length - 1) {
yangHui[i][j] = 1;
} else { // 中间的元素
yangHui[i][j] = yangHui[i - 1][j] + yangHui[i - 1][j - 1];
}
}
}
// 输出杨辉三角
for (int i = 0; i < yangHui.length; i++) {
for (int j = 0; j < yangHui[i].length; j++) { // 遍历输出该行
System.out.print(yangHui[i][j] + "\t");
}
System.out.println(); // 换行
}
}
}
代码详解
- 创建二维数组
int[][] yangHui = new int[12][];
-
- 创建一个 12 行的二维数组,第 0 行不使用,实际使用 1 到 11 行。
- 遍历每一行
for (int i = 0; i < yangHui.length; i++) {
yangHui[i] = new int[i + 1];
-
- 为每一行分配空间,第
i
行有i + 1
个元素。
- 为每一行分配空间,第
- 给每个一维数组(行)赋值
for (int j = 0; j < yangHui[i].length; j++) {
if (j == 0 || j == yangHui[i].length - 1) {
yangHui[i][j] = 1;
} else {
yangHui[i][j] = yangHui[i - 1][j] + yangHui[i - 1][j - 1];
}
}
-
- 每一行的第一个和最后一个元素都是 1。
- 其他元素的值等于上一行同一列和前一列的元素之和。
- 输出杨辉三角
for (int i = 0; i < yangHui.length; i++) {
for (int j = 0; j < yangHui[i].length; j++) {
System.out.print(yangHui[i][j] + "\t");
}
System.out.println();
}
-
- 遍历每一行并输出每个元素,使用制表符
\t
分隔。 - 每行输出完毕后换行。
- 遍历每一行并输出每个元素,使用制表符
4. 二维数组使用细节和注意事项
- 声明和初始化
-
- 二维数组可以声明为
int[][]
、int[][]
或int[][][]
。 - 初始化时可以指定每个一维数组的长度,也可以动态分配。
- 二维数组可以声明为
int[][] matrix = new int[3][4]; // 3 行 4 列的矩形数组
int[][] jaggedArray = new int[3][]; // 3 行,每行的列数可以不同
jaggedArray[0] = new int[2];
jaggedArray[1] = new int[3];
jaggedArray[2] = new int[4];
- 访问和修改
-
- 访问二维数组的元素使用
array[row][column]
。 - 修改元素时也使用相同的语法。
- 访问二维数组的元素使用
int[][] matrix = new int[3][4];
matrix[0][0] = 1; // 访问并修改元素
int value = matrix[0][0]; // 访问元素
- 不规则二维数组
-
- 二维数组的每个一维数组可以有不同的长度。
- 例如:
int[][] map = {{1, 2}, {3, 4, 5}};
。
int[][] map = {{1, 2}, {3, 4, 5}};
System.out.println(map[0][1]); // 输出 2
System.out.println(map[1][2]); // 输出 5
- 遍历
-
- 使用嵌套的
for
循环遍历二维数组。 - 外层循环遍历行,内层循环遍历列。
- 使用嵌套的
int[][] matrix = new int[3][4];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
- 内存布局
-
- 二维数组在内存中是以一维数组的形式存储的,每个一维数组是连续的。
- 例如,
int[][] array = new int[3][4];
在内存中是按行存储的。
array[0] -> [0, 0, 0, 0]
array[1] -> [0, 0, 0, 0]
array[2] -> [0, 0, 0, 0]
5. 常见问题和解决方案
- 数组越界异常
-
- 确保在访问数组元素时,索引在合法范围内。
int[][] matrix = new int[3][4];
try {
System.out.println(matrix[3][0]); // 会导致 ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界异常");
}
- 初始化不完全
-
- 确保每个一维数组都被正确初始化。
int[][] jaggedArray = new int[3][];
jaggedArray[0] = new int[2];
jaggedArray[1] = new int[3];
jaggedArray[2] = new int[4];
- 性能优化
-
- 在处理大规模数据时,考虑使用更高效的数据结构或算法。
- 例如,使用
ArrayList
代替数组,或者使用多线程处理数据。