数组
数组的应用
基础应用:针对数组中元素的顺序和数据值不做任何改变
案例:求和,求最值,…
中级应用:针对数组中的地址值的改变,原数组的顺序和数据值不做任何改变
案例:动态扩容,删除,插入
高级应用:针对原数组进行操作,不改变地址值,改变元素的顺序和数据值
案例:反转,排序
- 遍历数组及打印
public class ArrayDemo01 {
public static void main(String[] args) {
//声明初始化数组
int[] arr = {11,22,33,44,55};
//按照固定格式进行字符串拼接
System.out.print("数组:[");
//遍历数组
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.println(arr[i] + "]");
} else {
System.out.print(arr[i] + ", ");
}
}
}
}
- 数组的求和
public class ArrayDemo02 {
public static void main(String[] args) {
//声明初始化数组
int[] arr = {11,22,33};
//声明初始化求和变量
int sum = 0;
//遍历数组
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
//打印输出求和变量
System.out.println("sum = " + sum);
}
}
- 获取数组中所有元素的最大值
public class ArrayDemo03 {
public static void main(String[] args) {
//声明初始化数组
int[] arr = {5,15,2000,10000,100,4000};
//声明初始化临时最大值变量
int max = arr[0];
//遍历数组
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
//打印输出最大值变量
System.out.println("max = " + max);
}
}
- 评委打分
有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3.求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)
ps:赋值平均分(double)应在赋值符号右边插入*1.0(double)
public class ArrayDemo04 {
public static void main(String[] args) {
//声明初始化存储评委分数的数组
int[] arr = {5,4,6,8,9,0,1,2,7,3};
//获取十位评委的总分
int sum = arr[0];
//获取评委中的最高分
int max = arr[0];
//获取评委中的最低分
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
sum += arr[i];
if (max < arr[i]) {
max = arr[i];
}
if (min > arr[i]) {
min = arr[i];
}
}
//获取选手最后得分
double avg = (sum - max - min) * 1.0 / (arr.length - 2);
System.out.println("avg = " + avg);
}
}
- 数组的反转
针对数组中元素依次进行首尾交换位置:
- 确定待交换位置的元素的索引位置
- 待交换位置的索引移动规律
- 进行索引位置上元素交换的前提条件
- 如何进行两个元素的位置交换?
- 获取start和end之间的关系(三种表示方式)
public class ArrayDemo05 {
public static void main(String[] args) {
//声明初始化数组
int[] arr = {11,22,33,44,55,66};
//进行数组反转前的打印
System.out.print("反转前:[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.println(arr[i] + "]");
} else {
System.out.print(arr[i] + ", ");
}
}
//进行数组的反转
/*for (int start = 0 , end = arr.length - 1 ; start < end ; start++ , end--) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}*/
/*for (int i = 0; i < arr.length - 1 - i ; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}*/
for (int i = 0; i < arr.length / 2 ; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}
//进行数组反转后的打印
System.out.print("反转后:[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.println(arr[i] + "]");
} else {
System.out.print(arr[i] + ", ");
}
}
}
}
冒泡排序
原理:比较两个相邻的元素,将值大的元素交换至右端
- 内外层循环的意义:
- 外层循环表示求最大值的次数(int count=1;count<arr.length-1;count++)
- 内层循环表示求一次最大值需要比较几次(int i=0;i<arr.length-i;i++)
图解
public class ArrayDemo06 {
public static void main(String[] args) {
//声明初始化数组
int[] arr = {4,3,2,1};
//进行数组排序前的打印
System.out.print("排序前:[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.println(arr[i] + "]");
} else {
System.out.print(arr[i] + ", ");
}
}
/*
第一轮第一次比较
比较前:[4,3,2,1]
比较后:[3,4,2,1]
if (arr[0] > arr[0 + 1]) {
int temp = arr[0];
arr[0] = arr[0 + 1];
arr[0 + 1] = temp;
}
第一轮第二次比较
比较前:[3,4,2,1]
比较后:[3,2,4,1]
if (arr[1] > arr[1 + 1]) {
int temp = arr[1];
arr[1] = arr[1 + 1];
arr[1 + 1] = temp;
}
/*
第一轮第三次比较
比较前:[3,2,4,1]
比较后:[3,2,1,4]
if (arr[2] > arr[2 + 1]) {
int temp = arr[2];
arr[2] = arr[2 + 1];
arr[2 + 1] = temp;
}
*/
/*
第一轮比较
比较前:[4,3,2,1]
比较后:[3,2,1,4]
for (int i = 0; i < arr.length - 1 ; i++) {
if (arr[i] > arr[i+1]) {
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
/*
第二轮比较
比较前:[3,2,1,4]
比较后:[2,1,3,4]
for (int i = 0; i < arr.length - 2 ; i++) {
if (arr[i] > arr[i+1]) {
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
/*
第三轮比较
比较前:[2,1,3,4]
比较后:[1,2,3,4]
for (int i = 0; i < arr.length - 3 ; i++) {
if (arr[i] > arr[i+1]) {
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
*/
//外层循环:求几次最大值 内层循环:求1次最大值需要比较几次
for (int count = 1 ; count < arr.length ; count++) {
for (int i = 0 ; i < arr.length - count ; i++) {
if (arr[i] > arr[i+1]) {
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
}
//进行数组排序后的打印
System.out.print("排序后:[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.println(arr[i] + "]");
} else {
System.out.print(arr[i] + ", ");
}
}
}
}
- 获取指定元素在数组中出现的第一次索引
public class ArrayDemo07 {
public static void main(String[] args) {
//声明初始化数组
int[] arr = {2,5,7,8,10,15,18,20,22,25,28};
//声明初始化指定元素
int num = 18;
//声明初始化索引变量
int index = -1;
for (int i = 0; i < arr.length; i++) {
if (num == arr[i]) {
index = i;
System.out.println("index = " + index);
break;
}
}
if (index == -1) {
System.out.println("无法获取指定元素");
}
}
}
- 二分查找法(折半查找法)
前提条件:
容器必须是有序(数据从小到大或者从大到小)
注意:循环中中间位置索引变成两端的索引后,如何处理两端的索引值(start=mid+1;end=mid-1)
方法图解
public class ArrayDemo08 {
public static void main(String[] args) {
//声明初始化数组
int[] arr = {2,5,7,8,10,15,18,20,22,25,28};
//声明初始化指定元素
int num = 18;
//声明初始化索引变量
int index = -1;
//声明初始化待查找数据的范围索引变量
int start = 0;
int end = arr.length - 1;
//声明初始化中间变量的索引
int mid = (start + end) / 2;
//因为不清楚经历多少次循环获取到索引,选择while循环
while (start <= end) {
if (arr[mid] < num) {
start = mid + 1;
//mid = (start + end) / 2;
} else if (arr[mid] > num) {
end = mid - 1;
//mid = (start + end) / 2;
} else {
index = mid;
break;
}
mid = (start + end) / 2;
}
if (index == -1) {
System.out.println("无法获取指定元素");
} else {
System.out.println("index = " + index);
}
}
}
- 数组的动态扩容,删除,插入
动态删除图解
public class ArrayDemo09 {
public static void main(String[] args) {
//声明初始化数组
int[] arr = {11,22,33};
System.out.println("添加前:" + printArr(arr));
arr = add(arr,44);
System.out.println("添加后:" + printArr(arr));
System.out.println("============================================");
System.out.println("删除前:" + printArr(arr));
arr = remove(arr,3);
System.out.println("删除后:" + printArr(arr));
System.out.println("============================================");
System.out.println("插入前:" + printArr(arr));
arr = insert(arr,2 , 55);
System.out.println("插入后:" + printArr(arr));
}
/*
数组的动态插入
两个明确:
返回值类型: int[]
形参列表:int[] oldArr, int index , int num
*/
public static int[] insert (int[] oldArr, int index , int num) {
//考虑数组的长度不能改变,需要根据原来的数组创建长度+1的数组
int[] newArr = new int[oldArr.length + 1];
//将原数组中的数据依次复制到新数组中
for (int i = 0; i < oldArr.length; i++) {
if (i < index) {
//等位置移动
newArr[i] = oldArr[i];
} else {
//错位移动
newArr[i + 1] = oldArr[i];
}
}
//将指定元素存储到新数组中的指定索引处
newArr[index] = num;
//返回新数组
return newArr;
}
/*
数组的动态删除
两个明确:
返回值类型: int[]
形参列表: int[] oldArr , int index
*/
public static int[] remove (int[] oldArr , int index) {
//考虑数组的长度不能改变,需要根据原来的数组创建长度-1的数组
int[] newArr = new int[oldArr.length - 1];
//将原数组中的数据依次复制到新数组中
for (int i = 0; i < newArr.length; i++) {
if (i < index) {
//等位置移动
newArr[i] = oldArr[i];
} else {
//错位移动
newArr[i] = oldArr[i+1];
}
}
//返回新数组
return newArr;
}
/*
数组的动态扩容
两个明确:
返回值类型: int[]
形参列表: int[] oldArr, int num
*/
public static int[] add (int[] oldArr , int num) {
//考虑数组的长度不能改变,需要根据原来的数组创建长度+1的数组
int[] newArr = new int[oldArr.length + 1];
//将原数组中的数据依次复制到新数组中
for (int i = 0; i < oldArr.length; i++) {
newArr[i] = oldArr[i];
}
//需要将待添加元素存储到新数组最后一个位置
newArr[newArr.length - 1] = num;
//返回新数组
return newArr;
}
public static String printArr (int[] arr) {
String s = "[";
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
s += arr[i] + "]"; //s = s + arr[i] + "]";
} else {
s += arr[i] + ", ";// s = s + arr[i] + ", "
}
}
return s;
}
}
ps:在给新数组元素赋值时,注意索引 (i<?) 的范围,用newArr.length还是oldArr.length
- 合法性校验
public class ArrayDemo10 {
public static void main(String[] args) {
int[] arr = {11,22,33};
int num = getNum(arr , 10);
System.out.println("num = " + num);
}
/*
两个明确:
返回值类型: int
形参列表: int[] arr , int index
*/
public static int getNum (int[] arr, int index) {
if (arr == null) {
return 0;
}
if (index < 0 || index >= arr.length) {
System.out.println("索引非法");
return 0;
}
int num = arr[index];
return num;
}
}
二维数组
定义:就是数组中的元素数据类型还是数组结构的数组
/**
* 二维数组:
* 就是数组中的元素数据类型还是数组结构的数组
*
* 二维数组的声明
* 数据类型[][] 数组名;(推荐)
* 数据类型 数组名[][];
* 数据类型[] 数组名[];
*
* 二维数组的初始化
* 动态初始化:
* 格式1:初始化二维数组,同时也初始化里面的一维数组
* 数据类型[][] 数组名 = new 数据类型[m][n];
* m : 二维数组的长度 或者 在二维数组中存在几个一维数组
* n : 每个一维数组中含有多少个元素
* 格式2:只初始化二维数组,不初始化里面的一维数组
* 数据类型[][] 数组名 = new 数据类型[m][];
* 静态初始化:
* 格式1:标准版
* 数据类型[][] 数组名 = new 数据类型[][]{new 数据类型[]{元素1,元素2,......,元素n},new 数据类型[]{元素1,元素2,......,元素n},......,new 数据类型[]{元素1,元素2,......,元素n}};
* 格式2:半简化版
* 数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2,......,元素n},{元素1,元素2,......,元素n},......,{元素1,元素2,......,元素n}};
* 格式3:简化版
* 数据类型[][] 数组名 = {{元素1,元素2,......,元素n},{元素1,元素2,......,元素n},......,{元素1,元素2,......,元素n}};
*/
public class ArrayDemo11 {
public static void main(String[] args) {
//数据类型[][] 数组名;
int[][] arr01;
//数据类型 数组名[][];
int arr02[][];
//数据类型[] 数组名[];
int[] arr03[];
//数据类型[][] 数组名 = new 数据类型[m][n];
int[][] arr04 = new int[3][2]; // {{0,0},{0,0},{0,0}}
System.out.println(arr04);
System.out.println(arr04[0]);
System.out.println(arr04[0][0]);
System.out.println(arr04[0][1]);
System.out.println(arr04[1]);
System.out.println(arr04[2]);
//数据类型[][] 数组名 = new 数据类型[m][];
int[][] arr05 = new int[3][];
System.out.println(arr05);
System.out.println(arr05[0]);
System.out.println(arr05[1]);
System.out.println(arr05[2]);
//数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2,......,元素n},{元素1,元素2,......,元素n},......,{元素1,元素2,......,元素n}};
int[][] arr06 = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
//数据类型[][] 数组名 = {{元素1,元素2,......,元素n},{元素1,元素2,......,元素n},......,{元素1,元素2,......,元素n}};
int[][] arr07 = {{1,2,3},{4,5},{6,7,8,9}};
}
}
二维数组的遍历
- 外层循环:i<arr.length
- 内层循环:j<arr[i].length
public class ArrayDemo12 {
public static void main(String[] args) {
//声明初始化二维数组
int[][] arr = {{1,2,3},{4,5},{6,7,8,9}};
System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[0][0]);
System.out.println(arr[0][1]);
System.out.println(arr[0][2]);
System.out.println(arr[1]);
System.out.println(arr[1][0]);
System.out.println(arr[1][1]);
System.out.println(arr[2]);
System.out.println(arr[2][0]);
System.out.println(arr[2][1]);
System.out.println(arr[2][2]);
System.out.println(arr[2][3]);
System.out.println("=======================");
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
}
二维数组的内存图解
二维数组初始化及方法出栈后的内存图解:若主方法结束,则0x666不指向栈了,此时0x6661,0x6662,0x6663三个指向还在,那么0x666被认定为垃圾数据,等待扫描.清理,此时三个指向没了,各自被认定为立即数据,等待清理回收.(二维数组驻留内存较长,开发中不常用)