数组

存放一组相同的数据类型

引用从0开始

初始化

  1.  数据类型 数组变量[] = new 数据类型[元素个数];
     int a[] = new int[n]; //此处的n是整数常量
     
    1
    2
    3

    2. ```java
    数据类型 数组变量名[]; //先声明但是并未初始化数据
  2.  数据类型 数组变量名[] = {e1, e2, e3, ……};
     
    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

    ==注意:==

    - 数组的元素必须跟数组变量名一致或者能转换为与数组变量名一致的数据类型,否则会报错

    - 数组创建后,如果未初始化,则数组中各个元素有默认值
    | 类型 | 默认值 |
    | ------- | ------ |
    | int | 0 |
    | short | 0 |
    | byte | 0 |
    | long | 0 |
    | float | 0.0 |
    | double | 0.0 |
    | char | \u0000 |
    | boolean | false |
    | String | null |

    - 数组下标从0开始
    - 数组下标必须在范围内引用,否则会报错
    - 数组属于引用类型,本质是对象

    ## 举例

    使用for循环找到数组{5, 4, 8, 1, 9}中的最大值

    ```java
    // Array_example1.java

    pubilc class Array_example1{
    public static void main(String[] args){
    int array[] = {5, 4, 8, 1, 9};
    int max = array[0]; //假定array[0]最大
    for (int i= 0; i < 5; i++){
    max = max > array[i] ? max : array[i];
    }

    System.out.println("max=" + max);
    }
    }

赋值

拷贝类型:

  • 值拷贝:只是简单的赋值
1
2
int a = 1;
int b = a; //当对b进行修改的时候,a中的内容并不会受影响
  • 地址拷贝:传递的是地址,地址里面存放的是数据;
1
2
int[] array1 = {1, 2, 3};
int[] array2 = array1; //此时更改array2的值,array1也会被修改

感觉这个地址拷贝有点像C/C++的指针。

数组拷贝

进行数据的拷贝,并不是说指向同一地址,而是重新开辟一个新空间进行数据的重新赋值。

1
2
3
4
5
6
7
8
9
10
11
12
// Array_copy.java

public class Array_copy{
public static void main(String[] args){
int arr1 = {1, 2, 3};
int arr2 = new int[arr1.length];

for (int i= 0; i < arr1.length; i++){
arr2[i] = arr1[i];
}
}
}

数组反转

将数组中的元素进行反转,颠倒一下顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
//ArrayReverse.java
public class ArrayReverse{
public static void main(String[] args){
int arr = {1, 2, 3};
int len = arr.length;

for (int i= 0; i < len / 2; i++){
int temp = arr[len - 1 - i];
arr[len - 1- i] = arr[i];
arr[i] = temp;
}
}
}

数组扩容

前面说过,数组是指向地址的。当我们的数组需要扩容时,我们大可以重新找一块更大的地址供数据使用。

下面是一个用户不断在数组中增添元素的例子,只有当用户输入‘n’的时候,程序才会终止运行。感觉跟C++的vector有些类似,但是在实现vector的时候需要释放内存,java的内存由JVM管理,可以自动释放内存,这一点的话确实更方便一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//ArrayAdd.java
import java.util.Scanner;
public class ArrayAdd{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int[] arr1 = {1, 2, 3};
char c;
do{
int[] temp = new int[arr1.length + 1];
for (int i = 0; i < arr1.length; i++){
temp[i] = arr1[i];
}
System.out.print("请输入你需要输入的数字:");
temp[arr1.length] = scan.nextInt();
arr1 = temp;
for (int i= 0; i < arr1.length; i++){
System.out.print(arr1[i] + "\t");
}
System.out.print("y/n ?");
c = scan.next().charAt(0);
}while (c == 'y');
}
}

动态缩减

