我的Java学习笔记06-数组

目录

一、何为数组

二、数组的声明和创建

        1、数组的声明

        2、数组的创建

三、 内存分析及三种初始化

        1、内存分析

        2、三种初始化

四、数组的特点

五、数组的使用

        1、普通的for循环

        2、For-Each 循环

        3、数组作方法入参

        4 、数组作返回值

六、多维数组

七、Arrays类

八、稀疏数组

        1、含义

         2、适用情况

 九、数组与排序

        1、基本查找

        2、二分查找 

        3、冒泡排序

        4、选择排序

        5、直接插入排序

        6、希尔排序

        7、快速排序

        8、2路归并排序


一、何为数组

  • 数组是相同类型数据的有序集合
  • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
  • 每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问

二、数组的声明和创建

        1、数组的声明

  • 类型 [ ] 数组名  (首选方法)
  • 类型 数组名 [ ]

:声明一个 int 类型的,名称为 nums 的数组

int[] nums;    // Java的普遍写法

int nums[];    // 方便 c 或 c++ 程序员快速过渡到 Java 的写法

        2、数组的创建

  • 类型 [ ] 数组名 = new 类型[数组大小];        声明+创建
  • 数组名 = new 类型[数组大小];        在已声明的条件下进行创建

:定义大小为10的int数组

nums = new int[10];

:数组下标从0开始

:为大小为10的int数组赋值并计算总和

public class demo01 {
    public static void main(String[] args) {
        
        int [] nums = new int[10];  // 声明并创建
        
        // 数组下标从0到9,用 i 来进行遍历
        for(int i = 0; i < 10; i++){
            nums[i] = i + 1;    // 用“数组名[下标]”来访问数组元素
        }
        
        int sum = 0;    //记录总和
        
        // 遍历数组并依次相加
        for (int i = 0; i < 10; i++) {
            sum = sum + nums[i];
        }

        System.out.println(sum);
    }
}

三、 内存分析及三种初始化

        1、内存分析

                (1)堆

  • 存放 new 的对象和数组
  • 可以被所有的线程共享,不会存放别的对象引用

                (2)栈

  • 存放基本变量类型(会包含这个基本类型的具体数值)
  • 引用对象的变量(会存放这个引用在堆里面的具体地址)

                (3)方法区

  • 可以被所有的线程共享
  • 包含了所有的 class 和 static 变量

         

        2、三种初始化

                 (1)静态初始化

int [] a = {1, 2, 3, 4, 5};
Man [] man = {new Man(1,1), new Man(2,2)};

                (2)动态初始化 

int [] a = new int[2];
a[0] = 1;
a[1] = 2;

                (3)默认初始化

  • 数组属于引用类型,其元素相当于类的实例变量,故数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
  • int 型默认初始化为0,double 型默认初始化为0.0 , String 型默认初始化为null,Boolean 型默认初始化为false

四、数组的特点

  • 其长度是确定的。数组一旦被创建,其大小就不能再被改变
  • 其元素必须是相同类型,不允许出现混合类型
  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型
  • 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量
  • 数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本事是在堆中的
  • 若数组长度为 n,则其下标从 0 到 n-1

五、数组的使用

        1、普通的for循环

:计算数组中的最大值并输出

public class demo02 {
    public static void main(String[] args) {
        
        // 计算数组中的最大值并输出

        int[] num = {2,6,9,5,7};
        
        int max = num[0];   // 假设 num[0] 是最大元素
        
        // 进行“打擂台”算法
        for(int i = 1; i < 5; i++){
            if(num[i] > max)
                max = num[i];   // 更新最大值
        }

        System.out.println("最大值为:" + max);
    }
}

        2、For-Each 循环

:for-each增强循环遍历数组元素并输出

public class demo03 {
    public static void main(String[] args) {
        int [] num = {1,2,3,4,5};

        // for-each 增强循环
        for (int array : num) {
            System.out.println(array);
        }
    }
}

        3、数组作方法入参

:将打印数组作为方法使用

public class demo04 {

    public static void main(String[] args) {
        int[] nums = {1,2,3,4,5};
        arrayPrint(nums);   //调用 打印数组方法
    }

