第五章:数组

本文详细介绍了Java中的数组,包括数组的定义、内存分析、基本操作如遍历和赋值,以及查找和排序算法。强调了数组作为连续存储空间的重要性,并提到了常见的数组操作错误及解决方案,如数组角标越界和空指针异常。此外,还概述了各种排序算法的应用,如选择排序、冒泡排序和高级排序算法如归并排序和快速排序。

数组的定义

之前在定义数据的时候,大部分都是用变量来存储数据。如果我们的程序中出现大量的数据怎么办?连续输入多个数字,连续输入多个坐标点,一般而言会创建多个变量存储这些数据,显得比较麻烦。这些变量基本上类型是共通的,那我们就可以用一个容器将所有的数字进行管理。类似于字符串,字符串其实就是若干个字符的容器而已,“abc”可以通过索引/角标来获取其中某一个字符。[1,2,3,4,5]类似字符串能够也可以通过索引/角标来获取其中某一个数字呢?那么这个容器我们称之为数组。

数组主要解决多变量多数据的存储问题,方便程序后期统一维护操作数据。

数组的本质就是一系列空间大小相等且地址连续的一片存储空间。

为什么空间大小是相等的呢?就是为了方便统一维护我们的数据,必须得保证数据之间的类型是一样的。(多个同类型的变量空间连在一起组成的结构叫数组)。

为什么变量空间的地址是连续的呢?就是为了方便统一操作我们的数据。见下图

 

 

 

 1.数组就是一片地址连续且空间大小一致的存储空间(但是每个空间存的还是其他数据的地址)

2.数组存在于堆内存中,但凡在堆中存储的数据都称之为 对象

但凡在堆内存中创建的对象都会有默认初始值:整数类型默认0;浮点类型默认0.0;布尔类型默认false;引用数据类型(对象)默认null。

3.数组提供角标来访问数组当中的元素

4.数组变量存的就是数组在堆内存中首元素的地址

5.数组通过角标来访问元素的具体计算方式是 所要访问数据的地址=首元素地址+角标*数据类型大小

6.数组一旦定义下来,其长度不可改变;数组中有几个地址?就看数组有几个元素空间<==>数组的长度

7.创建数组时必须明确规定大小或内容

数据类型[] 数组名=new 数据类型[长度]:创建数组只指定长度但不指定内容

数据类型[] 数组名=new 数据类型[]{1,2,3,4,5}:创建数组指定内容(指定长度)

数据类型[] 数组名={1,2,3,4,5}:创建数组指定内容(指定长度)

[]表示是一维数组;[][]表示二维数组。

数组的内存分析:

数组常见错误:ArrayIndexOutOfBoundsException 数组角标越界;NullPointerException 空指针异常

 基本数组操作:

遍历;赋值;最大值/最小值

查找操作:

线性查找;二分查找;*斐波那契查找

排序操作:

选择排序;冒泡排序;插入排序;*归并排序;*堆排序;*快速排序;计数排序;*基数排序;*桶排序。

