数组
一、数组
数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。即:数组就是一组数据。
二、一维数组
1、数组的初始化
(1)动态初始化
- 第1种动态分配方式:
语法:数据类型[ ] 数组名 = new 数据类型[大小]
int[] a = new int[5];
//创建了一个数组,名字a,存放5个int
- 第 2 种动态分配方式:
先声明数组,再 new 分配空间
int[]a 这条语句只声明了变量a,并没有将a初始化为一个真正的数组。应该使用new操作符创建数组。
int[] a;
//或者 int a[];
a = new int[5];
(2)静态初始化
语法:数据类型 数组名[ ] = {元素值1,元素值2,…};
int a[] = {1, 2, 3, 4};
等价于
int[] a = new int[4];
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
2、数组的引用(使用/访问)
语法: 数组名[下标/索引/index]
int[] Array = {1,2,3,4};
for(int i = 0; i < 4; i++) {
System.out.println("第"+(i+1)+"个元素的值 = " + Array01[i])
}
3、数组长度
语法:数组名.length
for(int i = 0; i < Array01.length; i++) {
System.out.println("第"+(i+1)+"个元素的值 = " + Array01[i])
}
一旦创建了数组,就不能再改变它的长度(不过,当然可以改变单个的数组元素)。如果程序运行中需要经常扩展数组的大小,就应该使用另一种数据结构——数组列表(array list)。
4、数组的使用细节
(1)数组是多个相同类型数据的组合,实现对这些数据的统一管理
int[] arr1 = {1, 2, 3, 60,"hello"};//String ->int
int[] arr3 = {1, 2, 3, 60, 1.1};//double ->int
上述代码,是错的,1.1是double类型,存储到低精度的int数组中是不行的。String类型“hello”也不能直接存进int数组
double[] arr2 = {1.1, 2.2, 3.3, 60.6, 100};//int ->double
上述代码是正确的。
(2)数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
字符串是属于对象的,也属于引用类型。
String[] arr3 = {"北京","jack","milan"};
(3)数组创建后,如果没有赋值,有默认值
int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000(U表示后面是十六进制,就是属于字符),boolean false,String null
(4)使用数组的步骤 1. 声明数组并开辟空间 2 给数组各个元素赋值 3 使用数组
(5)数组的下标是从 0 开始的
(6)数组下标必须在指定范围内使用,否则报:下标越界异常
(7)数组属引用类型,数组型数据是对象(object)
5、例题(控制台的输入)
(1)循环输入5个成绩,保存到double数组,并输出
import java.util.Scanner;
public class Array01 {
public static void main(String[] args) {
double scores[] ;
scores = new double[5];
//循环输入
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)创建一个char类型的26个元素的数组,分别放置’A-Z’。使用for 循环访问所有元素并打印出来。提示: char类型数据运算 ‘A’+2->'CArrayExercise01.java
arr[i] = (char)(‘A’ + 1); //需要强制转化
public class Array02 {
//编写一个 main 方法
public static void main(String[] args) {
char[] arr = new char[26];
for(int i = 0; i < arr.length; i++) {
arr[i] = (char)('A' + i); //需要强制转化
}
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
(3)请求出一个数组 int[]的最大值{4,-1,9,10,23},并得到对应的下标。
public class Array03 {
//编写一个 main 方法
public static void main(String[] args) {
int[] a = {4,-1,9,10,23};
int max = 0;
int i;
for(i = 1; i < a.length; i++) {
if(a[i] > a[max]) {
max = i;
}
}
System.out.println(max);
}
}
6、数组赋值机制
(1)基本数据类型赋值
赋值方式是 值拷贝
int n1 = 10;
int n2 = n1;
n2 = 80;
System.out.println("n1 = " + n1);
System.out.println("n2 = " + n2);
(2)数组在默认情况下是引用传递,赋的值是地址。
赋值方式是 引用传递
int[] arr1 = {1,2,3};
int[] arr2 = arr1;
arr2[0] = 10;
for(int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
}
【重要】 值传递/值拷贝 和 引用传递的区别
例题:数组拷贝
编写代码实现数组拷贝(内容复制) 将int[] arr1 = {10,20,30};拷贝到 arr2数组,要求数据空间是独立的。
int[] arr1 = {10,20,30};
int[] arr2 = new int[arr1.length];
for(int i = 0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
for(int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
7、题目
(1)数组翻转
public class ArrayReverse {
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55, 66};
int temp;
int len = arr.length;
for(int i = 0; i < len/2; i++) {
temp = arr[i];
arr[i] = arr[len-1-i];
arr[len-1-i] = temp;
}
for(int i = 0; i < len; i++) {
System.out.println(arr[i]);
}
//方法二
int[] myArr = {11,22,33,44,55,66};
int[] myArr2 = new int[myArr.length];
for(int i = myArr.length-1, j = 0; i >= 0; i --, j++) {
myArr2[j] = myArr[i];
}
myArr = myArr2;//指向反转之后的数组
//此时myArr原来的数据空间没有变量引用,会被当作垃圾销毁
System.out.println();
for(int i = 0; i < myArr.length; i++) {
System.out.println(myArr[i]);
}
}
}
注意
①for循环里面,int i = myArr.length-1, j = 0 中的 j 前面不可以再写 int ,会报错
②myArr指向了myArr2的地址,myArr原来的数据空间没有变量引用,会被当作垃圾销毁
(2)数组扩容
要求:实现动态的给数组添加元素效果,实现对数组扩容。
① 原始数组使用静态分配 int[] arr = {1,2,3}
② 增加的元素 4,直接放在数组的最后 arr = {1,2,3,4}
③ 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
import java.util.Scanner;
public class ArrayEnlarge {
//编写一个 main 方法
public static void main(String[] args) {
Scanner myScanner = new Scanner(System.in);
int[] arr = {1, 2, 3};
while(true) {
System.out.println("是否继续输入?(y/n)");
char flag = myScanner.next().charAt(0);
if(flag == 'n') {break;}
else {
System.out.println("请输入需要添加到数组中的数字:");
int num = myScanner.nextInt();
int[] myArr = new int[arr.length+1];
for(int i = 0; i < arr.length; i++) {
myArr[i] = arr[i];
}
myArr[arr.length] = num;
arr = myArr;
}
}//end while
System.out.println();
System.out.println("扩容后的数组如下:");
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
注意
①键盘输入char
char flag = myScanner.next().charAt(0);
②字符串用双引号,字符用单引号。
③字符串的比较 用equals: if(str1.equals(str2))
(3)数组缩减
有一个数组 {1, 2, 3, 4, 5}, 可以将该数组进行缩减,提示用户是否继续缩减,每次缩减最后那个元素。当只剩下最后一个元素,提示,不能再缩减。
import java.util.Scanner;
public class ArrayReduce {
public static void main(String[] args) {
Scanner myScanner = new Scanner(System.in);
int[] arr = {1, 2, 3, 4, 5};
do{
if(arr.length == 1) {
System.out.println("只剩下最后一个元素,不能再缩减");
break;
}
System.out.print("是否继续缩减(y/n): ");
char flag = myScanner.next().charAt(0);
if(flag == 'n') {
break;
}
int[] tmp = new int[arr.length-1];
for(int i = 0; i < tmp.length; i++) {
tmp[i] = arr[i];
}
arr = tmp;
}while(true);
System.out.println("缩减后的数组如下:");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+"\t");
}
}
}
三、排序入门
1、排序的介绍
排序是将多个数据,依指定的顺序进行排列的过程
2、排序分类
(1)内部排序:
指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择式排序法和插入式排序法)。
(2)外部排序:
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。
四、查找入门
在 java 中,我们常用的查找有两种:
- 顺序查找 SeqSearch.java
- 二分查找【二分法,我们放在算法讲解】
五、多维数组-二维数组
以二维数组为例。
1、数组使用
(1)动态初始化
a. 定义数组
语法1: 类型[][] 数组名=new 类型[大小][大小]
有默认值
前一个大小是一维数组大小,后一个大小是二维数组大小。
比如: int a[][]=new int[2][3];
b. 先声明,再开辟空间
语法2: 先声明,再开辟空间
类型[][] 数组名 ;
数组名 =new 类型[大小][大小]
比如:
int a[][];
a=new int[2][3];
c.列数不确定
Java的二维数组可以看成多个一维数组。这里的一维数组的长度可以不一样。
比如:
int[][] arr = { {0},
{0,0},
{0,0,0}
{0,0,0,0}};
示例
创建数组
1
2 2
3 3 3
//列数不确定的二维数组初始化
int[][] arr2 = new int[3][]; //创建二维数组,但是只是确定一维数组的个数
for(int i = 0; i < arr2.length; i++) {//遍历每个一维数组
arr2[i] = new int[i+1];
for(int j = 0; j < arr2[i].length; j++) {
arr2[i][j] = i+1;
}
}
for(int i = 0; i < arr2.length; i++) {
for(int j = 0; j < arr2[i].length; j++) {
System.out.print(arr2[i][j] + " ");
}
System.out.println();//换行
}
(2)静态初始化
int[][] arr = { {0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0},
{0, 2, 0, 3},
{0} };
2、数组使用细节
- 一维数组的声明方式有:
int[] x 或者 int x[] - 二维数组的声明方式有:
int[][] y 或者 int[] y[] 或者 int y[][]
解释 int[ ] y[ ] : int[ ] 表示一维数组
int[][] a = new int[2][3];
int[] a[] = new int[2][3];
- 二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。
3、示例
(1)打印二维数组
public class TwoDimensionalArray {
public static void main(String[] args) {
int[][] arr = { {0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0},
{0, 2, 0, 3, 0, 0},
{0, 0, 0, 0, 0, 0} };
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();//换行
}
}
}
(1) 二维数组的元素个数(行)
System.out.println(“二维数组的元素个数=” + arr.length);
(2) 二维数组的每个元素是一维数组, 所以如果需要得到每个一维数组的值
(3) 如果我们要访问第 (i+1)个一维数组的第 j+1 个值 arr[i][j];
(2)二维数组求和
public class ArrayPractice {
public static void main(String[] args) {
//int arr[][]={{4,6},{1,4,5,7},{-2}}; 遍历该二维数组,并得到和
int arr[][]={{4,6},{1,4,5,7},{-2}};
int sum = 0;
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
sum += arr[i][j];
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
System.out.print("数组arr的和为 "+ sum);
}
}
注意
System.out.print(arr[i][j] + “\t”);这一句话 不可以是‘\t’,因为输出的是字符串。
(3)杨辉三角
【杨辉三角】
1.第一行有1个元素,第n行有n个元素
2.每一行的第一个元素和最后一个元素都是1
3.从第三行开始,对于非第一个元素和最后一个元素的元素的值
arr[i][j] = arr[i-1][j-1] + arr[i-1][j];
int[][] arr = new int[n][];
for(int i = 0; i < n; i++) {
arr[i] = new int[i+1];
arr[i][0] = arr[i][i] = 1;//第一列最后一列都为1
if(n >= 2) {
for(int j = 1; j < i; j++) {
arr[i][j] = arr[i-1][j-1] + arr[i-1][j];
}
}
}
另一种写法:
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];
}
}
}
(4)练习
声明:int[ ]x,y[ ];
说明:x是int类型一维数组, y是int类型的二维数组
以下选项允许通过编译的是():
a) x[0]=y;
b) y[0] = x;
c) y[0][0] = x;
d) x[0][0] = y;
e) y[0][0] = x[0];
f) x=y;
a) x[0]=y;//错误int[][]->int[]
b) y[0] = x;//正确int[] -> int[]
c) y[0][0] = x;//错误int[]->int
d) x[0][0] = y;//错误x[0][0]是错误
e) y[0][0] = x[0];//正确int->int
f) x=y;/错误int[][]->int[]
4、二维数组的内存布局
int arr[][] = new int[2][3];
本笔记是对韩顺平老师的Java课程做出的梳理。方便本人和观看者进行复习。
课程请见: https://www.bilibili.com/video/BV1fh411y7R8/?spm_id_from=333.999.0.0&vd_source=ceab44fb5c1365a19cb488ab650bab03