数组
概述
数组是相同数据类型的多个数据的容器。
这些元素按线性顺序排列。所谓线性顺序是指除第一个元素外,每一个元素都有唯一的前驱元素;除最后一个元素外,每一个元素都有唯一的后继元素。(“简单理解就是:一个跟一个顺序排列”)。
创建格式
常见创建格式:
1. 数组类型[] 数组名称 = {元素1,元素2,元素3,...};
例:int[] arr1 = {1,2,3,4,5};
2. 数组类型[] 数组名称 = new 数组类型[长度];
例:int[] arr2 = new int[5]; // 数组创建时有默认值,int:0
不常见创建格式:
3. 数组类型[] 数组名称;
这种方式只创建了数组引用名, 并未在内存创建数组空间。
后续给数值赋值时只能通过`new 数组类型[]{元素1,元素2,元素3,...}`进行赋值。
4. 数组类型[] 数组名称 = new 数组类型[]{元素1,元素2,元素3,...};
int[] arr1 = {1,2,3,4,5};
for(int i=0;i<arr1.length;i++) {
System.out.println(arr1[i]);
}
int[] arr2 = new int[5]; // 数组创建时有默认值,int:0
for(int i=0;i<arr2.length;i++) {
System.out.println(arr2[i]);
}
常见问题
数组下标越界异常 ArrayIndexOutOfBoundsException
(访问了不存在的下标)
空指针异常 NullPointerException
int[] arr1 = null;
System.out.println(arr1[1]);
常用数组算法
查找最大值最小值
// 查找最大值和最小值
int[] arr = { 1, 2, 3, 4, 5 };
int max = arr[0];
int min = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
}
System.out.println("max="+max);
System.out.println("min="+min);
冒泡排序
原理:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的 数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
名字由来:
是因为最小(或最大)的元素会经由交换慢慢“浮”到数列的顶端(降序或升序),
就如同水中的气泡最终会上浮到 顶端一样,故名“冒泡排序”。
升序排列的口诀:
N个数字来排队
两两相比小靠前,
外层 循环length-1
内层循环length-i-1
降序排序的口诀:
N个数字来排队
两两相比大靠前,
外层 循环length-1
内层循环length-i-1
// 冒泡排序
// 从第一个元素开始,和右边的数进行比较,大的换到右边,一直把最大的数换到数组的末尾,即最大的数就是数组中的最后一个。
// 重复上述操作(arr.length - 1)次,
int[] arr = { 2,1,7,32,89,55,44,33,22 };
int temp;
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-i-1; j++) {
if (arr[j] > arr[j+1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for (int i = 0; i < arr.length-1; i++) {
System.out.println(arr[i]);
}
二分查找
> 概述
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,二分查找要求数组数据必须采用顺序存储结构有序排列。
> 原理:
首先,假设数组中元素是按升序排列,将数组中间位置的数据与查找数据比较,如果两者相等,则查找成功;否则利用 中间位置记录将数组分成前、后两个子数组,如果中间位置数据大于查找数据,则进一步查找前子数组,否则进一步查 找后子数组。
重复以上过程,直到找到满足条件的数据,则表示查找成功, 直到子数组不存在为止,表示查找不成功。
实现步骤:
需要以下变量:
1. 最小下标
2. 最大下标
3. 中间下标 = (最小下标+最大下标)/2
当 要找的数 比 中间下标指示的数 大 时,最小下标=中间下标+1
当 要找的数 比 中间下标指示的数 小 时,最大下标=中间下标-1
中间下标 = (最小下标+最大下标)/2
重复以上过程,当 要找的数 等于 中间下标指示的数时,找到了!
当 最小下标>最大下标 时,说明 要找的数 不在数组中。
// 二分查找
int[] arr = {10,20,30,40,50,60,70,100};
int num = 10; // 查找10在数组中的位置
// 最小下标
int minIndex = 0;
// 最大下标
int maxIndex = arr.length - 1;
// 中间下标
int middleIndex = (minIndex+maxIndex)/2;
while(true) {
if(num > arr[middleIndex]) {
minIndex = middleIndex+1;
middleIndex = (minIndex+maxIndex)/2;
}else if(num < arr[middleIndex]) {
maxIndex = middleIndex-1;
middleIndex = (minIndex+maxIndex)/2;
}else { // num = arr[middleIndex] 找到了!
break;
}
if(minIndex > maxIndex) {
middleIndex = -1; // 没找到
break;
}
}
System.out.println(num+"数组中的位置是:"+middleIndex);
把0移到最后
/**
* 5、移动零 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
* 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0]
* */
public static void main(String[] args) {
int[] nums = {0,1,0,3,12};
int[] nums = {0,1,0,3,12,0,0,8,0,7,0};
System.out.print("0移动前的数组:");
printArr(nums);
// 思路:从后往前找0,找到0后,把0后面的所有元素往前挪
for(int i=nums.length-1-1; i>=0; i--) {
// 把0后面的所有元素往前挪
if(nums[i] == 0) {
for(int j=i; j<nums.length;j++) {
if(j == nums.length-1) {
nums[j] = 0;
}else {
nums[j] = nums[j+1];
//printArr(nums);
}
}
}
}
System.out.print("0移动后的数组:");
printArr(nums);
}
public static void printArr(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if(i == arr.length - 1) {
System.out.println();
}else{
System.out.print(",");
}
}
}
多维数组
多维数组:数组中存的也是数组。
2维数组创建格式:
数组类型[][] 数组名称 = new int[长度][]
int[][] nums = new int[10][];
nums[0] = new int[]{1,2,3};