image.png

3.1 数组的概述

3.1.1 定义

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

3.1.2 常见概念

  • 数组 名
  • 下标 或索引
  • 元素
  • 数组的长度

    3.1.3 其他要点

  • 数组本身是 引用数据类型 (还有类和接口)

  • 而数组中的元素可以是 任何数据类型 包括基本数据类型和引用数据类型 。
  • 创建数组对象会在内存中开辟一整块 连续的空间 而数组名中引用的是这块连续空间的首地址 。
  • 数组 的 长度一旦确定 就不能修改 。
  • 我们可以直接通过下标 或索引 的方式调用指定位置的元素 速度很快 。
  • 数组的分类:

按照维度:一维数组 、 二维数组 、 三维数组 、
按照元素的数据类型分:基本数据类型元素的数组 、 引用数据类型元素的数组 即对象数组

3.2 一维数组的使用

3.2.1 声明

  • 一维数组的 声明方式

    1. type var [] type[] var<br />例如:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1620698065571-38f0480e-fcbc-4186-9d81-524b4cfce721.png#clientId=u12236051-4da7-4&from=paste&height=80&id=u3d4a3309&margin=%5Bobject%20Object%5D&name=image.png&originHeight=159&originWidth=362&originalType=binary&size=10616&status=done&style=none&taskId=u8b9a8060-18a9-4c34-ae60-726e98beadc&width=181)
  • Java 语言中声明数组时不能指定其长度(数组中元素的数) 例如: int a[5 ]; //非法

    3.2.2 初始化

  • 动态初始化 数组声明且为数组元素分配空间 与 赋值的操作 分开进行

image.png

  • 静态初始化 在定义数组的同时就为数组元素分配空间并赋值。

image.png

3.2.3 数组元素的引用

  • 定义并用运算符 new 为之分配空间后,才可以引用数组中的每个元素;
  • 数组元素的引用方式:数组名 [ 数组元素下标 ]
    • 数组元素下标可以是整型常量或整型表达式。如 a[3] , b[ i ] , c[ i ]
    • 数组元素下标从 0 开始;长度为 n 的数组合法下标取值范围 : 0 ——>n 1 如 int a[]=new int [3]; 可引用的数组元素为 a[0] 、 a[1] 、 a[2]
  • 每个数组都有一个属性 length 指明它的长度,例如: a.length 指明数组 a 的长度 元素个数
    • 数组一旦初始化,其长度是不可变的 ```java package com.atguigu.java;

/*

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

  • 元素

  • 角标、下标、索引

  • 数组的长度:元素的个数

  • 3.数组的特点:
  • 1)数组是有序排列的
  • 2)数组属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以是引用数据类型
  • 3)创建数组对象会在内存中开辟一整块连续的空间
  • 4)数组的长度一旦确定,就不能修改。
    1. 数组的分类:
  • ① 按照维数:一维数组、二维数组、。。。
  • ② 按照数组元素的类型:基本数据类型元素的数组、引用数据类型元素的数组
    1. 一维数组的使用
  • ① 一维数组的声明和初始化
  • ② 如何调用数组的指定位置的元素
  • ③ 如何获取数组的长度
  • ④ 如何遍历数组
  • ⑤ 数组元素的默认初始化值 :见ArrayTest1.java
  • ⑥ 数组的内存解析 :见ArrayTest1.java */ public class ArrayTest {

    public static void main(String[] args) {

    //1. 一维数组的声明和初始化 int num;//声明 num = 10;//初始化 int id = 1001;//声明 + 初始化

    int[] ids;//声明 //1.1 静态初始化:数组的初始化和数组元素的赋值操作同时进行 ids = new int[]{1001,1002,1003,1004}; //1.2动态初始化:数组的初始化和数组元素的赋值操作分开进行 String[] names = new String[5];

    //错误的写法: // int[] arr1 = new int[]; // int[5] arr2 = new int[5]; // int[] arr3 = new int[3]{1,2,3};

    //也是正确的写法: int[] arr4 = {1,2,3,4,5};//类型推断

    //总结:数组一旦初始化完成,其长度就确定了。

    //2.如何调用数组的指定位置的元素:通过角标的方式调用。 //数组的角标(或索引)从0开始的,到数组的长度-1结束。 names[0] = “王铭”; names[1] = “王赫”; names[2] = “张学良”; names[3] = “孙居龙”; names[4] = “王宏志”;//charAt(0) // names[5] = “周扬”;

    //3.如何获取数组的长度。 //属性:length System.out.println(names.length);//5 System.out.println(ids.length);

    //4.如何遍历数组 /System.out.println(names[0]); System.out.println(names[1]); System.out.println(names[2]); System.out.println(names[3]); System.out.println(names[4]);/

    for(int i = 0;i < names.length;i++){

       System.out.println(names[i]);
    

    }

}

}

<a name="qI7xu"></a>
### 3.2.4 数组元素的默认初始化

- 数组是引用类型,它的元素 相当于类的成员变量 ,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化。例如:

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1620698603641-f4250719-ac33-46a0-9dc0-7ada304742f2.png#clientId=u12236051-4da7-4&from=paste&height=79&id=uaa679d8e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=157&originWidth=603&originalType=binary&size=17424&status=done&style=none&taskId=u061b012e-5a22-4979-a2e6-bef74496187&width=301.5)

- 对于**基本数据类型**而言,默认初始化值各有不同
- 对于**引用数据类型**而言,默认初始化值为 null( 注意 与 0 不同!)

![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1620698642551-e9c35f67-c1e3-4968-bacf-f76f119752d3.png#clientId=u12236051-4da7-4&from=paste&height=191&id=u8c16b98e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=382&originWidth=715&originalType=binary&size=29169&status=done&style=none&taskId=u2142bd52-a195-4961-b768-81ce396ea32&width=357.5)
```java
package com.atguigu.java;
/*
 * ⑤ 数组元素的默认初始化值
 *         > 数组元素是整型:0
 *         > 数组元素是浮点型:0.0
 *         > 数组元素是char型:0或'\u0000',而非'0'
 *         > 数组元素是boolean型:false
 * 
 *         > 数组元素是引用数据类型:null
 *  
 *  ⑥ 数组的内存解析
 */
