本文最后更新于:2023年11月25日 下午
数组:可以存放多个同一类型的数据。数组也是一种数据,是引用类型。
即:数组就是一组数据。
5.1 一维数组
5.1.1 数组基础
数组可以是多个相同类型数据的组合,实现对这些数据的统一管理。
数组中的元素可以是任何数据类型。包括基本类型和引用类型,但是不能混用
数组的下标的从0开始的
数组创建后,如果没有赋值,有默认值:int(0),short(0),byte(0),long(0L),float(0.0F),double(0.0),char(000),boolean(false),String(null),Object(null)
使用数组的步骤:
- 声明数组并开辟空间
- 给数组各个元素赋值
- 使用数组
数组属于引用类型,数组型数据是对象(object)
数组的构造方法:
构造方式1:动态初始化
1 2 3
| int[] a = new int[5]; int a2[] = new int[1]; a[2] = 15;
|
构造方式2:动态初始化
1 2 3
| double[] scores; double scores[]; scores = new double[5];
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.util.Scanner; public class test {
public static void main(String[] args) { double scores[]; scores = new double[5]; Scanner myScanner = new Scanner(System.in); for(int i = 0; i < scores.length; i++){ System.out.println("请输入第" + (i+1) + "个元素的值"); scores[i] = myScanner.nextDouble(); } System.out.println("===数组的元素的清空如下:==="); for(int i = 0; i < scores.length; i++){ System.out.println("第" + (i+1) + "个元素的值= " + scores[i]); } } }
|
构造方式3:静态初始化
1
| int a[] = {2,5,8,50,60,77}
|
确切知道数组每个元素的场合可以用这个方法。
数组的使用方法:
5.1.2 数组赋值机制
基本数据类型赋值,赋值方式是值拷贝。这个值就是具体的数据,且互不影响
数组在默认情况下是引用传递,赋的值是地址,赋值方式为引用传达。
1 2 3
| int[] array1 = {0, 0, 0}; int[] array2 = array1; array2[0] = 100;
|
上述情况下,array1[0]
也会变成
100
。因为数组在 JVM 的 栈
里是一个地址,指向 堆
里的一个空间。这两个数组在上述情况下指向同一空间。
5.1.3 数组拷贝
1 2 3 4 5 6
| int[] array1 = {10, 20, 30}; int[] array2 = new int[array1.length]; for (int i = 0;i < array1.length;i++) { array2[i] = array1[i]; }
|
5.1.4 数组反转
方式 1:通过找规律反转,(临时变量)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class ArrayReverse { public static void main(String[] args) { int[] arr = {11, 22, 33, 44, 55, 66};
int temp = 0; int len = arr.length; for( int i = 0; i < len / 2; i++) { temp = arr[len - 1 - i]; arr[len - 1 - i] = arr[i]; arr[i] = temp; } System.out.println("===翻转后数组==="); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }
|
方式 2:使用逆序赋值方式,(创建一个新数组)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class test {
public static void main(String[] args) { int[] arr = {11, 22, 33, 44, 55, 66}; int[] arr2 = new int[arr.length]; for(int i = arr.length - 1, j = 0; i >= 0; i--, j++) { arr2[j] = arr[i]; } arr = arr2; System.out.println("====arr 的元素情况====="); for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t"); } } }
|
5.1.5 数组的扩容
当数组达到上限时,创建一个容量更大的新数组。将旧数组的元素依次放入,之后替换旧数组。
以下是一个扩容方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| import java.util.Scanner; public class test {
public static void main(String[] args) {
Scanner myScanner = new Scanner(System.in); int[] arr = {1,2,3}; do { int[] arrNew = new int[arr.length + 1];
for(int i = 0; i < arr.length; i++) { arrNew[i] = arr[i]; } System.out.println("请输入你要添加的元素:"); int addNum = myScanner.nextInt(); arrNew[arrNew.length - 1] = addNum; arr = arrNew; System.out.println("====arr 扩容后元素情况===="); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } System.out.println("是否继续添加 y/n"); char key = myScanner.next().charAt(0); if( key == 'n') { break; } }while(true);
System.out.println("你退出了添加..."); } }
|
5.2 排序算法
排序也叫排序算法。是将一组数据,依指定的顺序进行排列的过程
排序分为两类:
5.2.1 排序算法的时间复杂度
冒泡排序 |
O(\(n^2\)) |
O(\(n^2\)) |
稳定 |
O(1) |
n 小时较好 |
交换排序 |
O(n2) |
O(\(n^2\)) |
不稳定 |
O(1) |
n 小时较好 |
选择排序 |
O(\(n^2\)) |
O(\(n^2\)) |
不稳定 |
O(1) |
n 小时较好 |
插入排序 |
O(\(n^2\)) |
O(\(n^2\)) |
稳定 |
O(1) |
大部分已排序时较好 |
基数排序 |
O(n × k) |
O(n × k) |
稳定 |
O(n) |
k 是 “桶” 的个数 |
Shell 排序 |
O(\(nlog_2n\)) |
O(\(nlog_2^2n\)) |
不稳定 |
O(1) |
n 大时较好 |
快速排序 |
O(\(nlog_2n\)) |
O(\(n^2\)) |
不稳定 |
O(n㏒n) |
n 大时较好 |
归并排序 |
O(\(nlog_2n\)) |
O(\(nlog_2n\)) |
稳定 |
O(1) |
n 小时较好 |
堆排序 |
O(\(nlog_2n\)) |
O(\(nlog_2n\)) |
不稳定 |
O(1) |
n 大时较好 |
稳定性:排序后,那些原本相等元素的相对顺序不改变
5.2.2 冒泡排序
冒泡排序:通过对待排序序列从左向右遍历,依次比较相邻元素的值。若发现前面的值比后面的值大则交换。
如此,各元素不断接近自己的位置。值较大的元素逐渐向后移动,就像水下的气泡一样逐渐上浮。
特别地:如果在某次排序中没有发生过任何交换,则此时是已完成排序,可提前结束排序过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class test {
public static void main(String[] args) { int arr[] = {52,16,32,88,64}; int temp = 0; for( int i = 0; i < arr.length - 1; i++) { for( int j = 0; j < arr.length - 1 - i; j++) { if(arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } System.out.println("\n==第"+(i+1)+"轮=="); for(int j = 0; j < arr.length; j++) { System.out.print(arr[j] + "\t");
} } } }
|
*5.2.3 选择排序……
5.3 查找算法
在 Java 中,常用的查找有 4 种:
- 顺序查找(遍历)
- 二分查找
- 插值查找
- 斐波那契查找
5.3.1 线性查找
逐一比对,直到发现目标值
1 2 3 4 5 6
| public static int seqSearch(int[] array, int target) { for (int i = 0; i < array.length; i++) { if (array[i] == target) return i; } return -1; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import java.util.Scanner; public class test { public static void main(String[] args) {
String[] names = {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"}; Scanner myScanner = new Scanner(System.in); System.out.println("请输入名字"); String findName = myScanner.next(); int index = -1; for(int i = 0; i < names.length; i++) { if(findName.equals(names[i])) { System.out.println("恭喜你找到 " + findName); System.out.println("下标为= " + i); index = i; break; } } if(index == -1) { System.out.println("sorry ,没有找到 " + findName); }
} }
|
*5.3.2 二分查找
二分查找要求数组必须是有序数组。
递归方式二分查找:
1 2 3 4 5 6 7 8 9 10 11 12
| public static int binarySearch(int[] array, int target) { return binarySearch(array, target, 0, array.length); }
public static int binarySearch(int[] array, int target, int l, int r) { if (l >= r) return -l - 1; int p = (l + r) / 2; if (target == array[p]) return p; else if (target > array[p]) { return binarySearch(array, target, p + 1, r); } else return binarySearch(array, target, l, p - 1); }
|
非递归方式二分查找:
1 2 3 4 5 6 7 8 9 10 11
| public static int binarySearch2(int[] array, int target) { int l = 0; int r = array.length; while (r > l) { int p = (r + l) / 2; if (target == array[p]) return p; else if (target > array[p]) l = p + 1; else r = p - 1; } return -l - 1; }
|
*5.3.3 插值查找
插值查找类似于二分查找,但其不是取出中位数,而是从自适应的位置取出一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static int insertSearch(int[] array, int target) { if (target > array[array.length - 1]) return -array.length; else if (target < array[0]) return 0; int l = 0; int r = array.length; int p = 0; while (r >= l) { p = l + (target - array[l]) * (r - 1 - l) / (array[r - 1] - array[l]); if (target == array[p]) return p; else if (target > array[p]) l = p + 1; else r = p - 1; } return -p; }
|
*5.3.4 斐波那契查找
斐波那契查找原理与前两种类似,仅仅改变了中间节点的位置。其中间节点不是中位或插值,而是位于黄金分割点附近。
5.4 二维数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class test { public static void main(String[] args) {
int[][] arr = {{0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0}, {0, 2, 0, 3, 0, 0}, {0, 0, 0, 0, 0, 0} }; System.out.println("二维数组的元素个数=" + arr.length); System.out.println("第 3 个一维数组的第 4 个值=" + arr[2][3]); for(int i = 0; i < arr.length; i++) { for(int j = 0; j < arr[i].length; j++) { System.out.print(arr[i][j] + " "); } System.out.println(); } } }
|
1 2 3 4 5
| int[][] ints; int[] ints2[]; int ints3[][]; int[] x,y[];
|
二维数组实际是由多个一维数组组成的,它的各个元素的长度可以相同,也可以不同。
数组是一个对象,所以二维数组的元素存放的是一维数组的地址。
二维数组构造方法
构造方法1:动态初始化
1 2
| int[][] a = new int[3][4] int a[][] = new int[3][4]
|
构造方法2:动态初始化
1 2
| double[][] many_doubles; many_doubles = new double[3][4];
|
构造方法3:动态初始化-列数不确定
1 2 3 4 5 6 7 8 9 10 11
| int[][] arr = new int[3][];
for(int i = 0; i < arr.length; i++) { arr[i] = new int[i + 1]; for(int j = 0; j < arr[i].length; j++) { arr[i][j] = i + 1; } }
|
构造方法4:静态初始化
1
| int[][] m = {{1, 3}, {4, 10, 2}, {95}};
|
二维数组使用方法
arr.length
:该二维数组的长度
arr[0]
:该二维数组的第一个子数组
arr[0].length
:该二维数组的第一个子数组的长度
arr[1][0]
:该二维数组第二个子数组的第一个元素的值
5.5 一些题目
1.已知有个升序的数组,要求插入个元素,该数组顺序依然是升序,
比如:[10,12,45,90],添加23 后, 数组为 [10,12,23,45,90]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class test {
public static void main(String[] args) { int[] arr = {10, 12, 45, 90}; int insertNum = 23; int index = -1; for(int i = 0; i < arr.length; i++){ if(insertNum < arr[i]){ index = i; break; } } if(index == -1){ index = arr.length; }
System.out.println("应该插入的位置,arr[i]中的i为:" + index);
int[] arrNew = new int[arr.length + 1]; for(int i = 0,j = 0; i < arrNew.length; i++){ if(index != i){ arrNew[i] = arr[j]; j++; } else{ arrNew[index] = insertNum; } }
System.out.println("下面即为定位+扩容后的数组:"); for(int i = 0; i < arrNew.length; i++){ System.out.print(arrNew[i] + "\t" ); }
} }
|