1.数组的引出

为什么需要数组

一个有 养鸡场有 6 只鸡,它们的体重分别是 3kg,5kg,1kg,3.4kg,2kg,50kg 。
请问这六只鸡的总体重是多少?平 均体重是多少? 请你编一个程序。 Array01.java

思路:

定义 6 个变量 , 加起来 总体重, 求出平均体重.引出 -> 数组

数组介绍

数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。
即:数(数据)组(一组)就是一组数据

定义数组和方法:

double[] hens = {3, 5, 1, 3.4, 2, 50, 7.8, 88.8,1.1,5.6,100};
方法:数组名.length 得到数组的大小/长度
访问元素:hens[下标],第一个元素就是 hens[0]
遍历元素:for+hens[i]

2.数组的使用:

1.动态初始化:

1.1 声明数组和分配内存空间
数据类型[ ] 数组名 = new 数据类型[大小];
eg:int[ ] a = new int[5];
1.2 先声明数组 int[ ] a;
后分配内存空间a = new int[5];
仅声明数组,a = null

2.静态初始化

数据类型[ ] 数组名 = {元素1,元素2,元素3,元素4,元素5…};
eg: double[ ] hens = {3,5,1,3.4,2,50};

image.png
image.png
image.png
image.png

3.数组使用注意事项和细节:

1) 数组是多个相同类型(或自动转换)数据的组合,实现对这些数据的统一管理
2) 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。
3) 数组创建后,如果没有赋值,有默认值
int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null
4) 使用数组的步骤 1. 声明数组并开辟空间 2.给数组各个元素赋值 3.使用数组
5) 数组的从下标是从 0 开始的。
6) 数组下标必须在指定范围内使用,否则报:下标越界异常,比如
int [] arr=new int[5]; 则有效下标为 0-4
7) 数组属引用类型,数组型数据是对象(object)

4.数组应用案例:

1) 创建一个 char 类型的 26 个元素的数组,分别 放置’A’-‘Z’。使用 for 循环访问所有元素并打印出来。
提示:char 类型 数据运算 ‘A’+1 =’B’ ArrayExercise01.java
2) 请求出一个数组 int[]的最大值 {4,-1,9, 10,23},并得到对应的下标。 ArrayExercise02.java
思路:
老韩思路分析

    1. 定义一个 int 数组 int[] arr = {4,-1,9, 10,23};
    1. 假定 max = arr[0] 是最大值 , maxIndex=0;
    1. 从下标 1 开始遍历 arr, 如果 max < 当前元素,说明max不是真正的 最大值, 我们就交换max=当前元素; maxIndex=当前元素下标
    1. 当我们遍历这个数组 arr 后 , max 就是真正的最大值,maxIndex 最大值 对应的下标

3) 请求出一个数组的和和平均值。(养鸡场)

总结:

char[ ] chars = new char[26]
chars==数组类型
chars[i]==基本数据类型
char类型字符关系== ‘A’+1 =’B’

5.数组赋值机制

1) 基本数据类型赋值,这个值就是具体的数据,而且相互不影响。——>值传递
int n1 = 2;
int n2 = n1;
n2 = 80;
n1 还是=2
2) 数组在默认情况下是引用传递,赋的值是地址。——>引用传递
看一个案例,并分析数组赋值的内存图(重点, 难点. )。
//代码 ArrayAssign.java
int[] arr1 = {1,2,3};
int[] arr2 = arr1;
arr2[0] = 10
实际:arr1 = {10,2,3};
中心规则:基本类型是值传递,引用类型是地址传递
不管是基本数据类型还是引用类型,我们都拷贝一个值,
但是基本数据类型拷贝的是具体数据,引用类型拷贝的是地址
image.png

6.数组拷贝

编写代码 实现数组拷贝(内容复制)ArrayCopy.java
将 int[] arr1 = {10,20,30}; 拷贝到 arr2 数组, 要求数据空间是独立的.

int[] arr2 = new int[arr1.length]; for(int i = 0; i < arr1.length; i++) { arr2[i] = arr1[i]; }

image.png7.数组反转

1.要求:把数组的元素内容反转。ArrayReverse.java
arr {11,22,33,44,55,66}, {66, 55,44,33,22,11}