public class ArrayTest1 {

    public static void main(String[] args) {
        //5.数组元素的默认初始化值
        int[] arr = new int[4];
        for(int i = 0;i < arr.length;i++){
            System.out.println(arr[i]);
        }
        System.out.println("**********");

        short[] arr1 = new short[4];
        for(int i = 0;i < arr1.length;i++){
            System.out.println(arr1[i]);
        }
        System.out.println("**********");
        float[] arr2 = new float[5];
        for(int i = 0;i < arr2.length;i++){
            System.out.println(arr2[i]);
        }

        System.out.println("**********");
        char[] arr3 = new char[4];
        for(int i = 0;i < arr3.length;i++){
            System.out.println("----" + arr3[i] + "****");
        }

        if(arr3[0] == 0){
            System.out.println("你好!");
        }

        System.out.println("**********");
        boolean[] arr4 = new boolean[5];
        System.out.println(arr4[0]);

        System.out.println("**********");
        String[] arr5 = new String[5];
        System.out.println(arr5[0]);
        if(arr5[0] == null){
            System.out.println("北京天气不错!");
        }
    }

}

3.2.5 创建基本数据类型数组

image.png
image.png
image.png

3.2.6 一维数组的内存解析

1.内存的简化结构

image.png
image.png
image.png
image.png

3.2.7 练习题

image.png
答案是:联系方式:18xxxxxxx
image.png

package com.atguigu.exer;

import java.util.Scanner;

/*
 * 2. 从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
        成绩>=最高分-10    等级为’A’   
        成绩>=最高分-20    等级为’B’
        成绩>=最高分-30    等级为’C’   
        其余                               等级为’D’

        提示:先读入学生人数,根据人数创建int数组,存放学生成绩。

 * 
 */
public class ArrayDemo1 {
    public static void main(String[] args) {
        //1.使用Scanner,读取学生个数
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入学生人数:");
        int number = scanner.nextInt();

        //2.创建数组,存储学生成绩:动态初始化
        int[] scores = new int[number];
        //3.给数组中的元素赋值
        System.out.println("请输入" + number + "个学生成绩:");
        int maxScore = 0;
        for(int i = 0;i < scores.length;i++){
            scores[i] = scanner.nextInt();
            //4.获取数组中的元素的最大值:最高分
            if(maxScore < scores[i]){
                maxScore = scores[i];
            }
        }
//        for(int i = 0;i < scores.length;i++){
//            if(maxScore < scores[i]){
//                maxScore = scores[i];
//            }
//        }

        //5.根据每个学生成绩与最高分的差值,得到每个学生的等级,并输出等级和成绩
        char level;
        for(int i = 0;i < scores.length;i++){
            if(maxScore - scores[i] <= 10){
                level = 'A';
            }else if(maxScore - scores[i] <= 20){
                level = 'B';
            }else if(maxScore - scores[i] <= 30){
                level = 'C';
            }else{
                level = 'D';
            }

            System.out.println("student " + i + 
                    " score is " + scores[i] + ",grade is " + level);
        }

    }
}