    // 定义 打印数组方法
    public static void arrayPrint(int[] num) {
        for (int i = 0; i < num.length; i++) {
            System.out.println(num[i]);
        }
    }

}

        4 、数组作返回值

:反转原数组

public class demo05 {

    public static void main(String[] args) {
        int[] num = {1,2,3,4,5};
        reverse(num);
        demo04.arrayPrint(num); //调用同一个包中的public方法
    }

    public static int[] reverse(int[] nums) {
        int n = nums.length;
        for(int i = 0, j = n - 1; i < n/2; i++, j--){
            // 经典:交换两变量值的语句体
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
        return nums;
    }
}

六、多维数组

        1、含义:多维数组可以看作是数组的数组

        2、二维数组:可以看作是 i行j列 的数组

类型 数组名 [][] = new 类型 [i][j];
类型 [][] 数组名 = { {···},{···},{···}, ··· };

:以数组为参数,打印二维数组

public class demo06 {

    public static void main(String[] args) {
        //二维数组的初始化
        int[][] num = { {1,2}, {2,3}, {3,4} };
        printArrays(num);
    }

    // 打印二维数组
    public static void printArrays(int[][] nums) {
        for (int i = 0; i < nums.length; i++) {
            for(int j = 0; j < nums[i].length; j++)
                System.out.print(nums[i][j] + "\t");
            System.out.println();
        }
    }
}

七、Arrays类

        1、java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。

        2、常用功能

  • public static int binarySearch(Object[] a, Object key)

查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作

  • public static boolean equals(long[] a, long[] a2)

比较数组:通过 equals 方法比较数组中元素值是否相等

  • public static void fill(int[] a, int val)

给数组赋相同的值:将 val 赋值给数组a 的每一个元素

  • public static void sort(Object[] a)

对数组排序:通过 sort 方法,按升序对数组进行排序

import java.util.Arrays;

public class demo07 {
    public static void main(String[] args) {
        // 1、按升序对数组进行排序
        int[] a = {5,9,87,67,34,2,1};
        Arrays.sort(a); //升序 排序
        System.out.println(Arrays.toString(a)); //打印
        //[1, 2, 5, 9, 34, 67, 87]

        
        // 2、用 val 赋值给数组中每个元素
        int[] b = {1,1,1,1,1,1};
        Arrays.fill(b,7);
        System.out.println(Arrays.toString(b));; //打印
        //[7, 7, 7, 7, 7, 7]

        
        // 3、在数组中进行二分查找 key 值
        System.out.println(Arrays.binarySearch(a,34));
        //4

        
        // 4、比较两个数组是否相等
        long[] c = {1,2,3,4,5};
        long[] d = {5,4,3};
        long[] e = {5,4,3};
        System.out.println(Arrays.equals(c,d));
        //false
        
        System.out.println(Arrays.equals(e,d));
        //true
    }
}

八、稀疏数组

        1、含义

         2、适用情况

  • 当一个数组中大部分元素为0,或者为同一值的数组时,可以用稀疏数组来保存该数组
public class demo09 {
    public static void main(String[] args) {

        // 定义数组
        int[][] array1 = new int [10][10];
        array1[2][4] = 5;
        array1[4][5] = 7;

        demo06.printArrays(array1); // 使用同一包类的public方法打印数组,具体方法在上述方法 demo06 中

        // 1、转化为稀疏数组
        int sum = 0;
        //记录非零元素个数
        for (int i = 0; i < 10; i++) {
            for(int j = 0; j < 10; j++){
                if(array1[i][j] != 0)
                    sum++;
            }
        }
        //定义稀疏数组,并初始化表头
        int[][] array2 = new int[sum+1][3];
        array2[0][0] = 10;
        array2[0][1] = 10;
        array2[0][2] = sum;

        // 初始化其他元素
        int col = 1;
        for (int i = 0; i < 10; i++) {
            for(int j = 0; j < 10; j++){
                if(array1[i][j] != 0){
                    array2[col][0] = i;
                    array2[col][1] = j;
                    array2[col][2] = array1[i][j];
                    col++;
                }
            }
        }

        System.out.println("===================");
        demo06.printArrays(array2);

        // 2、还原为原数组
        int[][] array3 = new int[ array2[0][0] ][ array2[0][1] ];
        for (int i = 1; i < sum+1; i++) {
            array3[ array2[i][0] ][ array2[i][1] ] = array2[i][2];
        }
        System.out.println("===================");
        demo06.printArrays(array3);
    }
}