//四种排序方法
class Test02{
    public static void main(String[] args){
        //1.选择排序O(n^2)
        selectSort();
        //2.冒泡排序O(n^2)
        bubbleSort();
        //3.插入排序O(n^2) 
        insertSort();
        //4.计数排序O(n+m)
        /*
        上述三个排序都是根据数据之间的大小关系进行比较排序的
        计数 基数 桶 都是根据数据本身的特性比较 与大小无关的排序
        这些排序只针对整数
        是一个典型的牺牲空间换时间的排序
        */
        countSort();

    }
    public static void countSort(){
        int[] arr={8,5,9,2,7,4,6,1,3,10,-3,-2,-10};
        int min=arr[0];
        int max=arr[0];
        for(int i=0;i<arr.length;i++){//O(n)
            if(arr[i]>max){
                max=arr[i];
            }
            if(arr[i]<min){
                min=arr[i];
            }
        }
        int[] nums=new int[max-min+1];
        int offset=min;
        for(int i=0;i<arr.length;i++){//O(n)
            nums[arr[i]-offset]++;
        }
        int index=0;
        for(int i=0;i<nums.length;i++){//O(m)
            if(nums[i]!=0){
                for(int j=0;j<nums[i];j++){
                    arr[index++]=i+offset;
                }
            }
        }
        show(arr);
    }
    public static void insertSort(){
        int[] arr={8,5,9,2,7,4,6,1,3};
        int e;
        int j;
        for(int i=1;i<arr.length;i++){
            e=arr[i];
            for(j=i;j>0&&arr[j-1]>e;j--){
                arr[j]=arr[j-1];
            }
            arr[j]=e;
        }
        /*
        for(int i=1;i<arr.length;i++){
            for(int j=i;j>0&&arr[j-1]>arr[j];j--){
                swap(arr,j,j-1);
            }
        }
        */
        show(arr);
    }
    public static void bubbleSort(){
        int[] arr={8,5,9,2,7,4,6,1,3};
        for(int i=0;i<arr.length-1;i++){//-1是少一轮比较
            for(int j=0;j<arr.length-1-i;j++){//-1避免重复比较和角标越界
                if(arr[j]>arr[j+1]){
                    swap(arr,j,j+1);
                }
            }
        }
        show(arr);
    }
    public static void selectSort(){
        int[] arr={8,5,9,2,7,4,6,1,3};
        for(int i=0;i<arr.length-1;i++){//-1是因为没有必要进行最后一个数字的比较
            for(int j=i+1;j<arr.length;j++){
                if(arr[i]>arr[j]){
                    swap(arr,i,j);//即用-即释放
                }
            }
        }
        show(arr);
    }
    public static void swap(int[] arr,int i,int j){
        //1.借助三方变量进行交换 
        //适用于所有的数据类型 比较通用
        /*
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
        */
        //2.借助加减法运算进行交换
        //只适用于数字相关的数据类型
        arr[i]=arr[i]+arr[j];
        arr[j]=arr[i]-arr[j];
        arr[i]=arr[i]-arr[j];

        //3.借助位运算进行交换
        //只适用于整数相关的数据类型
    }
    public static void show(int[] arr){
        //[1,2,3,4,5,6,7,8,9]
        String s="[";
        for(int i=0;i<arr.length;i++){
            if(i==arr.length-1){
                s+=arr[i]+"]";
            }else{
                s+=arr[i]+",";
            }
        }
        System.out.println(s);
    }
}

数组的扩容

class Test01{
    /* 
    数组的扩容,就是创建一个新的数组 将元素赋值进去之后,将新数组的地址返回即可
    */
    public static void main(String[] args){
        int[] arr=new int[]{1,2,3};
        arr=copyOf(arr,arr.length+1);
        arr[arr.length-1]=10;
        System.out.println(arr[3]);
    }
    public static int[] copyOf(int[] arr,int newLen){
        int[] newArr=new int[newLen];
        for(int i=0;i<arr.length;i++){
            newArr[i]=arr[i];
        }
        return newArr;
    }
}
public static void binarySearch(){
        //二分查找有个前提 数组必须有序
        /* 
        最好情况 查46 1次就出来了
        最坏情况 查12/60 O(logn)
        */
        int[] arr={12,17,21,32,38,41,46,49,50,50,51,59,60};
        int key=46;
        int index=-1;
        int min_index=0;
        int max_index=arr.length-1;
        int mid_index=(min_index+max_index)/2;
        while(arr[mid_index]!=key){
            if(key<arr[mid_index]){
                max_index=mid_index-1;
            }
            if(arr[mid_index]<key){
                min_index=mid_index+1;
            }
            if(min_index>max_index){
                index=-1;
                break;
            }
            mid_index=(min_index+max_index)/2;
        }
        System.out.println(mid_index);

    }
    public static void linearSearch(){
        /* 
        最好情况 查10 1次就出来了
        最坏情况 查5  10次才出来
        当数组的长度越大的话 最坏情况越差
        时间复杂度(最坏情况) O(n) 线性阶
        */
        int[] arr={10,2,8,3,1,6,4,7,9,5};
        int key=11;
        int index=-1;   //key元素不存在
        for(int i=0;i<arr.length;i++){
            if(arr[i]==key){
                index=i;
                break;
            }
        }
        System.out.println(index);
    }
}
​
import java.util.*;
class test5_1{
    public static void main(String[] args) {
        int[] num = createArrays();
        Arrays.sort(num);
        for (int i = 0; i < num.length; i++) {
            if (i == 0 || (num[i] != num[i - 1])) {
                System.out.println(num[i] + "在数组中出现了" + getCount(num[i], num) + "次");
            }
        }
    }
    
    public static int[] createArrays() {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入1~100之间的整数(以0作为结束):");
        int[] num = new int[100];
        int i = 0;
        int input;
        while (i >= 0) {
            input = scanner.nextInt();
            if (input != 0) {
                num[i] = input;
                i++;
            } else {
                break;
            }
        }
        int zeroIndex = getZeroIndex(num);
        int[] newNum = new int[zeroIndex];
        System.arraycopy(num, 0, newNum, 0, zeroIndex);
        return newNum;
    }
    