3.3 多维数组的使用

  • Java 语言里提供了支持多维数组的语法。
  • 如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格,像右图 Excel中的表格一样。
  • 对于二维数组的理解,我们可以看成是一维数组array1 又作为另一个一维数组 array2 的元素而存在。其实, 从数组底层的运行机制来看,其实没有多维数组。

    3.3.2 二维数组的声明和初始化

    image.png
    image.png
    代码演示: ```java package com.atguigu.java; /*

    • 二维数组的使用
    • 1.理解:
    • 对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。
    • 其实,从数组底层的运行机制来看,其实没有多维数组。
      1. 二维数组的使用:
    • ① 二维数组的声明和初始化
    • ② 如何调用数组的指定位置的元素
    • ③ 如何获取数组的长度
    • ④ 如何遍历数组
    • ⑤ 数组元素的默认初始化值 :见 ArrayTest3.java
    • ⑥ 数组的内存解析 :见 ArrayTest3.java
    • */ public class ArrayTest2 { public static void main(String[] args) {

      //1.二维数组的声明和初始化
      int[] arr = new int[]{1,2,3};//一维数组
      //静态初始化
      int[][] arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}};
      //动态初始化1
      String[][] arr2 = new String[3][2];
      //动态初始化2
      String[][] arr3 = new String[3][];
      //错误的情况 
      

      // String[][] arr4 = new String[][4]; // String[4][3] arr5 = new String[][]; // int[][] arr6 = new int[4][3]{{1,2,3},{4,5},{6,7,8}};

      //也是正确的写法:
      int[] arr4[] = new int[][]{{1,2,3},{4,5,9,10},{6,7,8}};
      int[] arr5[] = {{1,2,3},{4,5},{6,7,8}};
      
      //2.如何调用数组的指定位置的元素
      System.out.println(arr1[0][1]);//2
      System.out.println(arr2[1][1]);//null
      
      arr3[1] = new String[4];
      System.out.println(arr3[1][0]);//null
      
      //3.获取数组的长度
      System.out.println(arr4.length);//3
      System.out.println(arr4[0].length);//3
      System.out.println(arr4[1].length);//4
      
      //4.如何遍历二维数组
      for(int i = 0;i < arr4.length;i++){
      
          for(int j = 0;j < arr4[i].length;j++){
              System.out.print(arr4[i][j] + "  ");
          }
          System.out.println();
      }
      

      } }


<a name="HouHW"></a>
### 3.3.3 二维数组的内存解析
![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1620702292216-f16618c0-49b9-4219-9aee-bec0027e7a94.png#clientId=u12236051-4da7-4&from=paste&height=205&id=hwKRU&margin=%5Bobject%20Object%5D&name=image.png&originHeight=409&originWidth=846&originalType=binary&size=28836&status=done&style=none&taskId=u0b89bad2-a671-4328-8411-0fe6863ca92&width=423)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1620702313993-aee881ed-443f-4bab-9ab9-1f5fdd8f4fa2.png#clientId=u12236051-4da7-4&from=paste&height=234&id=u7fbad54d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=467&originWidth=889&originalType=binary&size=46517&status=done&style=none&taskId=ua986260c-d9ea-4bc0-8ba7-4029ed1c552&width=444.5)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1620702689645-593e2c07-4972-412f-8f36-4fdf219c8965.png#clientId=u12236051-4da7-4&from=paste&height=221&id=ub821d9a9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=441&originWidth=879&originalType=binary&size=49250&status=done&style=none&taskId=ufeefa5c2-0dba-431f-93ec-68d055eee0d&width=439.5)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1620702700504-09f79fe2-0a4f-48ba-96c4-19c427c9dedf.png#clientId=u12236051-4da7-4&from=paste&height=223&id=ub50a7a7c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=445&originWidth=637&originalType=binary&size=34259&status=done&style=none&taskId=u133f7cf4-0ac9-4924-bd02-bb8609ae63e&width=318.5)![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1620702712160-1cc3acdd-0dc1-4758-a505-74f31d014224.png#clientId=u12236051-4da7-4&from=paste&height=230&id=uc2b5b129&margin=%5Bobject%20Object%5D&name=image.png&originHeight=459&originWidth=871&originalType=binary&size=52801&status=done&style=none&taskId=u57b24c26-c60d-44e6-aa11-da9d8f64d79&width=435.5)<br />代码演示
```java
package com.atguigu.java;
/*
 * 二维数组的使用:
 *     规定:二维数组分为外层数组的元素,内层数组的元素
 *         int[][] arr = new int[4][3];
 *         外层元素:arr[0],arr[1]等
 *         内层元素:arr[0][0],arr[1][2]等
 * 
 *   ⑤ 数组元素的默认初始化值 
 *   针对于初始化方式一:比如:int[][] arr = new int[4][3];
 *      外层元素的初始化值为:地址值
 *      内层元素的初始化值为:与一维数组初始化情况相同
 *      
 *   针对于初始化方式二:比如:int[][] arr = new int[4][];
 *       外层元素的初始化值为:null
 *      内层元素的初始化值为:不能调用,否则报错。
 *   
 *   ⑥ 数组的内存解析 
 * 
 */