简单概括:

①头尾交换 ②新建数组

方式 1:通过找规律反转-头尾交换

【思路分析】ArrayReverse.java

  1. 把 arr[0] 和 arr[5] 进行交换 {66,22,33,44,55,11}
  2. 把 arr[1] 和 arr[4] 进行交换 {66,55,33,44,22,11}
  3. 把 arr[2] 和 arr[3] 进行交换 {66,55,44,33,22,11}
  4. 一共要交换 3 次 = arr.length / 2
  5. 每次交换时,对应的下标 是 arr[i] 和 arr[arr.length - 1 -i]

    方式 2:使用逆序赋值方式-逆序赋值

    【思路分析, 学员自己完成】 ArrayReverse02.java

  6. 先创建一个新的数组 arr2 ,大小 arr.length

  7. 逆序遍历 arr ,将 每个元素拷贝到 arr2 的元素中(顺序拷贝)
  8. 建议增加一个循环变量 j -> 0 -> 5
  9. 当 for 循环结束,arr2 就是一个逆序的数组 {66, 55, 44,33, 22, 11}
  10. 让 arr 指向 arr2 数据空间, 此时 arr 原来的数据空间就没有变量引用

image.png
image.png

8.数组添加/扩容

课堂练习:

要求:
实现动态的给数组添加元素效果,实现对数组扩容。ArrayAdd.java
1) 原始数组使用静态分配 int[] arr = {1,2,3}
2) 增加的元素 4,直接放在数组的最后 arr = {1,2,3,4}
3) 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n ArrayAdd02.java

思路分析

  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来控制 (集合的概念)

do-while可以至少循环一次,最开始不用判断循环条件

以下代码也是集合添加元素的大致原理:

//之所以可以不断添加,
//是因为每次循环开始重新定义了arr1(相当于新数组)
//最后把新数组赋值给arr(旧数组)

  1. int[] arr = {1,2,3};
  2. do{
  3. int[] arr1 = new int[arr.length + 1];
  4. for(int i = 0;i < arr1.length - 1;i++){
  5. arr1[i] = arr[i];
  6. }
  7. System.out.println("请输入添加的元素");
  8. int addNum = myScanner.nextInt();
  9. arr1[arr1.length - 1] = addNum;
  10. arr = arr1;
  11. System.out.println("====arr===========");
  12. for(int i = 0;i < arr.length;i++){
  13. System.out.println(arr[i]);
  14. }
  15. System.out.println("是否还要继续添加(y/n)");
  16. char c = myScanner.next().charAt(0);
  17. if(c == 'n'){
  18. break;
  19. }
  20. }while(true);

image.png

课后练习题:

ArrayReduce.java
有一个数组 {1, 2, 3, 4, 5}, 可以将该数组进行缩减,提示用户是否继续缩减,每次缩减最后那个元素。当只剩 下最后一个元素,提示,不能再缩减。
image.png

9.排序的介绍

排序是将多个数据,依指定的顺序进行排列的过程。
排序的分类: 内部排序、外部排序。
简单点:内存中排序、外部排序

1.内部排序:

指将需要处理的所有数据都加载到内部存储器中(内存中)进行排序。
包括(交换式排序法、选择 式排序法和插入式排序法);

2.外部排序法:

数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。

10.冒泡排序法

冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素 的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。

较大的元素往右移动

11. 冒泡排序法原理

冒泡排序法案例:

BubbleSort.java
下面我们举一个具体的案例来说明冒泡法。我们将五个无序:24,69,80,57,13
使用冒泡排序法将其排成一个从小到大的有 序数列。

思路->走代码:

思路->走代码, 你可以自己完整的分析冒泡的执行流程,并可以不看老师代码,也可以写出代码.
image.png

12.查找

介绍:

在 java 中,我们常用的查找有两种:
1) 顺序查找 SeqSearch.java
2) 二分查找【二分法,我们放在算法讲解】

案例演示:

1) 有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:从键盘中任意输入一个名称,判断数列中是否 包含此名称【顺序查找】 要求: 如果找到了,就提示找到,并给出下标值。
2) 请对一个有序数组进行二分查找 {1,8, 10, 89, 1000, 1234} ,输入一个数看看该数组是否存在此数,并且求出下标, 如果没有就提示”没有这个数”。
顺序查找-无序就行——效率低
二分查找-数组有序——效率高