其实可以按照上面的思路进行缩减,同一个例子,大家试着自己动手做一下。

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
//ArrayReduce.java
import java.util.Scanner;
public class ArrayReduce{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int[] arr = {1, 2, 3, 4, 5, 6};
char c;
do{
System.out.print("请输入你想要减去的元素:");
int reduce = scan.nextInt();
int j = 0;
int[] temp = new int[arr.length - 1];
for(int i = 0; i < arr.length; i++){
if(arr[i] == reduce) continue;
temp[j++] = arr[i];
}
arr =temp;
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + "\t");
}
System.out.print("y/n ?");
c = scan.next().charAt(0);
}while(c == 'y');
}
}

排序

将数据按照指定的顺序进行排列

本节只说冒泡排序,其他的排序,如:快排、大根堆、小根堆等后边的数据结构会详细总结,毕竟现在在学的是java基础

  • 内部排序
    • 将需要处理的数据加载到内部存储器进行排序,现在学的轻量的排序都可以认为是内部排序
  • 外部排序
    • 数据量比较大,内存不能直接容纳,需要借助外部存储进行排序和拼接

冒泡排序

通过对需要排序的序列从后向前依次对比数据,使得紧邻的两个元素按照规则是顺序的,经过多次扫描,最终达到所有数据都符合规则。就像水底气泡向上升一样,越到最后变得越大,也就是说,越大的数据越排在后边,所以也叫冒泡排序。

举例:对{1, 5, 4, 6, 3}进行冒泡排序的过程分析

  1. 第一次比较过程

    • 1和5比较,不需要交换
    • 5和4比较,5>4需要交换,数组为{1, 4, 5, 6, 3}
    • 5和6比较,不需要交换
    • 6和3比较,6>3需要交换,数组为{1, 4, 5, 3, 6}
  2. 第二次比较过程,此时最高位也就是最后一位已经定了,所以不要再考虑它了

    • 1和4比较,不需要变换
    • 4和5比较,不需要变换
    • 5和3比较,5>3需要变换,数组为{1, 4, 3, 5, 6}
  3. 第三次比较,同理,倒数第二个位置也不需要再考虑了

    • 1和4比较,不需要变换
    • 4和3比较,4>3需要变换,数组为{1, 3, 4, 5, 6}
  4. 第四次比较,同理,倒数第三位不需要考虑了

    • 1和3比较,不需要变换
  5. 确定数组排列后的顺序{1, 3, 4, 5, 6}

程序代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class BubleSeq{
public static void main(String[] args){
int[] arr = {1, 5, 4, 6, 3};
for (int i = 0; i < arr.length - 1; i++){
for (int j = 1; j < arr.length - i; j++){
if (arr[j - 1] > arr[j]) {
int temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
for (int i = 0; i < arr.length; i++){
System.out.print(arr[i] + "\t");
}
}
}

这只是一个基础的代码,可以优化的地方很多,根据具体问题进行具体的改进优化。

查找

就是在数组中找到我们想要的数据,也可能是该元素所在的位置

顺序查找;二分查找

顺序查找,在数组中遍历,依次进行对比,找到的话,返回其所在数组的下标

二维数组

每个数组的元素都是一个一维数组

所包括的一维数组并不一定有相同个数的元素

1
2
3
4
5
数据类型 变量名[][] = {{}, {}, ……};
数据类型 变量名[][] = new int[M][N]; // M代表一共有几个一维数组,N代表一个一维数组一共有多少个元素
// 下面是变量声明
数据类型[] 变量名[];
数据类型[][] 变量名;

作业

  1. 输出如图所示的杨辉三角,可以指定n的大小

    image-20240714145401856

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
import java.util.Scanner;

public class YangHui{
public static void main(String[] args){
System.out.print("请输入n的值:");
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();

int arr[][];
arr = new int[n][];

for (int i = 0; i < n; i++){
arr[i] = new int[i+1];
for(int j = 0; j < i + 1; j++){
if(j == 0 || j == i) {
arr[i][j] = 1;
} else {
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
}
}

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.print("\n");
}
}
}