public class ArrayTest3 {
    public static void main(String[] args) {

        int[][] arr = new int[4][3];
        System.out.println(arr[0]);//[I@15db9742 
        System.out.println(arr[0][0]);//0

//        System.out.println(arr);//[[I@6d06d69c

        System.out.println("*****************");
        float[][] arr1 = new float[4][3];
        System.out.println(arr1[0]);//地址值
        System.out.println(arr1[0][0]);//0.0

        System.out.println("*****************");

        String[][] arr2 = new String[4][2];
        System.out.println(arr2[1]);//地址值
        System.out.println(arr2[1][1]);//null

        System.out.println("*****************");
        double[][] arr3 = new double[4][];
        System.out.println(arr3[1]);//null
//        System.out.println(arr3[1][0]);//报错

    }
}

3.3.4 练习题

image.png

package com.atguigu.exer;
public class ArrayExer1 {

    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);
    }
}

image.png

image.png

package com.atguigu.exer;
/*
 * 使用二维数组打印一个 10 行杨辉三角。

【提示】
 1. 第一行有 1 个元素, 第 n 行有 n 个元素
 2. 每一行的第一个元素和最后一个元素都是 1
 3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
 * 
 */
public class YangHuiTest {

    public static void main(String[] args) {
        //1.声明并初始化二维数组
        int[][] yangHui = new int[10][];

        //2.给数组的元素赋值
        for(int i = 0;i < yangHui.length;i++){
            yangHui[i] = new int[i + 1];    
            //2.1 给首末元素赋值
            yangHui[i][0] = yangHui[i][i] = 1;
            //2.2 给每行的非首末元素赋值
            //if(i > 1){
            for(int j = 1;j < yangHui[i].length - 1;j++){
                yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];
            }
            //}
        }

        //3.遍历二维数组
        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();
        }    
    }    
}

拓展笔试题(题目见上)

