概述
数组是相同数据类型的多个数据的容器。
这些元素按线性顺序排列。所谓线性顺序是指除第一个元素外,每一个元素都有唯一的前驱元素;除最后一个 元素外,每一个元素都有唯一的后继元素。(“简单理解就是:一个跟一个顺序排列”)。
创建格式
格式 1. 数据类型[] 数组名称 = new 数据类型[数组长度];
格式 2. 数据类型[] 数组名称 = {数组内容 1,数组内容 2,数组内容 3...数组内容 n};
格式 3. 数据类型[] 数组名;
格式 3 属于只创建了数组引用名, 并未在内存创建数组空间。
格式 4. 数据类型[] 数组名称 = new 数据类型[]{内容 1,内容 2,内容 3...内容 n};
下标
可以理解为数组中内容的数字序号,从 0 开始 ,对于长度为 n 的数组,下标的范围是 0~n-1。 可以通过下标的方式访问数组中的每一个元素。 例如: 创建 int 类型数组 arr , 给数组 arr 的 5 下标赋值数据 , 然后打印 int[] arr = new int[10]; arr[5] = 123; System.out.println(arr[5]);
数组长度获取
数组名称.length
注意 使用数组不当, 会出现如下问题:
- 数组未赋值: 空指针异常
- 超出长度的下标操作: 数组越界异常 (数组的长度在创建时就固定了)
局部变量需要赋值(不管基本数据类型还是数组都要赋值否则引用该变量时编译阶段就会报错)
求数组的最大值最小值算法
int[] array= {1,2,3,4,5,55,345,64,23,78,98};
int max=array[0];
for (int i = 1; i < array.length; i++) {
max=max>=array[i]?max:array[i];
}
System.out.println(max);
数组常用算法
冒泡排序
原理:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的 数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
名字由来: 是因为最小(或最大)的元素会经由交换慢慢“浮”到数列的顶端(降序或升序),就如同水中的气泡最终会上浮到 顶端一样,故名“冒泡排序”。
升/降序排列的口诀:
N个数字来排队 两两相比小靠前, 外层 循环length-1 内层循环length-i-1
N个数字来排队 两两相比大靠前, 外层 循环length-1 内层循环length-i-1
int[] array= {1,2,3,4,5,55,345,64,23,78,98};
//外层循环控制比较轮数
for (int i = 0; i < array.length-1; i++) {
//内层循环控制每轮比较的次数
for (int j = 0; j < array.length-i-1; j++) {
if (array[j]>array[j+1]) {
int temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
二分查找 (折半查找)
概述
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,二分查找要求数组数据必须采用顺序存储结构有序排列。
原理
假设数组中元素是按升序排列,将数组中间位置的数据与查找数据比较,如果两者相等,则查找成功;否则利用中间位置记录将数组分成前、后两个子数组,如果中间位置数据大于查找数据,则进一步查找前子数组,否则进一步查 找后子数组。 重复以上过程,直到找到满足条件的数据,则表示查找成功, 直到子数组不存在为止,表示查找不成功。
技巧:
- 确定查找的范围(最小到最大)
- 计算中间的下标(最小+最大/2)
- 比较中间下标数据,中间数据较大,则最大下标等于中间下标-1 比较中间下表数据,中间数据较小,则最小下标等于中间下标+1
- 当最小下标大于最大下标,数据不存在
int[] array= {1,2,3,4,5,55,64,78,98};
//要查找的数值
int num=78;
//最小范围下标
int minindex=0;
//最大范围下标
int maxindex=array.length-1;
//中间数据下标
int middleindex=(minindex+maxindex)/2;
//查找轮数不确定,因此不宜使用for循环
while (true) {
if (array[middleindex]>num) {
maxindex=middleindex-1;
}
else if (array[middleindex]<num) {
minindex=middleindex+1;
}
else {
//找到数据
break;
}
if (minindex>maxindex) {
middleindex=-1;
break;
}
//边界发生变化,需要更新中间下标
middleindex=(minindex+maxindex)/2;
}
二分查找的效率高(log n),遍历整个数组的方式要遍历n次
数组经典算法题:(双指针)
public static void moveZeroTotheend(int[] array) {
//定义两个下标的索引
int index1=0;
int index2=0;
//遇到0指针二右移,指针1不动,不为0指针二与指针一均移动
while (index2<array.length) {//直到指针2到数组的最后一个位置
if (array[index2]!=0) {
array[index1]=array[index2];//放到指针1位置,保证将0覆盖
index1++;
index2++;
}
else {
//此时该索引位置元素为0
index2++;
}
}
for (int i = index1; i < array.length; i++) {//将指针1后的位置用0补全
array[i]=0;
}
}
数组动态扩容(详见集合)
多维数组
int[][]array=new int[2][];//实例化时必须指定外层数组的长度
int[][]array=new int[2][3];//固定内层数组的长度
array[0]=new int[3];