 九、数组与排序

        1、基本查找

  • 遍历整个数组,逐一与目标值比较
public class BasicLookup {
    public static void main(String[] args) {
        int[] a = {10,57,8,34,67,48,66};
        System.out.println(basicLookup(a,34)); // 3
    }


    //查找算法
    private static int basicLookup(int[] array, int i) {
        for(int j = 0; j < array.length; j++)
            if(i == array[j])
                return j;
        return -1;
    }
}

        2、二分查找 

                (1)使用前提:数组元素是有序的

                (2)算法思想:每一次都查找、比较中间的元素;若目标值比中间值小,则在其左侧再进行相同的步骤,否则在右侧进行

public class TwoPointLookup {
    public static void main(String[] args) {
        int[] a = {10,20,30,40,50,60,70,80};
        System.out.println(twoPointLookup(a,70));
    }



    // 二分查找算法
    private static int twoPointLookup(int[] array, int target) {
        int low = 0;
        int high = array.length - 1;

        while (low < high){
            int mid = low + (high - low) / 2;   //定义中间值下标
            
            // 将目标值与中间值进行比较
            if ( target == array[mid] )
                return mid; // 如果相等则直接返回
            else if ( target < array[mid])
                high = mid - 1; //更改查找范围,在 原low ~ 原mid 间查找
            else
                low = mid + 1; //更改查找范围,在 原mid ~ 原high 间查找
        }

        return -1;  //数组中没有目标值时返回-1
    }
}

        3、冒泡排序

        核心

                (1)比较数组中相邻的两个元素,若前一个数比后一个数大,则交换二者位置

                (2)每一次比较,都会产生一个最大或最小的值

                (3)第一轮从0到n,第二轮从1到n-1,以此类推,直至结束

public static void pSort(int[] array){
        for(int i = 0; i < array.length-1; i++){
            for(int j = 0; j < array.length-1-i;j++){
                if(array[j+1] < array[j]){
                    int temp = array[j+1];
                    array[j+1] = array[j];
                    array[j] = temp;
                }
            }
        }
    }

        

        4、选择排序

                (1)思想:每轮选择出一个最大/最小的元素,放在每轮的起始位置

                (2)算法

  • 第一轮从0下标开始,选择出一个最大/最小的元素与array[0]交换
  • 第二轮从1下标开始,选择出一个最大/最小的元素与array[1]交换

        · · ·     · · ·

  • 第(n-1)轮从 n-1 开始,选择出一个最大/最小的元素与array[n-1]交换
// 选择排序
    private static int[] selectSort(int[] array) {

        for (int i = 0; i < array.length - 1; i++) {
            int min = i; //假设每轮开头的元素为最小值,随后进行打擂台
            for(int j = i+1; j < array.length; j++){
                if(array[min] > array[j])
                    min = j; // 更新最小值下标
            }
            // 将最小值放在每轮开头的位置
            int temp = array[i];
            array[i] = array[min];
            array[min] = temp;
        }

        return array;
    }

        5、直接插入排序

                (1)思想:将一个数插入到原数组(有序)中,时其仍然保持有序状态

                (2)算法