class ArrayExer {
    public static void main(String[] args) {
        //方式一:
//        int[] arr = new int[6];
//        for (int i = 0; i < arr.length; i++) {// [0,1) [0,30) [1,31)
//            arr[i] = (int) (Math.random() * 30) + 1;
//
//            boolean flag = false;
//            while (true) {
//                for (int j = 0; j < i; j++) {
//                    if (arr[i] == arr[j]) {
//                        flag = true;
//                        break;
//                    }
//                }
//                if (flag) {
//                    arr[i] = (int) (Math.random() * 30) + 1;
//                    flag = false;
//                    continue;
//                }
//                break;
//            }
//        }
//
//        for (int i = 0; i < arr.length; i++) {
//            System.out.println(arr[i]);
//        }
        //方式二:
        int[] arr = new int[6];
        for (int i = 0; i < arr.length; i++) {// [0,1) [0,30) [1,31)
            arr[i] = (int) (Math.random() * 30) + 1;

                for (int j = 0; j < i; j++) {
                    if (arr[i] == arr[j]) {
                        i--;
                        break;
                    }
                }
            }

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

3.4 数组中设计到的常见算法

3.4.1 数组元素的赋值:

1.杨辉三角(见上)

2.回形数

image.png
方法一:

class RectangleTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入一个数字");
        int len = scanner.nextInt();
        int[][] arr = new int[len][len];

        int s = len * len;
        /*
         * k = 1:向右 k = 2:向下 k = 3:向左 k = 4:向上
         */
        int k = 1;
        int i = 0, j = 0;
        for (int m = 1; m <= s; m++) {
            if (k == 1) {
                if (j < len && arr[i][j] == 0) {
                    arr[i][j++] = m;
                } else {
                    k = 2;
                    i++;
                    j--;
                    m--;
                }
            } else if (k == 2) {
                if (i < len && arr[i][j] == 0) {
                    arr[i++][j] = m;
                } else {
                    k = 3;
                    i--;
                    j--;
                    m--;
                }
            } else if (k == 3) {
                if (j >= 0 && arr[i][j] == 0) {
                    arr[i][j--] = m;
                } else {
                    k = 4;
                    i--;
                    j++;
                    m--;
                }
            } else if (k == 4) {
                if (i >= 0 && arr[i][j] == 0) {
                    arr[i--][j] = m;
                } else {
                    k = 1;
                    i++;
                    j++;
                    m--;
                }
            }
        }

        // 遍历
        for (int m = 0; m < arr.length; m++) {
            for (int n = 0; n < arr[m].length; n++) {
                System.out.print(arr[m][n] + "\t");
            }
            System.out.println();
        }
    }
}

方法二:

class RectangleTest1 {

    public static void main(String[] args) {
        int n = 7;
        int[][] arr = new int[n][n];

        int count = 0; // 要显示的数据
        int maxX = n - 1; // x轴的最大下标
        int maxY = n - 1; // Y轴的最大下标
        int minX = 0; // x轴的最小下标
        int minY = 0; // Y轴的最小下标
        while (minX <= maxX) {
            for (int x = minX; x <= maxX; x++) {
                arr[minY][x] = ++count;
            }
            minY++;
            for (int y = minY; y <= maxY; y++) {
                arr[y][maxX] = ++count;
            }
            maxX--;
            for (int x = maxX; x >= minX; x--) {
                arr[maxY][x] = ++count;
            }
            maxY--;
            for (int y = maxY; y >= minY; y--) {
                arr[y][minX] = ++count;
            }
            minX++;
        }

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length; j++) {
                String space = (arr[i][j] + "").length() == 1 ? "0" : "";
                System.out.print(space + arr[i][j] + " ");
            }
            System.out.println();
        }
    }
}

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

image.png

package com.atguigu.java;
/*
 * 算法的考查:求数值型数组中元素的最大值、最小值、平均数、总和等
 * 
 * 定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,
 * 然后求出所有元素的最大值,最小值,和值,平均值,并输出出来。    
 * 要求:所有随机数都是两位数。
 * 
 * [10,99]
 * 公式:(int)(Math.random() * (99 - 10 + 1) + 10)
 * 
 */
public class ArrayTest1 {
    public static void main(String[] args) {
        int[] arr = new int[10];

        for(int i = 0;i < arr.length;i++){
            arr[i] = (int)(Math.random() * (99 - 10 + 1) + 10);
        }

        //遍历
        for(int i = 0;i < arr.length;i++){
            System.out.print(arr[i] + "\t");
        }
        System.out.println();

        //求数组元素的最大值
        int maxValue = arr[0];
        for(int i = 1;i < arr.length;i++){
            if(maxValue < arr[i]){
                maxValue = arr[i];
            }
        }
        System.out.println("最大值为:" + maxValue);

        //求数组元素的最小值
        int minValue = arr[0];
        for(int i = 1;i < arr.length;i++){
            if(minValue > arr[i]){
                minValue = arr[i];
            }
        }
        System.out.println("最小值为:" + minValue);
        //求数组元素的总和
        int sum = 0;
        for(int i = 0;i < arr.length;i++){
            sum += arr[i];
        }
        System.out.println("总和为:" + sum);
        //求数组元素的平均数
        int avgValue = sum / arr.length;
        System.out.println("平均数为:" + avgValue);
    }
}


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

1.数组的复制

image.png

package com.atguigu.exer;
/*
 * 使用简单数组
(1)创建一个名为ArrayExer2的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
(3)显示array1的内容。
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。打印出array1。
 * 
 * 思考:array1和array2是什么关系?array1和array2地址值相同,都指向了堆空间的唯一的一个数组实体。
 * 拓展:修改题目,实现array2对array1数组的复制
 */
