六、数组
\1.数组的声明和初始化
\2. 数组的元素访问以及遍历
\3. 数组的应用(冒泡排序、选择排序、顺序查找和二分法查找)
1.1.3.1 数组概念
数组是保持固定数目的同一类型的值的容器对象。元素可以是基本类型或引用类型、通过下标来访问元素、长度固定(length).注意:数组中的每一项称为一个元素,每个元素都由其数字索引访问
注意:数组长度一旦确认,不可改变
数组的元素的索引从0开始,到长度减-1
1.1.3.2. 创建数组
由于数组的特殊性,所以创建数组(分配连续空间)需要采用特殊的语法,语法如下
new 数据类型[长度]
实例:
public static void main(String[] args){
//基本类型变量
int age;
//创建数组
//new int[5];//无效语句,因为使用不了这个数组。以下方式可以使用一次这个数组
System.out.
println((new int[5])
.length);
}
1.1.3.3. 数组变量的声明
数组创建后我们需要记录这个连续空间的地址,然后才可以使用它,在Java中需要通过引用型变量来**存放地址**,引用型变量需要声明,声明语法如下:
注意:推荐使用方式一,更加明确
示例:
public static void main(String[] args){
//基本类型变量
int age;
//声明数组变量(引用型变量)
int[] ages;
//创建数组,保存地址
ages=new int[5];
}
1..1.3.4. 数组元素初始化
我们创建了一个数组(同类型的连续空间),并且通过一个引用型变量记录了数组的起始地址。然后通过引用型变量中的地址就可以使用数组空间,语句如下
引用型变量名[索引]
实例:
public static void main(String[] args){
//基本类型变量
int age;
//声明数组变量(引用型变量)
int[] ages;
//创建数组,保存地址
ages=new int[5];
//数组元素初始化(第
一
次明确赋值)
ages[0]
=1;
}
1.1.3.5. 数组的其它语法
1.1.3.5.1. 数组变量声明、数组创建整合
实际使用时可以将数组变量声明、数组创建整合为一条语句。如:数组元素默认值:
数组类型[] 数组变量名 = new 数组元素类型[5];
整数型为0
浮点型为0.0
字符型为‘\u0000’
(不同的系统平台显示结果不同)
布尔类型为false
引用类型为null
也可以创建数组时不指定长度,而使用元素值来取代:
数组元素类型[] 数组名 = new 数组元素类型[]{元素0,元素1,....};
或者
数组元素类型[] 数组名 = {元素0,元素1,....};
有几个元素值,数组长度就是几;而且元素默认值是此处给出的值
1.1.3.5.2. 其它类型的数组示例
1.1.3.5.3. 数组的使用
\1. 通过下标访问指定元素
Java语言的数组索引(下标、角标)是从0开始的,数组的下标的最大值长度-1不要超出索引的范围,如果超出范围出现异常 java.lang.ArrayIndexOutOfBoundsException
\2. 获取数组元素的个数
在Java中,所有数组都提供了一个length属性,通过这个属性可以访问到数组的长度
System.out.println(ages.length);
\3. 遍历数组
依次访问数组中的每一个元素,获取每个下标对应的元素值简单for循环
\3. 遍历数组
依次访问数组中的每一个元素,获取每个下标对应的元素值
简单for循环
public static void main(String[] args) {
int[] ages = new int[5];
//数据元素初始化
for (int i =
0; i < ages.length; i++) {
ages[i]
= i;
}
//数据元素获取
for (int i =
0; i < ages.length; i++) {
System.out.
println(ages[i]);
}
}
增强for循环(foreach)
public static void main(String[] args) {
int[] ages = new int[5];
//数据元素初始化,这是没用的,赋值的是age变量,不是数组元素
for (int age: ages) {
age=1;
}
//数据元素获取
for (int age: ages) {
System.out.
println(age);
}
}
1.1.3.6. 数组元素的排序
排序是一个非常经典的问题,它以一定的顺序对一个数组(或一个列表)中的元素进行重新排序。有许多不同的排序算法,每个算法都有其自身的优点和局限性。
\1. 数组排序的必要性
在数组 A 中搜索特定值 v
查找数组 A 中的最小或者最大值
测试唯一性并删除数组中的重复元素
计算特定值 v 在数组 中出现多少次
获取两个排序数组之间的交集/并集
\2. 什么是算法
计算的方法,解决问题的方案
1.1.3.6.1. 冒泡排序**(Bubble Sort)**
每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。一次冒泡会让至少一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作。对一个有N个元素(如:5个元素)的数组进行冒泡排序的思路:
\1. 比较一对相邻元素(如:ages[0]、ages[1])
\2. 如果大小关系不符合规则(如规则:ages[0]<ages[1]),则交换数据
\3. 重复步骤1、2,直到数组末尾(最后比对的是ages[3]、ages[4])
\4. 重复步骤3,每次重复直到所有元素都以排序
\1. 初始数据
\2. 第一次冒泡
5个元素,相邻元素整体比对一
遍,需要执行5-1次(ages.length-1),第一次冒泡结束后的结果如下:
\3. 第二次冒泡
第二次冒泡不需要最后一个元素参与比对,所以需要执行5-2次(ages.length-11),,第二次冒泡结束后的结果如下:
\4. 多次冒泡 如果有5个元素,每次冒泡找到一个最大的,则需要执行5次,也可以是5-1次(最后一个元素可排可不排),每次冒泡不再处理前几次冒泡的元素(ages.length - 1-j)。多次冒泡后的结果:
\5. 冒泡优化
如果数据是相对有顺的,如:{1,2,3,5,4},则是否有优化的方式?
思路:如果某次冒泡没有发生数据交换,则数组以及是有序的,则跳出冒泡
1.1.3.6.2. 插入排序**(Insertion Sort)--可选
将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有
一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。
实现思路:
插入排序法:
在已经排好顺序的数组中插入一个新的元素,数组仍然保持原有排序方式I
1、查找要插入的元素在数组中应该存在位置
2、创建新数组,长度为原数组长度加1
3、将新元素应该存在位置及之后的元素向后移一个位置
4、将新元素插入到其应该存在的位置
\1. 初始数据
\2. 第一次插入
从未排序区间取第一
数据出来(待插入数据,如:4),保存到临时变量,作为本次要插入到已排序区间的数据,由后往前与已排序区间的数据比对,如果发现待插入数据比已排序区间的某个元素小,则已排序区间的那个元素后移,否则结束查找过程,当前位置的后一个即为插入位置。
本次插入的数据是4,已排序区间包括{2},4需要和2比对。不移动、不插入
\3. 第二次插入
从未排序区间取第一数据出来(待插入数据,如:3),保存到临时变量,作为本次要插入到已排序区间的数据,由后往前和已排序区间的数据比对,如果发现待插入数据比已排序区间的某个元素小,则已排序区间的那个元素后移,否则结束查找过程,当前位置的后一个即为插入位置。
本次插入的数据是3,已排序区间包括{2、4}。3和4比对,发现4大,则4往后移动;3和2比对,发现3 大,则结束比对,4和2中间的位置即为插入位置
\4. 多次插入
如果有5个元素,每次插入一个未排序元素到到已排序区间,则需要执行4次。
1.1.3.6.3. 选择排序**(Selection sort)--可选**
第一次从待排序的数据中选择出最小的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
\1. 初始数据
假设所有数据都是未排序的
\2. 第一次选择
从未排序区间找出最小的数,然后放入到已排序区间的末尾。
本次选择出的是1。选择过程:2和4比对,不交换;2和3比对,不交换;2和5比对,不交换,;2和1 比对,交换
\3. 第二次选择
从未排序区间找出最小的数,然后放入到已排序区间的末尾。
本次选择出的是2。选择过程:4和3比对,交换;3和5比对,不交换;3和2比对,交换
\4. N次选择
从未排序区间找出最小的数,然后放入到已排序区间的末尾。
1.1.3.7. 数组元素的查找
1.1.3.7.1. 顺序查找
遍历整个数组,依次把每一位元素和要查找的数据进行比较
1.1.3.7.2. 二分法查找**(Binary Search)**
二分查找(Binary Search)算法,也叫折半查找算法。前提是数组是有序(升序或者降序)的,将待查找的元素与中间下标对应的元素比较,如果大于中间下标对应的元素,则去右半部分查找。直到找到要查找的元素,或者区间被缩小为0。
1.1.4. 关键知识点默写
\1. eclipse的基本使用
\2. 数组是保持固定数目的同一类型的值的容器对象
\1. 数组变量(属于引用型变量<对应于基本类型变量>),int[] arr或者int arr[]
\2. 创建数组,new int[5]
\3. 数组创建、数组变量声明整合
\1. int[] arr=new int[5];
\2. int[] arr=new int[]{1,2,3,4,5};
\3. int[] arr={1,2,3,4,5};
\4. 数组的使用
\1. 通过下标访问元素,下标的范围0-长度-1,arr[0],数组元素有默认值
\2. 使用length属性获取数组的长度
\3. 遍历数组元素
\1. for
\2. 增强for
\5. 排序: 冒泡排序、 插入排序、 选择排序
\6. 查找: 顺序查找 二分法查找
\3. 通过数组变量理解引用型变量引用型变量放的是个地址,便于通过一个变量找到多个空间
1.1.5. 常见面试题
\1. 基本数据类型和引用数据类型之间的区别?打印结果是什么?
public static void main(String[] args) {
int[] ages = {6};
int age = 6;
for (int i : ages) {
System.out.println(i);
}
System.out.println(ages[0]);
System.out.println(age);
}
public static void change(int[] ages, int age) {
ages[0] = 10;
age = 10;
}
\2. 在Java中,声明一个数组过程中,是如何分配内存的?
1.当声明数组类型变量时,为其分配了(32位)引用空间,由于未赋值,因此并不指向任何对象;
2.当创建了一个数组对象(也就是new出来的)并将其地址赋值给了变量,其中创建出来的那几个数组元素相当于引用类型变量,因此各自占用(32位的)引用空间并按其默认初始化规则被赋值为null
3.程序继续运行,当创建新的对象并(将其地址)赋值给各数组元素,此时堆内存就会有值了
\3. 数组的定义方式?
\1. int[] arr=new int[5];
\2. int[] arr=new int[]{1,2,3,4,5};
\3. int[] arr={1,2,3,4,5};
\4. 说说你知道的数组排序算法? 写个冒泡算法?
冒泡、插入、选择、顺序、二分查找排序