数组
数组是多个
相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理
数组常见概念
- 数组名
- 元素
- 下标(索引)
- 数组的长度(固定):元素的个数
数组的特点
- 数组是有序排列的
- 数组本身是
引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型 - 创建的数组对象会在内存中开辟
一整块连续的空间,而数组名中引用的是这块连续空间的首地址 - 数组的
长度一旦确定,就不能修改 - 可以通过数组下标的方式调用指定位置的元素
一维数组的使用
一维数组的声明和初始化
调用数组的指定位置的元素
获取数组的长度
遍历数组
数组元素的默认初始化值
数组的内存解析
二维元素的使用
对于二维数组的理解,我们可以看成是一维数组arr1又作为另一个一维数组arr2的元素而存在;其实,从数组底层运行机制来看,没有多维数组。
二维数组的声明和初始化
// 1. 静态初始化
int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}, {6, 7, 8}};
// 2.1 动态初始化
String[][] arr2 = new String[3][2]; // 三行,两列
// 2.2
String[][] arr3 = new String[3][]; // 三行,未知列
// 变化
int[] arr4[] = new int[][]{{1,2}, {3, 4, 5}, {6, 7}};
int[] arr5[] = {{1, 2}, {3, 4, 5}, {6, 7}}; // 类型推断
调用二维数组指定位置的元素
Syetem.out.println(arr1[0][1]); // 2
Syetem.out.println(arr2[1][1]); // null
Syetem.out.println(arr3[1][0]); // NullPointerException
arr3[1] = new String[]{1, 2, 3};
arr3[0] = new String[2];
获取数组的长度
System.out.println(arr4.length); // 3
System.out.println(arr4[0].length); // 2
遍历数组
// 两层 for 循环
for(int i = 0; i < arr4.length; ++i) {
for(int j = 0; j < arr4[i].length; ++j) {
System.out.println(arr4[i][j]);
}
}
数组元素的默认初始化值
规定:二维数组分为 外层数组元素,内层数组元素
针对初始化方式一:int[][] arr = new int[4][3];
- 外层元素的初始化值为:地址值
- 内层元素的初始化值为:与一维数组初始化情况相同
针对初始化方式二:int[][] arr = new int[4][];
- 外层元素的初始化值为:null(引用类型)
- 内层元素的初始化值为:error
int[][] arr = new int[4][3];
System.out.println(arr); // 十六进制的地址值 [[I@adc6461
System.out.println(arr[0]); // 十六进制的地址值 [I@46ad435
System.out.println(arr[0][0]); // 0
// float
float[][] arr1 = new float[4][3];
System.out.println(arr1[1]); // [F@ac4131
System.out.println(arr1[1][1]); // 0.0
// booelan false
// String null
数组的内存解析
int[][] arr = new int[4][];
// arr 保存数组首地址
arr[1] = new int[]{1, 2, 3};
// arr[1]元素 保存内存数组首地址,并赋值
arr[2] = new int[4];
arr[2][1] = 30;
小结:
一维数组初始化的两种方式
// 1. 动态初始化
int[] arr1 = new int[5];
// 2. 静态初始化
String[] str1 = new String[]{"Tom", "Jerry", "tage"};
- 数组一旦初始化,其长度就是固定的,不可修改
二维数组初始化的两种方式
// 1.
int[][] arr2 = new int[4][5]; // 内层元素个数相同
int[][] arr3 = new int[4][]; // 内层元素个数不同时
// 2.
String[][] str2 = new String[][]{{1, 2}, {3, 4, 5}, {6. 7}};
遍历二维数组
int[][] arr = new int[][]{{1, 2, 3}, {4, 5}, {6, 7, 8}};
for(int i = 0; i < arr.length; ++i) {
for(int j = 0; j < arr[i].length; ++j) {
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
不同类型一维数组元素的默认初始化值
- 整型: 0
- 浮点型: 0.0
- 字符型: 0(ASCII)
- 布尔型: false
- 字符串型: null
- 引用类型: null
数据结构
-
数据与数据之间的逻辑关系: 集合、一对一、一对多、多对多
-
数据的存储结构:
-
线性表(一对一): 顺序表(数组)、链表、栈(先进后出)、队列(先进先出)
-
树形结构(一对多): 二叉树
-
图形结构
-
算法
-
排序算法
-
搜索算法
数组中涉及的常见算法
数组元素的赋值(杨辉三角、回形数...)(面试)
// 杨辉三角
class YTri {
public static void main(String[] args) {
int[][] arr = new int[10][];
for(int i = 0; i< arr.length; ++i) {
arr[i] = new int[i + 1];
for(int j = 0; j < arr[i].length; ++j) {
if(j == 0 || j == (arr[i].length - 1)) {
arr[i][j] = 1;
}else {
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
}
}
// 创建一个长度为6的int数组,要求元素的值在 1 - 30 之间随机,并且元素值各不相同
class ArrSJ {
public static void main(String[] args) {
int[] arr = new int[6];
for(int i = 0; i < arr.length; ++i) {
boolean isWhile = false;
do {
int temp = (int)(Math.random() * (30 - 1 + 1) + 1);
if(i == 0) {
arr[i] = temp;
}else {
isWhile = false;
for(int j = 0; j < i; ++j) {
if(arr[j] == temp) {
isWhile = true;
}
}
if(!isWhile) {
arr[i] = temp;
}
}
}while(isWhile);
System.out.print(arr[i] + "\t");
}
}
}
数值型数组中元素的最大值、最小值、平均值、总和等
// 获取随机的两位数,求最大、最小、平均、总和
// 随机两位整数 (int)(Math.random() * (b - a + 1) + a)
class SumArr {
public static void main(String[] args) {
int[] arr = new int[10];
int min = 0;
int max = 0;
int sum = 0;
for(int i = 0; i < arr.length; ++i) {
arr[i] = (int)(Math.random() * (99 - 10 + 1) + 10);
if(i == 0) {
min = arr[i];
max = arr[i];
}else {
if(min > arr[i]) {
min = arr[i];
}
if(max < arr[i]) {
max = arr[i];
}
}
sum += arr[i];
System.out.print(arr[i] + "\t");
}
System.out.println();
System.out.println("sum = " + sum + "\t max = " + max + "\t min = " + min);
}
}
数组的复制、反转、查找(线性查找、二分法查找)(面试)
// 数组复制
int[] arr1 = new[]{1, 8, 6, 4, 5};
int[] arr2 = new[arr1.length];
for(int i = 0; i < arr1.length; ++i) {
arr2[i] = arr1[i];
System.out.print(arr2[i] + "\t");
}
// 数组反转
int[] arr = new int[]{1, 5, 7, 8, 0};
for(int i = 0, j = arr.length - 1; i < j; ++i, --j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 查找
// 1. 线性
String str = String[]{"jj", "gg", "ww", "xx", "oo"};
String str1 = "jj";
int idx = -1;
for(int i = 0; i < str.length; ++i) {
// str1.equals(arr[i]) 对比字符串是否相同
if(str1.equals(arr[i])) {
System.out.println("指定位置的元素的位置为:" + i);
idx = i;
break;
}
}
if(idx == -1) {
System.out.println("很遗憾,没有找到!");
}
// 2. 二分法(折半)
// 前提:数据必须有序
class ErFen {
public static void main(String[] args) {
int[] arr = new int[]{-8, -6, -3, -2, 1, 3, 5, 8, 9};
int target = -5;
int start = 0;
int end = arr.length - 1;
while(start <= end) {
int middle = (start + end) / 2;
if(target == arr[middle]) {
System.out.println("target index = " + middle);
break;
}else if(target > arr[middle]) {
start = middle + 1;
// }else if(target < arr[middle]) {
}else {
end = middle - 1;
}
}
if(start > end) {
System.out.println("start > end : " + start + " : " + end);
}
}
}
数组元素的排序算法(面试)
排序:将数据按照关键字值进行某种顺序进行排序,这样的操作称为
排序
// 冒泡
class Bubble {
public static void main(String[] args) {
int[] arr = new int[]{-9, 5, -2, 3, 0, 8, -12, 6, 46, 88};
for(int i = 0, len = arr.length; i< len - 1; ++i) {
for(int j = 0, leng = arr.length - 1 - i; j < leng; ++j) {
if(arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for(int i = 0, len = arr.length; i < len; ++i) {
System.out.print(arr[i] + "\t");
}
System.out.println();
for(int i = 0, len = arr.length; i < len - 1; ++i) {
for(int j = arr.length - 1; j > i; --j ) {
if(arr[j] > arr[j - 1]) {
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
for(int i = 0, len = arr.length; i < len; ++i) {
System.out.print(arr[i] + "\t");
}
}
}
// 快速排序
-
衡量排序算法的优劣
-
时间复杂度:分析关键字的比较次数和记录的移动次数
-
空间复杂度:分析排序算法中需要多少辅助内容
-
稳定性:当A和B的关键字值相等,但排序后A和B的先后次序保持不变,则称这种排序算法稳定
-
-
排序算法分类:内部排序和外部排序
-
内部排序:整个排序过程不需要借助于外部存储器,所有排序操作在内存中完成
-
外部排序:参与排序的数据分厂多,数据量非常大,整个排序过程无法全部放在内存中完成,必须借助于外部存储器(如磁盘);外部排序最常见的是多路归并排序,可认为外部排序是由多次内部排序完成的
-
-
十大内部排序算法(前八种常用)
-
选择排序
- 直接选择排序、
堆排序
- 直接选择排序、
-
交换排序
- `冒泡排序`、`块速排序` -
插入排序
- 直接插入排序、折半插入排序、Shell(希尔)排序 -
归并排序 -
桶排序
-
基数排序
-
-
算法的五大特征
-
输入
-
输出
-
有穷型(可接受时间)
-
确定性
-
可行性(可用纸笔计算结果)
-
Arrays工具类的使用
import java.util.Arrays;
public class Arrs {
public static void main(String[] args) {
int[] arr1 = new int[]{1, 2, 4, 3};
int[] arr2 = new int[]{1, 2, 3, 4, 6, 5};
// analys A and B is equal
// 1. boolean equals(int[] a, int[] b)
boolean isEquals = Arrays.equals(arr1, arr2);
System.out.println("equals: arr1 == arr2 ? " + isEquals);
// print out array info
// 2. String toString(int[] a)
String arrInfo = Arrays.toString(arr1);
System.out.println("toString: " + arrInfo); // [1, 2, 4, 3]
// replace value to all array element
// 3. void fill(int[] a, int value)
Arrays.fill(arr1, 8); // [8, 8, 8, 8]
System.out.println("fill: " + Arrays.toString(arr1));
// 4. sort(int[] a)
Arrays.sort(arr2);
System.out.println("sort: " + Arrays.toString(arr2)); // [1, 2, 3, 4]
// er fen search
// int binarySearch(int[] a, int key)
int[] arr3 = new int[]{1, 3, 5, 7, 8, 10, 18};
int idx = Arrays.binarySearch(arr3, 9);
if(idx >= 0) {
System.out.println("binarySearch: " + idx);
}else {
System.out.println("binarySearch: none " + idx);
}
}
}
数组使用中的常见异常
数组角标越界的异常: ArrayIndexOutOfBoundsException
int[] arr = new int[]{1, 2, 5, 8, 9};
for(int i = 0; i <= arr.length; ++i) {
System.out.println(arr[i]);
// i = 5 error: ArrayIndexOutOfBoundsException
}
System.out.println(arr[-1]); // error: ArrayIndexOutOfBoundsException
空指针异常: NullPointerException
// 1.
int[] arr1 = new int[]{1, 2, 3};
arr1 = null;
System.out.println(arr[0]); // error: NullPointerException
// 2.
int[][] arr2 = new int[4][];
System.out.println(arr2[0]); // null
System.out.println(arr2[0][0]); // error: NullPointerException
// 3.
String arr3 = new String[]{"aa", "bb", "cc"};
arr3[0] = null;
System.out.println(arr3[0].toString()); // error: NullPointerException