public class ArrayExer2 {
    public static void main(String[] args) {  //alt + /
        int[] array1,array2;

        array1 = new int[]{2,3,5,7,11,13,17,19};

        //显示array1的内容
        for(int i = 0;i < array1.length;i++){
            System.out.print(array1[i] + "\t");
        }

        //赋值array2变量等于array1
        //不能称作数组的复制。
        array2 = array1;

        //数组的复制:
        //array2 = new int[array1.length];
        //for(int i = 0;i < array2.length;i++){
        //    array2[i] = array1[i];
        //}

        //修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
        for(int i = 0;i < array2.length;i++){
            if(i % 2 == 0){
                array2[i] = i;
            }

        }
        System.out.println();
        //打印出array1
        for(int i = 0;i < array1.length;i++){
            System.out.print(array1[i] + "\t");
        }
    }
}

这是赋值:

image.png
这是复制:
image.png

2.数组的反转

package com.atguigu.java;
/*
 * 算法的考查:数组的复制、反转、查找(线性查找、二分法查找)
 * 
 * 
 */
public class ArrayTest2 {

    public static void main(String[] args) {

        String[] arr = new String[]{"JJ","DD","MM","BB","GG","AA"};


        //数组的复制(区别于数组变量的赋值:arr1 = arr)
        String[] arr1 = new String[arr.length];
        for(int i = 0;i < arr1.length;i++){
            arr1[i] = arr[i];
        }

        //数组的反转
        //方法一:
//        for(int i = 0;i < arr.length / 2;i++){
//            String temp = arr[i];
//            arr[i] = arr[arr.length - i -1];
//            arr[arr.length - i -1] = temp;
//        }

        //方法二:
//        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] + "\t");
        }

        System.out.println();
        //查找(或搜索)
        //线性查找:
        String dest = "BB";
        dest = "CC";

        boolean isFlag = true;

        for(int i = 0;i < arr.length;i++){

            if(dest.equals(arr[i])){
                System.out.println("找到了指定的元素,位置为:" + i);
                isFlag = false;
                break;
            }

        }
        if(isFlag){
            System.out.println("很遗憾,没有找到的啦!");        
        }    
    }
}

3.二分查找算法

image.png

//二分法查找:(熟悉)
        //前提:所要查找的数组必须有序。
        int[] arr2 = new int[]{-98,-34,2,34,54,66,79,105,210,333};

        int dest1 = -34;
        dest1 = 35;
        int head = 0;//初始的首索引
        int end = arr2.length - 1;//初始的末索引
        boolean isFlag1 = true;
        while(head <= end){

            int middle = (head + end)/2;

            if(dest1 == arr2[middle]){
                System.out.println("找到了指定的元素,位置为:" + middle);
                isFlag1 = false;
                break;
            }else if(arr2[middle] > dest1){
                end = middle - 1;
            }else{//arr2[middle] < dest1
                head = middle + 1;
            }


        }

        if(isFlag1){
            System.out.println("很遗憾,没有找到的啦!");
        }

image.png

3.4.4 数组 元素 的 排序算法

1.基本定义

排序:假设含有 n 个记录的序列为 {R1 R2 Rn 其相应的关键字序列为{K1 K2 Kn 。将这些记录重新排序为 {Ri1, Rin 使得相应的关键字值满足条 Ki1<=Ki2<=…<=Kin, 这样的一种操作称为排序。

  • 通常来说,排序的目的是快速查找。

2.衡量排序算法的优劣:

1.时间复杂度 :分析关键字的比较次数和记录的移动次数
2.空间复杂度: 分析排序算法中需要多少辅助内存
3.稳定性: 若两个记录 A 和 B 的关键字值相等,但排序后 A 、 B 的先后次序保
持不变,则称这种排序算法是稳定的。

3.排序算法分类:内部排序 和 外部排序 。

  • 内部排序 :整个排序过程不需要借助于外部存储器(如磁盘等),所有排

序操作都在内存中完成。

  • 外部排序 :参与排序的数据非常多,数据量非常大,计算机无法把整个排

序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最
常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。

4.十大内部排序

  • 选择排序:直接选择排序、 堆排序
  • 交换排序:冒泡排序 、 快速排序
  • 插入排序:直接插入排序、 折半插入排序、 Shell 排序
  • 归并排序
  • 桶式排序
  • 基数排序

《 附录:尚硅谷 宋红康 排序算法 pdf 》
附录:尚硅谷宋红康排序算法.pdf

5.算法的5大特征

image.png

6.冒泡排序

介绍
冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元
素,如果他们的顺序错误就把他们交换过来。
排序思想
1.比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止 。

package com.atguigu.java;
/*
 * 数组的冒泡排序的实现
 * 
 */
public class BubbleSortTest {
    public static void main(String[] args) {    
        int[] arr = new int[]{43,32,76,-98,0,64,33,-21,32,99};    
        //冒泡排序
        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] + "\t");
        }
    }
}