数组查找两大编程思想(重点):

判断是否找到=①boolean flag ②int index = -1 配合 break ③单个计数 ④两个计数

13.多维数组-二维数组

多维数组我们只介绍二维数组。
二维数组的应用场景
比如我们开发一个五子棋游戏,棋盘就是需要二维数组来表示。如图:
image.png

14.二维数组的使用

快速入门案例:

TwoDimensionalArray01.java
请用二维数组输出如下图形
0 0 0 0 0 0
0 0 1 0 0 0
0 2 0 3 0 0
0 0 0 0 0 0

使用方式 1: 动态初始化

TwoDimensionalArray02.java

1) 二维数组定义

  1. 动态初始化

类型[ ][ ] 数组名=new 类型[大小][大小]
比如: int a[ ][ ]=new int[2][3]
2.静态初始化
比如: int a[ ][ ]= {{0,0,0,0,0,0},{0,0,0,0,0,0}

2) 二维数组解读:

二维数组的每个元素是一维数组
一维数组的的元素才是真正元素
访问第(i + 1)个一维数组的(j+1)个值,arr[i][j];

3) 二维数组在内存的存在形式(画图) image.png

使用方式 2: 动态初始化

先声明:类型 数组名[][]; TwoDimensionalArray02.java
再定义(开辟空间):数组名 = new 类型[大小][大小]
有默认值:比如 int 类型的就是 0

使用方式 3: 动态初始化-列数不确定

image.png
如果没有开辟空间就是null
arr[i] = new int[i + 1];

  1. //创建二维数组,一个有3个一维数组,但是每个一维数组还没有开数据空间
  2. int[][] arr = new int[3][];
  3. for(int i = 0; i < arr.length; i++) {//遍历 arr 每个一维数组
  4. //给每个一维数组开空间 new
  5. //如果没有给一维数组 new ,那么 arr[i]就是 null
  6. arr[i] = new int[i + 1];
  7. //遍历一维数组,并给一维数组的每个元素赋值
  8. for(int j = 0; j < arr[i].length; j++) {
  9. arr[i][j] = i + 1;//赋值
  10. }
  11. }

使用方式 4: 静态初始化

TwoDimensionalArray04.java
定义:类型 数组名[][] = {{值 1,值 2..},{值 1,值 2..},{值 1,值 2..}}
使用即可 [固定方式访问]

比如:

int[][] arr = {{1,1,1}, {8,8,9}, {100}};

解读:

  1. 定义了一个二维数组 arr
  2. arr 有三个元素(每个元素都是一维数组)
  3. 第一个一维数组有 3 个元素 , 第二个一维数组有 3 个元素, 第三个一维数组有 1 个元素

    15.经典二维数组练习-杨辉三角:

int arr[][]={{4,6},{1,4,5,7},{-2}}; 遍历该二维数组,并得到和 TwoDimensionalArray05.java

  1. 使用二维数组打印一个 10 行杨辉三角 YangHui.java

image.png

总结:

|| 多个值或满足一个条件
&& 一个值或满足多个条件
|| 相反的是 !&&

  1. int[] arr = {1,2,3,4,5};
  2. for (int i = 0; i < arr.length; i++) {
  3. if(i == 0 || i == 1){
  4. System.out.println(arr[i]);//1,2
  5. }else{
  6. System.out.println(arr[i]);//3,4,5
  7. }
  8. }

16.二维数组使用细节和注意事项

1) 一维数组的声明方式有: int[] x 或者 int x[]
2) 二维数组的声明方式有: int[][] y 或者 int[] y[] 者 或者 int y[][]
3) 二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。
比如: map[][] 是 一个二维数组 ,int map [][] = {{1,2},{3,4,5}}
由 map[0] 是一个含有两个元素的一维数组 ,map[1] 是一个含有三个元素的一维数组构成,我们也称为列数不等
的二维数组

17.二维数组练习

image.png
image.png

18.本章作业

image.png
image.png
image.png
第四题:if双指针,if大小
image.png