当前位置:   article > 正文

Java基础学习——第三章 数组_java给定数组 a 的声明如下:double [ ]a = {75,53, 32, 12, 46,

java给定数组 a 的声明如下:double [ ]a = {75,53, 32, 12, 46, 199, 17, 54}

Java基础学习——第三章 数组

一、数组的概述

1. 数组的定义

数组(Array)是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。

2. 数组相关的概念

  1. 数组名
  2. 下标(索引)
  3. 元素
  4. 数组的长度(元素的个数)

3. 数组的特点

  1. 数组是==有序==排列的
  2. 数组属于==引用类型变量==
  3. 数组中的元素既可以是基本数据类型,也可以是引用数据类型(如String、数组……)
  4. 创建数组对象会在内存中开辟一整块==连续==的空间
  5. 数组的长度一旦确定,就不能修改(长度不可变

4. 数组的分类

  1. 按照维数:一维数组、二维数组……
  2. 按照数组元素的类型:基本数据类型元素的数组、引用数据类型元素的数组

二、一维数组

  1. 一维数组的声明和初始化
  2. 如何调用数组的指定位置(索引)的元素
  3. 如何获取数组的长度
  4. 如何遍历数组
  5. 数组元素的默认初始化值
  6. 数组的内存解析

1. 一维数组的声明和初始化

public class Day06_ArrayTest {
    public static void main(String[] args) {
        //1. 一维数组的声明和初始化
        //注意:数组一旦初始化完成,其长度就确定了
        int[] ids; //声明
        //1.1 静态初始化:数组的初始化和数组元素的赋值操作同时进行
        ids = new int[]{1001, 1002, 1003, 1004};
        //也是正确的
        // ids = {1001, 1002, 1003, 1004};
        //2.2 动态初始化:数组的初始化和数组元素的赋值操作分开进行
        //这里仅对数组进行了初始化(对数组内元素的数据类型和数组的长度初始化),但数组内的元素还没有赋值
        String[] names = new String[3];

        //注意:下述两种写法中1是正确的(静态初始化),2是错误的
        int[] array = new int[]{1001, 1002, 1003, 1004};
        //int[] array = new int[5]{1001, 1002, 1003, 1004};
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

2. 如何调用数组指定位置(索引)的元素

public class Day06_ArrayTest {
    public static void main(String[] args) {
        String[] names = new String[3];
		//2. 如何调用数组的指定位置(索引)的元素
        //数组的索引从0开始,到数组的长度-1结束
        //对数组内各元素赋值
        names[0] = "张三";
        names[1] = "李四";
        names[2] = "王五";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3. 如何获取数组的长度

public class Day06_ArrayTest {
    public static void main(String[] args) {
        String[] names = new String[3];
		//3. 如何获取数组的长度
        //属性:length
        System.out.println(names.length);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4. 如何遍历数组

public class Day06_ArrayTest {
    public static void main(String[] args) {
        String[] names = new String[3];
        names[0] = "张三";
        names[1] = "李四";
        names[2] = "王五";
		//4. 如何遍历数组
        for (int i = 0; i < names.length; i++) {
            System.out.println(names[i]);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

5. 数组元素的默认初始化值

1) 数组元素是整型(byte、short、int、long)的默认初始化值:0
public class Day06_ArrayTest {
    public static void main(String[] args) {
        //数组元素是int类型
        int[] arr1 = new int[4];
        for (int i = 0; i < arr1.length; i++) {
            System.out.println(arr1[i]);
        }
        //数组元素是short类型
        short[] arr2 = new short[4];
        for (int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
2) 数组元素是浮点型(float、double)的默认初始化值:0.0
public class Day06_ArrayTest {
    public static void main(String[] args) {
        //数组元素是double类型
        double[] arr3 = new double[4];
        for (int i = 0; i < arr1.length; i++) {
            System.out.println(arr3[i]);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
3) 数组元素是char类型的默认初始化值:0或’\u0000’(表示ASCII码为0的字符null,而不是字符’0’)
public class Day06_ArrayTest {
    public static void main(String[] args) {
        //数组元素是char类型
        char[] arr4 = new char[4];
        for (int i = 0; i < arr1.length; i++) {
            System.out.println(arr4[i]);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
4) 数组元素是boolean类型的默认初始化值:false
public class Day06_ArrayTest {
    public static void main(String[] args) {
        //数组元素是boolean类型
        boolean[] arr5 = new boolean[4];
        for (int i = 0; i < arr1.length; i++) {
            System.out.println(arr5[i]);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
5) 数组元素是引用数据类型(如String、数组等)的默认初始化值:null
public class Day06_ArrayTest {
    public static void main(String[] args) {
        //数组元素是String(引用数据类型)
        String[] arr6 = new String[4];
        for (int i = 0; i < arr1.length; i++) {
            System.out.println(arr6[i]);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

6. 数组的内存解析

Java 中的堆和栈

Java把内存划分成两种:一种是栈内存,一种是堆内存。栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。

  • 在方法(函数)体内部定义的一些局部变量,包括==基本数据类型变量(int, short, long, byte, float, double, boolean, char)数组或对象的引用数据类型变量(如array1)==都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
  • 堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或对象后,可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的==引用数据类型变量==。引用类型变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用类型变量来访问堆中的数组或对象(类似于指针)。

Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。

在这里插入图片描述
在这里插入图片描述
注意:String(字符串)实际上存放在方法区的字符串常量池中。引用类型变量的值要么是null,要么是地址

7. 一维数组例题

例1:从键盘读入学生的成绩,找出最高分,并输出学生成绩的等级

  • >=最高分-10 等级为A
  • >=最高分-20 等级为B
  • >=最高分-30 等级为C
  • 其他 等级为D
    提示:先读入学生人数,根据人数创建int数组,存放学生成绩
import java.util.Scanner;
public class Day06_ArrayExer {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入学生人数:");
        //1.获取学生人数
        int StudentNum = scan.nextInt();
        //2.根据人数创建int数组,用来存放学生成绩
        int[] scoreArr = new int[StudentNum];
        System.out.println("请输入" + StudentNum +  "个成绩:");
        //3.依次从键盘获取学生成绩并存入数组,并顺便找出最大值
        int maxsocre = scoreArr[0];
        for (int i = 0; i < scoreArr.length; i++) {
            scoreArr[i] = scan.nextInt();
            if (scoreArr[i] > maxsocre) {
                maxsocre = scoreArr[i];
            }
        }
        //4.根据每个学生成绩与最高分的差值,得到每个学生的等级,并输出等级
        for (int i = 0; i < scoreArr.length; i++) {
            char level;
            if (scoreArr[i] >= maxsocre - 10) {
                level = 'A';
            } else if (scoreArr[i] >= maxsocre - 20) {
                level = 'B';
            } else if (scoreArr[i] >= maxsocre - 30) {
                level = 'C';
            } else {
                level = 'D';
            }
            System.out.println("第" + (i + 1) + "个学生的等级为:" + level);
        }
    }
}
  • 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

三、二维数组

  • 二维数组可以理解为==一维数组array1作为另一个一维数组array2的元素==而存在。
  • 从数组底层的运行机制来看,其实并没有多维数组
  • 二维数组可以看成一个表格,行数等于外层数组的长度,列数等于内层数组的长度
  1. 二维数组的声明和初始化
  2. 如何调用数组的指定位置(索引)的元素
  3. 如何获取数组的长度
  4. 如何遍历数组
  5. 数组元素的默认初始化值
  6. 数组的内存解析

1. 二维数组的声明和初始化

public class Day06_twoDArrayTest {
    public static void main(String[] args) {
        //1. 二维数组的声明和初始化
        //1.1 静态初始化
        int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}, {6, 7, 8}}; //内层数组的长度可以不一样
        //也是正确的
        // int[][] arr1 = {{1, 2, 3}, {4, 5}, {6, 7, 8}};
        //1.2 动态初始化的方式一
        //从内存占用来解析,外层一维数组的长度为3,每个内层一维数组的长度为2
        int[][] arr2 = new int[3][2];
        //动态初始化的方式二
        int[][] arr3 = new int[3][];
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2. 如何调用数组指定位置(索引)的元素

public class Day06_twoDArrayTest {
    public static void main(String[] args) {
        int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}, {6, 7, 8}};
        int[][] arr2 = new int[3][2];
        int[][] arr3 = new int[3][];
        //2. 如何调用数组指定位置(索引)的元素
        System.out.println(arr1[0][1]);
        System.out.println(arr2[0][1]);
        //在arr3外层数组的第0个位置初始化一个长度为3的一维数组
        arr3[1] = new int[3];
        System.out.println(arr3[1][0]); //0
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3. 如何获取数组的长度

public class Day06_twoDArrayTest {
    public static void main(String[] args) {
        int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}, {6, 7, 8}};
        //3. 如何获取数组的长度
        System.out.println(arr1.length); //3 返回的是外层数组的长度
        System.out.println(arr1[1].length); //2 返回外层数组第1个位置上的内层数组的长度
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4. 如何遍历数组

public class Day06_twoDArrayTest {
    public static void main(String[] args) {
        int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}, {6, 7, 8}};
        //4. 如何遍历数组
        for (int i = 0; i < arr1.length; i++) {
            for (int j = 0; j < arr1[i].length; j++) {
                System.out.print(arr1[i][j] + " ");
            }
            System.out.println();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

5. 数组元素的默认初始化值

规定:二维数组分为外层数组的元素和内存数组的元素。如

int[][] arr = new int[4][3];
//外层元素:arr[0],arr[1]等
//内层元素:arr[0][0],arr[0][1]等
  • 1
  • 2
  • 3
  1. 针对动态初始化方式1
  • 外层元素的初始化值为:首地址值
  • 内层元素的初始化值为:与一维数组初始化情况相同
  1. 针对动态初始化方式2
  • 外层元素的初始化值为:null(因为==外层数组的元素为引用数据类型(数组),初始化值为null==)
  • 内层元素的初始化值为:不能调用,否则报错
    特别注意:外层数组元素的值只能是null或地址值,这是因为外层数组的元素为数组(引用数据类型变量),引用数据类型变量的值要么是null,要么是地址值
public class Day06_ArrayTest {
    public static void main(String[] args) {
        //5. 数组元素的默认初始化值
        //动态初始化方式1
        int[][] arr = new int[4][3];
        System.out.println(arr[0]); //外层数组第0个位置上的内层数组的地址值
        System.out.println(arr[0][0]); //0
        
		//动态初始化方式2
        int[][] arr1 = new int[4][];
        System.out.println(arr1[0]); //null
        //System.out.println(arr1[0][0]); //报错
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

6. 数组的内存解析

在这里插入图片描述

7. 二维数组例题

例1:获取arr数组中所有元素的和

public class twoDArrayExer {
    public static void main(String[] args) {
        int[][] arr = new int[][]{{3, 5, 8}, {12, 9}, {7, 0, 6, 4}};
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
             for (int j = 0; j < arr[i].length; j++) {
                 sum += arr[i][j];
             }
        }
        System.out.println(sum);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

例2:声明

int[] x,y[] //x是一维数组,y是二维数组
  • 1

以下选项允许通过编译的是:

a) x[0] = y;
b) y[0] = x; √
c) y[0][0] = x; 
d) x[0][0] = y;
e) y[0][0] = x[0]; √
f) x = y;
//提示:
1. 一维数组的正确声明方式:int[] x 或 int x[]
2. 二维数组的正确声明方式:int[][] y 或 int[] y[]int y[][]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

四、数组的常见算法

  1. 数组元素的赋值(杨辉三角、回形数)
  2. 求数值型数组中元素的最大值、最小值、平均值、总和等
  3. 数组的复制、反转、查找(线性查找、二分法查找
  4. 数组元素的==排序==算法(冒泡排序、快速排序)

1. 数组元素的赋值(杨辉三角、回形数)

练习1:使用二维数组打印一个10行的杨辉三角

  1. 第一行有一个元素,第n行有n个元素
  2. 每一行的第一个元素和最后一个元素都是1
  3. 从第三行开始,对于非第一个和最后一个的元素满足
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
  • 1
public class twoDArrayExer {
    public static void main(String[] args) {
        int[][] yanghui = new int[10][];
        for (int i = 0; i < yanghui.length; i++) {
            //第一行有一个元素,第n行有n个元素
            yanghui[i] = new int[i + 1];
            //对每一行的第一个元素和最后一个元素赋值(连续赋值)
            yanghui[i][0] = yanghui[i][i] = 1;
        }
        //从第三行开始,对非第一个和最后一个的元素赋值
        for (int i = 2; i < yanghui.length; i++) {
            for (int j = 1; j < yanghui[i].length - 1; j++) {
                yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
            }
        }
        //循环遍历输出
        for (int i = 0; i < yanghui.length; i++) {
            for (int j =0; j < yanghui[i].length; j++) {
                System.out.print(yanghui[i][j] + " ");
            }
            System.out.println();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

优化后:去掉了一个for循环嵌套

public class twoDArrayExer {
    public static void main(String[] args) {
        int[][] yanghui = new int[10][];
        for (int i = 0; i < yanghui.length; i++) {
            //第一行有一个元素,第n行有n个元素
            yanghui[i] = new int[i + 1];
            //每一行的第一个元素和最后一个元素都是1(连续赋值)
            yanghui[i][0] = yanghui[i][i] = 1;
            //对第三行开始的第一个和最后一个元素赋值(不需要加if,因为i=0或1时for循环的循环条件为false)
            for (int j = 1; j < yanghui[i].length - 1; j++) {
            	yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
            }
        }
        //循环遍历输出
        for (int i = 0; i < yanghui.length; i++) {
            for (int j =0; j < yanghui[i].length; j++) {
                System.out.print(yanghui[i][j] + " ");
            }
            System.out.println();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2. 求数值型数组中元素的最大值、最小值、平均值、总和等

练习1: 定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值、最小值、和值。要求:所有随机数都是两位数。

  • 如何获得一个整数随机数:
(int)(Math.random() * (b - a + 1) + a)
  • 1
public class Day07_ArrarCommonExer {
    public static void main(String[] args) {
        int[] arr = new int[10]; //元素默认初始化为0
        int max = 0;
        int min = 100;
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            //赋10~99的随机数
            arr[i] = (int)(Math.random() * (99 - 10 + 1) + 10);
            //最大值
            if (arr[i] > max) {
                max = arr[i];
            }
            //最小值
            if (arr[i] < min) {
                min = arr[i];
            }
            //和值
            sum += arr[i];
        }
        System.out.print("10个元素依次为:");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        System.out.println("最大值为:" + max);
        System.out.println("最小值为:" + min);
        System.out.println("和值为:" + sum);
    }
}
  • 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

3. 数组的复制、反转、查找(线性查找、二分法查找)

1) 区分:数组变量的赋值和数组的复制
  1. 创建一个名为ArraryTest的类,再main()方法中声明array1,array2和array3三个int类型的数组
  2. 使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19
  3. 打印原始array1的内容
  4. 实现array2对array1的复制
  5. 赋值array3变量等于array1,修改array3中的偶索引元素等于对应索引值
  6. 打印三个array1,array2,array3
public class Day07_ArrarSetValueExer {
    public static void main(String[] args) {
       int[] array1, array2, array3;
        array1 = new int[]{2, 3, 5, 7, 11, 13, 17, 19};
        System.out.print("原始array1:");
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + " ");
        }
        System.out.println();
        //array2对array1的复制
        array2 = new int[array1.length]; //通过new的方式给array2在堆空间中新开辟一片独立的数组空间
        for (int i = 0; i < array2.length; i++) {
            array2[i] = array1[i];
        }
        //数组变量的赋值,而非数组的复制
        array3 = array1;
        for (int i = 0; i < array3.length; i++) {
            if (i % 2 == 0) {
                array3[i] = i;
            }
        }
        System.out.print("array1:");
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + " ");
        }
        System.out.println();
        System.out.print("array2:");
        for (int i = 0; i < array2.length; i++) {
            System.out.print(array2[i] + " ");
        }
        System.out.println();
        System.out.print("array3:");
        for (int i = 0; i < array3.length; i++) {
            System.out.print(array3[i] + " ");
        }
    }
}
  • 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

总结:
7. 可以看到,在对array3中的元素进行操作后,array1中的元素也发生了变化,而array2中的元素仍然和原始array1中的元素保持一致
8. array3 = array1;代表数组变量的赋值(即引用数据类型变量的赋值),而非数组的复制。具体来说将栈中array1指向的数组的首地址值赋给了array3,此时array3也指向了堆中array1指向的数组。也就是说引用类型变量array1和array3保存的地址值是一样的,它们共同指向堆空间中同一个数组实体
9. 而array2是对array1的复制,二者在栈中保存的地址值是不同的,指向的也是堆中相互独立的两个数组实体,故对array3中元素的操作并不影响array2中的元素
在这里插入图片描述
在这里插入图片描述

2) 数组的反转

对数组 String[] arr = new String[]{“A”, “B”, “C”, “D”, “E”, “F”}; 进行反转

public class Day07_ArrarSetValueExer {
    public static void main(String[] args) {
    	String[] arr = new String[]{"AA", "BB", "CC", "DD", "EE", "FF"};
        //方法一:对应位置元素交换变量值
        for (int i = 0; i < arr.length / 2; i++) {
            String temp = arr[i];
            arr[i] = arr[arr.length - 1 - i];
            arr[arr.length - 1 - i] = temp;
        }
        for (int i = 0; i< arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();

        //方法二:用i和j分别表示首尾元素
        for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
            String temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        for (int i = 0; i< arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}
  • 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
3) 数组的查找(搜索)
a) 线性查找
  • 直接一个一个按顺序找,找到就停
public class Day07_ArrarSetValueExer {
    public static void main(String[] args) {
    	//线性查找
        boolean flag = true;
        for (int i = 0; i < arr.length; i++) {
            //if (arr[i] == dest) {
            if (dest.equals(arr[i])) {
                System.out.println("BB在arr中的索引为:" + i);
                flag = false;
                break;
            }
        }
        if (flag) {
            System.out.println("arr中不存在元素BB");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
b) 二分法查找
  • 前提:所要查找的数组必须有序
    在这里插入图片描述
public class Day07_ArrarSetValueExer {
    public static void main(String[] args) {
    	int[] arr2 = new int[]{2, 5, 7, 8, 10, 15, 18, 20, 22, 25, 28};
        int dest1 = 18;
        //用来标识是否查找到目标
        boolean isFlag = true;
        //查找范围的首索引,初始为0
        int start = 0;
        //查找范围的末索引,初始为数组最后一个元素的索引
        int end = arr2.length - 1;
        //二分法查找
        while (start <= end) { //注意这里要加等号,因为最后的查找范围可能只剩一个数,仍需要再查找一次
            //查找范围的中间元素的索引,如果查找范围内有偶数个元素,则取靠左边的中间元素
            int mid = (start + end) / 2;
            //比较所有查找的数和中间元素值的大小,从而调整查找范围
            //若所要查找的数 < 中间元素值,则说明所要查找的数在中间元素左侧,设置end为mid前一个索引
            if (dest1 < arr2[mid]) {
                end = mid - 1;
            //若所要查找的数 > 中间元素值,则说明所要查找的数在中间元素右侧,设置start为mid后一个索引
            } else if (dest1 > arr2[mid]) {
                start = mid + 1;
            //若所有查找的数 == 中间元素值,则查找结束
            } else {
                System.out.println("该元素在数组中的索引为" + mid);
                isFlag = false;
                break;
            }
        }
        if (isFlag) {
            System.out.println("数组中不存在该元素");
        }
    }
}
  • 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

4. 数组元素的排序算法(冒泡排序、快速排序)

一、十大内部排序算法:

  • 选择排序
  1. 直接选择排序
  2. 堆排序(能说出实现思想)
  • 交换排序
  1. 冒泡排序(熟练手撕)
  2. 快速排序(能说出实现思想,最好能手撕)
  • 插入排序
  1. 直接插入排序
  2. 折半插入排序
  3. Shell排序
  • 归并排序(能说出实现思想)

  • 桶式排序

  • 基数排序

**二、衡量排序算法的指标:**时间复杂度、空间复杂度、稳定性

**三、不同排序算法的时间复杂度:**重点掌握冒泡排序、快速排序
在这里插入图片描述

1) 冒泡排序
  • 排序思想(按从小到大排序):
  1. 从前往后依次比较数组中相邻元素的大小,若发现逆序则交换,使最后一个元素的排序码最大(第一轮排序)
  2. 对除最后一个元素外的所有元素重复步骤1,使次大值元素也排到最后(第二轮排序)
  3. 持续每次对越来越少的元素重复步骤1,使排序码较大的元素逐渐从前往后移,直到没有任何一对元素需要比较,排序结束 (共==arr.length - 1==轮排序)
public class Day07_BubbleSortTest {
    public static void main(String[] args) {
        int[] arr = new int[]{43, 32, 76, -98, 0, 64, 33, -21, 32, 99};
        //共 arr.length - 1 轮排序
        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]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        //打印排序后的数组
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

也可以写成

public class Day07_BubbleSortTest {
    public static void main(String[] args) {
        int[] arr = new int[]{43, 32, 76, -98, 0, 64, 33, -21, 32, 99};
        //共 arr.length - 1 轮排序
        for (int i = arr.length - 1; i > 0; i--) {
            //从前往后依次比较数组中相邻元素的大小,若发现逆序则交换
            for (int j = 0; 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; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
2) 快速排序
  • 排序思想(按从小到大排序):
  1. 从数列中挑出一个元素,称为"基准"(pivot)
  2. 分区(partition)操作:重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。
  3. 递归地(recursive)把小于基准值元素的分区和大于基准值元素的分区进行排序。
  4. 递归的最底部情形,是数列的大小是0或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代中,它至少会把一个元素摆到它最后的位置去。

五、Arrays工具类的使用

==java.util.Arrays==类即为操作数组的工具类,包含了用来操作数组的各种方法(如排序和搜索)
在这里插入图片描述

1. boolean equals(int[] a,int[] b):判断两个数组是否相等(两个数组的对应元素是否都相等)

import java.util.Arrays;
public class Day07_ArraysClassTest {
    public static void main(String[] args) {
        int[] arr1 = new int[]{1, 2, 3, 4};
        int[] arr2 = new int[]{1, 3, 2, 4};
        //判断两个数组是否相等(两个数组的对应元素是否都相等)
        boolean isEquals = Arrays.equals(arr1, arr2);
        System.out.println(isEquals); //false
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2. String toString(int[] a):输出数组信息(各元素)

import java.util.Arrays;
public class Day07_ArraysClassTest {
    public static void main(String[] args) {
        int[] arr1 = new int[]{1, 2, 3, 4};
        int[] arr2 = new int[]{1, 3, 2, 4};
        //输出数组信息(各元素)
        System.out.println(Arrays.toString(arr1)); //[1, 2, 3, 4]
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3. void fill(int[] a,int val):将指定值填充到数组中(将数组中所有元素都替换成指定值)

import java.util.Arrays;
public class Day07_ArraysClassTest {
    public static void main(String[] args) {
        int[] arr1 = new int[]{1, 2, 3, 4};
        int[] arr2 = new int[]{1, 3, 2, 4};
        //将指定值填充到数组中(将数组中所有元素都替换成指定值)
        Arrays.fill(arr1, 10);
        System.out.println(Arrays.toString(arr1)); //[10, 10, 10, 10]
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4. void sort(int[] a):对数组进行排序(从小到大)

  • 底层用的是快速排序
import java.util.Arrays;
public class Day07_ArraysClassTest {
    public static void main(String[] args) {
        int[] arr1 = new int[]{1, 2, 3, 4};
        int[] arr2 = new int[]{1, 3, 2, 4};
        //对数组进行排序(从小到大)
        Arrays.sort(arr2);
        System.out.println(Arrays.toString(arr2)); //[1, 2, 3, 4]
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5. int binarySearch(int[] a,int key):对排序后的数组进行二分法检索指定的值

  • 返回指定值在数组中的索引。若返回值是非负数,即为对应的索引;若返回值为负数,则说明未找到
import java.util.Arrays;
public class Day07_ArraysClassTest {
    public static void main(String[] args) {
        int[] arr1 = new int[]{1, 2, 3, 4};
        int[] arr2 = new int[]{1, 3, 2, 4};
        //对数组进行排序(从小到大)
        Arrays.sort(arr2);
        System.out.println(Arrays.toString(arr2)); //[1, 2, 3, 4]
        //对排序后的数组进行二分法检索指定的值
        int index = Arrays.binarySearch(arr2, 2); //返回索引值
        System.out.println(index);
        //若key在数组中不存在,则返回一个负数
        int index1 = Arrays.binarySearch(arr2, 8);
        System.out.println(index1);
        
        //通常可以写成这样的形式:
        if (index >= 0) {
            System.out.println(index);
        } else {
            System.out.println("未找到");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

六、数组的常见异常

  • 数组中的常见异常
  1. 数组超出索引的异常:ArrayIndexOutOfBoundsException
  2. 空指针异常:NullPointerException

1. 数组超出索引的异常:ArrayIndexOutOfBoundsException

public class Day07_ArrayException {
    public static void main(String[] args) {
        int[] arr = new int[]{1, 2, 3, 4, 5};
        for(int i = 0; i <= arr.length; i++) {
            System.out.println(arr[i]); //ArrayIndexOutOfBoundsException
        }

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2. 空指针异常:NullPointerException

public class Day07_ArrayException {
    public static void main(String[] args) {
        //情况1:
        int[] arr1 = new int[]{1, 2, 3};
        arr1 = null;//数组arr1是引用数据类型变量,其值要么是null,要么是地址
        System.out.println(arr1[0]); //NullPointerException
        //情况2:
        int[][] arr2 = new int[3][];
        System.out.println(arr2[0]); //null
        System.out.println(arr2[0][0]); //NullPointerException
        //情况3:
        String[] arr3 = new String[]{"AA", "BB", "CC"};
        arr3[0] = null;
        System.out.println(arr3[0].toString()); //NullPointerException
    }
}
 for(int i = 0; i <= arr.length; i++) {
            System.out.println(arr[i]); //ArrayIndexOutOfBoundsException
        }

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2. 空指针异常:NullPointerException

public class Day07_ArrayException {
    public static void main(String[] args) {
        //情况1:
        int[] arr1 = new int[]{1, 2, 3};
        arr1 = null;//数组arr1是引用数据类型变量,其值要么是null,要么是地址
        System.out.println(arr1[0]); //NullPointerException
        //情况2:
        int[][] arr2 = new int[3][];
        System.out.println(arr2[0]); //null
        System.out.println(arr2[0][0]); //NullPointerException
        //情况3:
        String[] arr3 = new String[]{"AA", "BB", "CC"};
        arr3[0] = null;
        System.out.println(arr3[0].toString()); //NullPointerException
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号