7.快速排序

介绍
快速排序通常明显比同为O(nlogn) 的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试面试中能经常看到快排的影子。可见掌握快排的重要性 。
快速排序(Quick Sort )由图灵奖获得者 Tony Hoare 发明,被列为 20 世纪十大算法之一 ,是迄今为止所有内排序算法中速度最快的一种。冒泡排序的升级版,交换排序的一种。快速排序的时间复杂度为 O(nlog(n)) 。

排序思想
1.从数列中挑出一个元素,称为 基准 pivot
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区( partition )操作。
3.递归地( recursive )把小于基准值元素的子数列和大于基准值元素的子数列排序。
4.递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代iteration )中,它至少会把一个元素摆到它最后的位置去 。
image.pngimage.png

package com.atguigu.java;

/**
 * 快速排序
 * 通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,
 * 则分别对这两部分继续进行排序,直到整个序列有序。
 * @author shkstart
 * 2018-12-17
 */
public class QuickSort {
    private static void swap(int[] data, int i, int j) {
        int temp = data[i];
        data[i] = data[j];
        data[j] = temp;
    }

    private static void subSort(int[] data, int start, int end) {
        if (start < end) {
            int base = data[start];
            int low = start;
            int high = end + 1;
            while (true) {
                while (low < end && data[++low] - base <= 0)
                    ;
                while (high > start && data[--high] - base >= 0)
                    ;
                if (low < high) {
                    swap(data, low, high);
                } else {
                    break;
                }
            }
            swap(data, start, high);

            subSort(data, start, high - 1);//递归调用
            subSort(data, high + 1, end);
        }
    }
    public static void quickSort(int[] data){
        subSort(data,0,data.length-1);
    }


    public static void main(String[] args) {
        int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
        quickSort(data);
        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
    }
}

8.排序算法性能对比

image.png
各种内部排序方法性能比较
1.从平均时间而言 快速排序最佳。 但在最坏情况下时间性能不如堆排序和归并排序。
2.从算法简单性看 :由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,将其认为是 简单 算法。 对于 Shell 排序、堆排序、快速排序和归并排序算法,其算法比较复杂,认为是复杂排序。
3.从稳定性看 :直接插入排序、冒泡排序和归并排序时稳定的;而直接选择排序、快速排序、 Shell 排序和堆排序是不稳定排序
4.从待排序的记录数 n 的大小看:n 较小时,宜采用简单排序;而 n 较大时宜采用改进排序。

9.排序算法 的 选择