  • 从1下标开始(一个元素的数组总是有序的)进行循环
  • 比较后一个元素与前一个元素,若 array[j] < array[j-1] 则交换两者位置,再向前找比它更小的元素
//直接插入排序
    private static int[] insertSort(int[] array) {
        // 一个元素的排序总是有序的,故从索引1处开始插入
        for (int i = 1; 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;
    }

        6、希尔排序

                (1)思想: 以增量h为间隔比较两个元素,排成有序元素,随后减少h再进行相同的操作,直至h=1时完成对所有数的排序

                (2)算法

  • 根据克努特序列寻找最佳增量h
  • 从下标h开始,直至 array.length-1 为止,进入循环
  • 排列此元素和与之相隔 h 距离的元素(向前寻找)
  • 对 h 进行 h = (h-1) / 3 操作,减少 h 的值,再次进行以上操作,直至 h=1 为止
// 希尔算法
    private static int[] hillSort(int[] array) {
        // 根据克努特序列,寻找最佳增量
        int interval = 1;
        while(interval < array.length/3)
            interval = interval * 3 + 1;

        // 插入算法的进阶

        // 增量 h 需不断变化,直至为 1 时完成排序后结束
        for (int h = interval; h > 0; h = (h-1)/3) {
            // 从 h 索引处开始排序
            for (int i = h; i < array.length; i++) {
                // 将 h 索引值 与前面元素进行比较
                for (int j = i; j > h-1; j = j-h) {
                    if(array[j] < array[j-h]){
                        int temp = array[j];
                        array[j] = array[j-h];
                        array[j-h] = temp;
                    }
                }
            }
        }
        
        return array;
    }

        7、快速排序

                (1)思想:寻找一个基准数,将数组中大于它的数放右边,小于它的数放左边,再对左右两边进行相同的操作

                (2)算法

  • 一般地,选择 array[0] 为基准数
  • 设定 j,从后往前找小于 array[0] 的数,设定 i,从前往后找大于 array[0] 的数,交换两者位置
  • 直至 j =i 为止(总是 j 先寻找),将 array[0] 与 array[i] 交换位置
  • 对原基准数的左右两侧再进行相同的操作
//快速排序
    private static void quickSort(int[] array, int low, int high) {
        if(low > high)
            return;

        int i = low;
        int j = high;
        int base = array[low];

        while (i < j) {
            //先对右侧进行查找
            while (base <= array[j] && i < j) {
                j--;
            }
            //再对左侧进行查找
            while (base >= array[i] && i < j) {
                i++;
            }
            //交换两者的值
            if (i < j) {
                int temp = array[j];
                array[j] = array[i];
                array[i] = temp;
            }
        }

        //将基准数与二者重合处的数进行交换
        array[low] = array[i];
        array[i] = base;

        //对左右两侧再进行相同的操作
        quickSort(array,low,j-1);
        quickSort(array,j+1,high);

    }

        

        8、2路归并排序

                (1)思想:对数组进行对半拆分直至分为一个个的,再两两排序至有序状态

                (2)算法

  • 对数组进行对半拆分,再进行递归的左右两侧拆分至单个元素
  • 定义一个临时数组
  • 比较左右数组,谁小谁先放入临时数组中,最后再把剩余元素全部放入临时数组中
//2路归并排序    
    // 拆分
    private static void sort(int[] array, int startIndex, int endIndex) {
        //计算中间索引
        int centerIndex = (startIndex + endIndex) / 2;

        if(startIndex < endIndex){
            sort(array, startIndex, centerIndex);
            sort(array, centerIndex+1, endIndex);
            merge(array, startIndex, centerIndex, endIndex);
        }
    }
    // 合并
    private static void merge(int[] array, int startIndex, int centerIndex, int endIndex) {
        //定义一个临时数组
        int[] tempArray = new int [endIndex - startIndex + 1];
        //定义左边数组的起始索引
        int i = startIndex;
        //定义右边数组的起始索引
        int j = centerIndex + 1;
        //定义临时数组的起始索引
        int index = 0;

        //放入元素至临时数组
        while (i <= centerIndex && j <= endIndex) {
            //左边小时,先放左边
            if(array[i] <= array[j]){
                tempArray[index] = array[i];
                i++;
            }
            //右边小时,先放右边
            else{
                tempArray[index] = array[j];
                j++;
            }
            index++;
        }

        //处理剩余元素
        while (i <= centerIndex) {
            tempArray[index] = array[i];
            i++;
            index++;
        }
        while (j <= endIndex) {
            tempArray[index] = array[j];
            j++;
            index++;
        }
        // 将临时数组的值赋值到原数组中
        for (int k = 0; k < tempArray.length; k++)
            array[k + startIndex] = tempArray[k];
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值