    public static int getZeroIndex(int[] num) {
        for (int i = 0; i < num.length; i++) {
            if (num[i] == 0) {
                return i;
            }
        }
        return -1;
    }
    
    public static int getCount(int indexNum, int[] num) {
        int count = 0;
        for (int i = 0; i < num.length; i++) {
            if (indexNum == num[i]) {
                count++;
            }
        }
        return count;
    }
}

​
import java.util.*;
class test5_2{
        public static void main(String[] args) {
        System.out.print("请输入10个正整数:");
        int[] inputNumList = inputNumList();
        System.out.println("当前的数组为:" + Arrays.toString(inputNumList));
        resultNumList(inputNumList);
    }
    
    public static int[] inputNumList() {
        Scanner scanner = new Scanner(System.in);
        int[] inputNumList = new int[10];
        for (int i = 0; i < 10; i++) {
            inputNumList[i] = scanner.nextInt();
        }
        return inputNumList;
    }
    
    public static void resultNumList(int[] inputNumList) {
        int counts = 0;
        ArrayList<Integer> resultNumList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            for (int j = i; j < 10; j++) {
                if (inputNumList[i] == inputNumList[j] && i != j) {
                    inputNumList[j] = -1;
                }
            }
            if (inputNumList[i] != -1) {
                counts++;
                resultNumList.add(inputNumList[i]);
            }
        }
        System.out.println("其中不同的数字个数为:" + counts);
        System.out.print("最后的结果为:" + Arrays.toString(resultNumList.toArray()));
    }
}
import java.util.*;
class test5_3{
        public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int num;
        System.out.print("请输入数字(第一个数表示数组长度):");
        num = scanner.nextInt();
        int[] numArray = new int[num];
        for (int i = 0; i < num; i++) {
            numArray[i] = scanner.nextInt();
        }
        System.out.println("输入的数组为:" + Arrays.toString(numArray));
        if (isSorted(numArray)) {
            System.out.print("该数组已经按升序排列");
        } else {
            System.out.print("该数组没有按升序排列");
        }
    }
    
    public static boolean isSorted(int[] numArray) {
        int[] tmpArray = new int[numArray.length];
        System.arraycopy(numArray, 0, tmpArray, 0, numArray.length);
        Arrays.sort(tmpArray);
        return Arrays.equals(tmpArray, numArray);
    }
}
import java.util.*;
class test5_5{
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入数组1(第一个数字表示数组长度):");
        int[] list1 = new int[scanner.nextInt()];
        for (int i = 0; i < list1.length; i++) {
            list1[i] = scanner.nextInt();
        }
        System.out.print("请输入数组2(第一个数字表示数组长度):");
        int[] list2 = new int[scanner.nextInt()];
        for (int i = 0; i < list2.length; i++) {
            list2[i] = scanner.nextInt();
        }
        if (equals(list1, list2)) {
            System.out.print("这两个数组完全相同");
        } else {
            System.out.print("这两个数组不完全相同");
        }
    }
     
    public static boolean equals(int[] list1, int[] list2) {
        return Arrays.equals(list1, list2);
    }
}
class test5_6{
    public static void main(String[] args){
        int[] arr={1,1,1,1,2,2,2,2,2,3,3,3,3,3,4};
        for(int i=0;i<arr.length;){
            int count=1;
            for(int j=i+1;j<arr.length;j++){
                if(arr[i]==arr[j]){
                    count++;
                }else{
                    break;
                }
            }
            if(count>=4){
                System.out.println(arr[i]);
                return;
            }
            i+=count;
        }
        System.out.println("没有!");
    }
}
import java.util.*;
class test5_7{
    public static void main(String[] args){
        int[] list1={1,3,5,7,9};
        int[] list2={2,4,6,8,10};
        System.out.println(Arrays.toString(merge(list1,list2)));
    }
    public static int[] merge(int[] list1,int[] list2){
        if(list1==null&&list2==null){
            return null;
        }
        if(list1==null){
            return list2;
        }
        if(list2==null){
            return list1;
        }
        //只有两个都不是null的情况再考虑具体操作
        int[] list3=new int[list1.length+list2.length];
        int p1=0;
        int p2=0;
        int p3=0;
        while(true){
            if(p1==list1.length&&p2==list2.length){
                break;
            }
            if(p1<list1.length&&p2==list2.length){
                list3[p3++]=list1[p1++];
            }else if(p1==list1.length&&p2<list2.length){
                list3[p3++]=list2[p2++];
            }else{
                if(list1[p1]<=list2[p2]){
                    list3[p3++]=list1[p1++];
                }else{
                    list3[p3++]=list2[p2++];
                }
            }
        }
        return list3;
    }
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值