思维导图
一、数组的概念
概念:一组连续的存储空间,存储多个相同类型的值
特点:类型相同、长度固定
二、数组的基本操作
2.1 创建数组
第一种方式
// 1 声明数组
int[] array1;
// 2 初始化数组
array1 = new int[12];
第二种方式
int[] array2 = new int[12];
第三种方式
int[] array4 = new int[]{1, 3, 1, 4};
第四中方式
int[] array3 = {5, 2, 0, 1, 3, 1, 4};
2.2 修改数组元素
array1[0] = 5;
array1[1] = 2;
array1[2] = 0;
2.3 访问数组元素
System.out.println(array1[0]);
2.3 遍历数组
常规遍历
for(int i = 0; i < array1.length; i++) {
System.out.println(array1[i]);
}
for 增强遍历
for (int value : array1) {
System.out.println(value);
}
2.4 小练习
给定一个整数数组,统计数组中所有元素的平均值
// 给定一个整数数组,统计数组中所有元素的平均值
public void averageCount() {
int[] array = {12, 25, 99, 99, 3, 15, 1, 25};
int sum = 0;
double average = 0;
for(int i = 0; i < array.length; i++) {
sum += array[i];
}
average = sum / array.length;
System.out.printf("%.2f", average);
}
给定一个整数数组,读入一个整数n,如果n在数组中存在,输出下标,不存在则输出-1
// 给定一个整数数组,读入一个整数n,如果n在数组中存在,输出下标,不存在则输出-1
public void judge() {
int[] array = {5, 2, 0, 1, 3, 1, 4};
boolean exist = false;
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
for(int i = 0; i < array.length; i++) {
if (n == array[i]) {
System.out.println("存在,下标: " + i);
exist = true;
}
}
if (!exist) {
System.out.println(-1);
}
}
控制台输入5个城市名称,用数组保存,并遍历输出
// 控制台输入5个城市名称,用数组保存,并遍历输出
public void saveCity() {
String[] citys = new String[5];
Scanner scanner = new Scanner(System.in);
for(int i = 0; i < citys.length; i++) {
String input = scanner.next();
citys[i] = input;
}
for (String city : citys) {
System.out.print(city + " ");
}
}
三、数组在内存中的划分
数组属于引用类型
- 栈:栈中存放数组的引用(地址)
- 堆:堆中存放数组的内容
两个数组,在内存中的划分
将一个数组直接赋值给另一个数组时的内存图
- 数组是引用类型,直接赋值时赋值的是数组的引用(地址)
- 所以将array1的地址给array2时,它们两个在栈中存放的地址就是同一个了,指向堆中同一个位置
- 所以当修改array1或者array2的时候,它们两个的值会同时变,因为是同一个内容
int[] array1 = {1, 2, 3};
int[] array2 = new int[3];
array2 = array1;
四、数组的常用操作
4.1 数组的复制
第一种方法:循环
public void arrayCopy1() {
int[] array1 = {5, 2, 0};
int[] array2 = new int[array1.length];
for(int i = 0; i < array1.length; i++) {
array2[i] = array1[i];
}
for (int value : array2) {
System.out.print(value + " ");
}
}
第二种方法:clone
public void arrayCopy2() {
int[] array1 = {5, 2, 0};
int[] array2;
array2 = array1.clone();
for (int value : array2) {
System.out.print(value + " ");
}
}
第三种方法:Arrays.copyOf()
public void arrayCopy3() {
int[] array1 = {5, 2, 0};
int[] array2;
// 第一个参数:要复制的数组
// 第二个参数:新数组的大小(如果新长度 > 原数组长度,则用0填充)
array2 = Arrays.copyOf(array1, 5);
for (int value : array2) {
System.out.print(value + " "); // 结果: 5 2 0 0 0
}
}
第四种方法:Arrays.copyOfRange()
public void arrayCopy4() {
int[] oldArray = {5, 2, 0, 1, 3, 1, 4};
int[] newArray;
// 复制[0, 5)的数组元素 到新数组中
// 如果复制长度 < 原数组长度,则就截取部分
// 如果复制长度 > 原数组长度,则用0填充
newArray = Arrays.copyOfRange(oldArray, 0, 5);
for (int value : newArray) {
System.out.print(value + " ");
}
}
第五种方法:System.arraycopy()
public void arrayCopy5() {
int[] oldArray = {5, 2, 0, 1, 3, 1, 4};
int[] newArray = new int[oldArray.length];
// 参数: (原数组 原数组起始下标 新数组 新数组起始下标 复制长度)
// 也就是从原数组的0位置开始复制,复制到新数组从0开始的位置
System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
for (int value : newArray) {
System.out.print(value + " ");
}
}
4.1 数组的扩容
思路:
- 创建一个大于原数组的新数组
- 将原数组的元素复制到新数组中
就是将原数组中的元素,放到了一个更大的地方,就实现了扩容
/*
数组扩容
1. 创建一个大于原数组的新数组
2. 将原数组的元素复制到新数组中
*/
public int[] arrayExpand(int[] oldArray, int newLength) {
int[] newArray = new int[newLength];
if (newLength < oldArray.length) {
System.out.println("扩容后的数组长度不能小于原数组长度");
} else {
// 将原数组的元素复制到新数组中
newArray = Arrays.copyOf(oldArray, newLength);
}
return newArray;
}
方法测试
int[] oldArray = {5, 2, 0, 1, 3, 1, 4};
int[] newArray = arrayTest.arrayExpand(oldArray, 10);
结果
5 2 0 1 3 1 4 0 0 0
4.3 数组作为参数
参数传递时(数组是引用类型)
- 如果传递的是基本数据类型,则传递的是值
- 如果传递的是引用数据类型,则传递的是引用
public static void printArray(int[] array) {
for (int value : array) {
System.out.print(value + " ");
}
}
因为数组是引用类型,传递的是引用
- 当在其它地方修改数组时,两者的数据都会变
- 因为实际上修改的那个数组和此数组指向的内存空间是一个地方,所以修改一个,另一个也会变
可变参数
- 只能有一个
- 必须在最后
public static void printArray(int... array) {
for (int value : array) {
System.out.print(value + " ");
}
}
// 调用
printArray(12, 25, 99, 99);
printArray(newArray);
五、数组的排序
5.1 冒泡排序
// 冒泡排序
public int[] bubbleSort(int[] array) {
for(int i = 0; i < array.length; 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;
}
}
}
return array;
}
5.2 选择排序
// 选择排序
public int[] selectSort(int[] array) {
for(int i = 0; i < array.length; i++) {
int minIndex = i;
for(int j = i + 1; j < array.length; j++) {
if (array[minIndex] > array[j]) {
minIndex = j;
}
}
if (minIndex != i) {
int temp = array[i];
array[i] = array[minIndex];
array[minIndex] = temp;
}
}
return array;
}
5.3 插入排序
第一种方式
// 插入排序
public int[] insertSort(int[] array) {
for(int i = 0; i < array.length; i++) {
for(int j = i; j > 0; j--) {
if (array[j] < array[j - 1]) {
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
return array;
}
第二种方式
// 插入排序
public int[] insertSort2(int[] array) {
for(int i = 0; i < array.length; i++) {
int temp = array[i];
int j = i;
while (j > 0 && temp < array[j - 1]) {
array[j] = array[j - 1];
j--;
}
if (i !=j) {
array[j] = temp;
}
}
return array;
}
5.4 希尔排序
// 希尔排序
public int[] shellSort(int[] array) {
int gap = array.length;
while (true) {
gap /= 2;
for(int i = 0; i < gap; i++) {
// 插入排序
for(int j = i + gap; j < array.length; j += gap) {
int temp = array[j]; // temp是取出的要比较的值
int pos = j; // pos是向前移的指针
// 向前找,如果找到更大的元素,则向后移
while (pos > 0 && array[pos - gap] > temp) {
array[pos] = array[pos - gap];
pos -= gap; // pos指针向前移 步长gap
}
// 结束后,将temp交换到这里
array[pos] = temp;
}
}
if (gap == 1) {
break;
}
}
return array;
}
5.5 快速排序
// 快速排序
public void quickSort(int[] array, int low, int high) {
if (low >= high) {
return;
}
int pivot = array[low];
int left = low;
int right = high;
while (low < high) {
// 在右面找到第一个小于基准的数
// 也就是大于基准时,high指针就左移
while (low < high && pivot <= array[high]) {
high--;
}
int temp = array[high];
array[high] = array[low];
array[low] = temp;
// 在左面找到第一个大于基准的数
// 也就是小于基准时,low指针就右移
while (low < high && pivot >= array[low]) {
low++;
}
temp = array[high];
array[high] = array[low];
array[low] = temp;
}
quickSort(array, left, low - 1);
quickSort(array, low + 1, right);
}
六、多维数组
6.1 二维数组
// 二维数组
public void ArrayTwoTest() {
// 创建二维数组
int[][] array = new int[5][5];
// 先声明,再分配空间
int[][] array1;
array1 = new int[3][3];
// 创建二维数组并赋值
int[][] array2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
// 访问二维数组
System.out.println(array[0][1]);
// 二维数组赋值
array[2][2] = 12;
array[1][3] = 25;
// 二维数组的遍历
for(int i = 0; i < array.length; i++) {
for(int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
6.2 小练习
// 杨辉三角形
public void yanghui() {
int[][] array = new int[12][];
for(int i = 0; i < array.length; i++) {
array[i] = new int[i + 1];
// 填充空格
for(int k = 0; k < array.length - i - 1; k++) {
System.out.print(" ");
}
for(int j = 0; j < array[i].length; j++) {
if (j == 0 || i == j) {
array[i][j] = 1;
} else {
array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
}
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
七、查找算法
7.1 二分法查找
// 二分查找
public int binarySearch(int[] array, int target) {
int low = 0;
int high = array.length - 1;
int mid = (low + high) / 2;
while (low < high) {
if (array[mid] == target) {
return mid;
} else if (target > array[mid]) {
low = mid + 1;
} else if (target < array[mid]) {
high = mid - 1;
}
if (low == high) {
return -1;
}
mid = (low +high) / 2;
}
return -1;
}
注意:二分法查找只能对有序序列进行查找