(1)若 n 较小 如 n≤50) 50),可采用 直接插入 或 直接选择排序 。
当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直
接插 入 ,应选直接选择排序 为宜 。
(2)若文件初始状态基本有序 指正序 )),则应选用 直接插 入 、 冒泡 或随机的 快速排序 为宜
(3)若 n 较大,则应采用时间复杂度为 O( nlgn 的排序方法: 快速排序 、 堆排序 或归并排序 。

3.5 Arrays工具类的使用

javautil Arrays 类即为操作数组的工具类 包含 了用来操作数组 比如排序和搜索 的各种 方法 。
image.png

package com.atguigu.java;

import java.util.Arrays;

/*
 * java.util.Arrays:操作数组的工具类,里面定义了很多操作数组的方法
 * 
 * 
 */
public class ArraysTest {
    public static void main(String[] args) {

        //1.boolean equals(int[] a,int[] b):判断两个数组是否相等。
        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

        //2.String toString(int[] a):输出数组信息。
        System.out.println(Arrays.toString(arr1));//[1,2,3,4]


        //3.void fill(int[] a,int val):将指定值填充到数组之中。
        Arrays.fill(arr1,10);
        System.out.println(Arrays.toString(arr1));[10,10,10,10]


        //4.void sort(int[] a):对数组进行排序。
        Arrays.sort(arr2);
        System.out.println(Arrays.toString(arr2));

        //5.int binarySearch(int[] a,int key)
        int[] arr3 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
        int index = Arrays.binarySearch(arr3, 210);
        if(index >= 0){
            System.out.println(index);
        }else{
            System.out.println("未找到");
        }


    }
}

image.png

3.6 数组使用中的常见异常

编译时,不报错!!
image.png

package com.atguigu.java;
/*
 * 数组中的常见异常:
 * 1. 数组角标越界的异常:ArrayIndexOutOfBoundsExcetion
 * 
 * 2. 空指针异常:NullPointerException
 * 
 */
public class ArrayExceptionTest {
    public static void main(String[] args) {

        //1. 数组角标越界的异常:ArrayIndexOutOfBoundsExcetion
        int[] arr = new int[]{1,2,3,4,5};

//        for(int i = 0;i <= arr.length;i++){
//            System.out.println(arr[i]);
//        }

//        System.out.println(arr[-2]);

//        System.out.println("hello");

        //2.2. 空指针异常:NullPointerException
        //情况一:
//        int[] arr1 = new int[]{1,2,3};
//        arr1 = null;
//        System.out.println(arr1[0]);

        //情况二:
//        int[][] arr2 = new int[4][];
//        System.out.println(arr2[0][0]);

        //情况三:
        String[] arr3 = new String[]{"AA","BB","CC"};
        arr3[0] = null;
        System.out.println(arr3[0].toString());
    }
}

每日一考 Day06

1.写出一维数组初始化的两种方式

int[] arr = new int[5];//动态初始化
String[] arr1 = new String[]{“Tom”,”Jerry”,”Jim”};//静态初始化

数组一旦初始化,其长度就是确定的。arr.length
数组长度一旦确定,就不可修改。

2.写出二维数组初始化的两种方式

int[][] arr = new int[4][3];//动态初始化1
int[][] arr1 = new int[4][];//动态初始化2

int[][] arr2 = new int[][]{{1,2,3},{4,5,6},{7,8}};//静态初始化

3.如何遍历如下的二维数组

int[] arr = new int[][]{{1,2,3},{4,5},{6,7,8}};

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();
}

4.不同类型的一维数组元素的默认初始化值各是多少

整型 : 0
浮点型:0.0
char:0
boolean :false
引用类型:null

5.一维数组的内存解析:

String[] strs = new String[5];
strs[2] = “Tom”;
strs = new String[3];
image.png

每日一考 Day07

1.使用冒泡排序,实现如下的数组从小到大排序。

int[] arr = new int[]{34,5,22,-98,6,-76,0,-3};

for(int i = 0;i < arr.length - 1;i++){
    for(int j = 0;j < arr.length -i - 1;j++){
        if(arr[j] > arr[j+1]){
            int temp =arr[i];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }    
    }
}

快排时间复杂度:O(nlogn)
冒泡时间复杂度:O(n^2)
堆排序、归并排序

2.如何反转上面的数组。请代码实现

        //数组的反转
        //方法一:
//        for(int i = 0;i < arr.length / 2;i++){
//            String temp = arr[i];
//            arr[i] = arr[arr.length - i -1];
//            arr[arr.length - i -1] = temp;
//        }

        //方法二:
//        for(int i = 0,j = arr.length - 1;i < j;i++,j--){
//            String temp = arr[i];
//            arr[i] = arr[j];
//            arr[j] = temp;
//        }

3. 复制上述数组,得到一个新的数组

vs 赋值操作
array2 = array1;

int[] arr1 = new int[arr.length];
for(;;)...

4. 使用线性查找,从上述数组中查找22是否存在。存在,返回所在位置的索引。不存在,输出提示信息。

int dest = 22;
boolean isFlag = true;
for(int i = 0;i < arr.length;i++){
    if(dest == arr[i]){
        sysout(i);
        isFlag = false;
        break;
    }
}
if(isFlag){
    sysout("未找到");
}
或
int dest = 22;
for(int i = 0;i < arr.length;i++){    
    if(dest == arr[i]){
        sysout(i);
        break;
    }
}

if(i == arr.length){
    sysout("未找到");
}

5. 数组中常见的异常有哪些?请举例说明

ArrayIndexOutOfBoundsException:数组角标越界异常:
合理范围:[0,arr.length -1]
越界:arr[-1],arr[arr.length]

NullPointerException:空指针异常
int[] arr = null;
arr[0];