【Java自学】搬砖中年人代码自学之路Lesson 5

这篇博客记录了作者在自学Java过程中的学习心得,详细介绍了数组的概念、特点、分类,特别是对一维数组和多维数组的声明、初始化、元素访问以及内存解析进行了深入探讨。此外,还涉及到了数组的默认初始化值和内存分布,并以代码示例解释了数组的内存结构。最后,博主分享了排序算法的基础知识,包括冒泡排序和快速排序的原理,以及排序算法的性能比较和选择策略。

是的我还在。。。。

2022年真的是我经历过的最牛逼的一年了,从年初开始到现在3个多月的时间,先后经历了2次疫情隔离,合计一个半月。作为一个自控力非常弱鸡的人,隔离在家对我来说简直就是噩梦。。。

真的是会懒,而且长期两地分居的我第二次隔离被隔离在了家中,居然过了一个月的已婚生活,每天徘徊在厨房做饭和躺着消遣两点一线之间,实在是提不起精神学习,这一点还是要自我抨击一下的,真弱!!梦想呢!!宏图壮志呢!!

不过还好,还是重新捡起来跟着学习了,700多课的视频课已经听了200多课了,现在立个flag,希望自己在今年年底之前能够顺利完成所有课程的学习(毕竟现在的工作真的是越干越觉得傻逼,搞不好7、8月份还要出去找工作,所以就到年底好了)


一、数组「Array」

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

        2、数组的常见概念

                1、数组名

                2、下标(或索引):索引的起始值是0

                3、元素

                4、数组的长度:存储的元素的个数

        3、数组的特点:

                1、数组是有序排列的

                2、数组本身是引用数据类型,而数组中的元素既可以是基本数据类型,也可以是引用数据类型

                3、创建数组的对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址

                4、数组的长度一旦确定就不可以修改。如果使用中发现已有的数组长度不够了,但是还要添加元素,只能新建数组

        4、数组的分类:

                1、按照维数分类:一维数组、二维数组、多维数组

                2、按照数组元素的类型分类:基本数据类型元素的数组、引用数据类型元素的数组

二、一维数组的使用

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

                1、静态初始化:数组的初始化和数组元素的赋值操作同时进行

                2、动态初始化:数组的初始化和数组元素的赋值操作分开进行

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

int ids[];//声明数组

//静态初始化
ids = new int[]{1001,1002,1003,1004};
//动态初始化
String[] names = new String[5];

//特殊的正确写法
int[] arr10 = {1,2,3}//类型推断

        2、如何调用数组的指定位置的元素

                1、通过角标(下标、索引)的方式调用

                2、Java中数组的角标(下标、索引)是从0开始的,到数组的「长度-1」结束

                      Java中只要涉及到"索引"的,「基本上」都是从0开始,但是后续学习的数据库相关的内容,是从1开始的

names[0] = "周杰伦";
names[1] = "王力宏";
names[2] = "林俊杰";
names[3] = "蔡依林";
names[4] = "潘玮柏";
names[5] = "周润发";//编译是可以通过的,因为语法上是没有错误的,但是只有解释运行的时候才会加载到内存中,所以运行时候会报错,因为已经超过内存范围了

        3、如何获取数组的长度

                1、数组的属性:length

System.out.println(names.length);//5
System.out.println(ids.length);//4

        4、如何遍历数组元素

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

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

                1、虽然数组还没有赋值,但是在创建数组的时候,为了在内存中开辟一块连续的空间,会填进去一些无意义的值来占据这个空间

                2、不同类型的数组的默认初始化值

                        1、基本数据类型

                                1、数组元素是整型(short、byte、int、long):默认初始化值是0

                                2、数组元素是浮点型:默认初始化值是0.0

                                3、数组元素是char型:默认初始化值是「ASCII码是0或者是\u0000,而非数字0」,执行后表现出来效果是空格,但是其实不是空的

                                4、数组元素是布尔型:默认初始化值是false,因为false在二进制中是0

                        2、引用数据类型:数组元素是引用数据类型——默认初始化值是null,即空值

//数组元素是整型(short、byte、int、long):默认初始化值:0
short[] arr1 = new short[4];
for(int i = 0;i < arr1.length;i++){
    System.out.println(arr1[i]);
}

//数据元素是浮点型:默认初始化值:0.0
float[] arr2 = new float[4];
for(int i = 0;i < arr1.length;i++){
    System.out.println(arr2[i]);
}

//数组元素是char型:默认初始化值:ASCII码是0或者是\u0000,而非数字0,执行后表现效果为空格,但是其实不是空的
char[] arr3 = new char[4];
for(int i = 0;i < arr1.length;i++){
    System.out.println("----" + arr3[i] + "****");
}
if(arr3[0] == 0){
    System.out.println("你好");
}

//数组元素是boolean型:默认初始化值:false,因为false在二进制中是0
boolean[] arr4 = new boolean[4];
for(int i = 0;i < arr1.length;i++){
    System.out.println(arr4[i]);
}

//数组元素是引用数据类型:默认初始化值是null,即空值。注意是null而不是"null"
String[] arr5 = new String[4];
System.out.println(arr5[0]);
if(arr5[0] == null){
    System.out.println("今天天气不错");
}

        6、 数组的内存解析:内存的简化结构⬇️

                1、栈(stack):主要存放「局部变量(方法中定义的变量都是局部变量,比如main方法)」

                2、堆(heap):主要存放new出来的结构

                        1、对象

                        2、数组

                3、方法区(method area)

                        1、常量池,存放例如String

                        2、静态域,存放例如static

                4、举例说明:

                        1、代码示例:仅为简单解析使用,其实实际执行过程还会有所偏差,先理解即可

int[] arr6 = new int[]{1,2,3;
String[] arr7 = new String[4];
arr7[1] = "刘德华";
arr7[2] = "张学友";
arr7 = new String[3];

                        2、解析过程:逐行代码进行分析

                                1、栈结构:声明arr6、声明arr7

                                2、堆结构:声明new int[]{1,2,3};、声明new String[4];

                                3、赋值过程中,给堆结构中的数组分配一个十六进制的首地址值,例如arr6:0x34ab、arr7:0x12ab

                                4、这个首地址值同时也会分配给栈结构中的arr6、arr7

                                5、通过首地址值将栈结构和堆结构联系起来

                                6、通过角标元素调用堆结构new String[]中的元素

                                7、arr7[1]代表给arr7中的第二个元素赋值刘德华,arr7[2]代表给arr7中的第三个元素赋值张学友

                                8、arr7 = new String[3];意味着重新创建了一个数组,同时分配一个首地址值,例如0x5566,同时因为arr7原来分配过一个首地址值,但是由于重新创建了,所以将之前的首地址值作废了,分配了新的首地址值,即0x5566

                                9、所以示例代码的输出值应该是null

三、多维数组的使用:二维数组的使用

        1、Java语言里提供了支持多维数组的语法

        2、如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表

         3、对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实从数组底层的运行机制来看,其实没有多维数组

                1、二维数组的使用

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

//二维数组的静态初始化
int[][] arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}};

//二维数组的动态初始化1
String[][] arr2 = new String[3][2];//3代表着堆结构空间中有3个长度的数组,2代表这3个空间里的每个元素都是2个长度的数组
//二维数组的动态初始化2
String[][] arr3 = new String[3][];

//特殊的正确写法
int arr4[][] = new int[][]{{1,2,3},{4,5},{6,7,8}};
int[] arr5[] = new int[][]{{1,2,3},{4,5},{6,7,8}};
int[] arr6[] = {{1,2,3},{4,5},{6,7,8}};//类型推断

                        2、如何调用数组的指定位置的元素

System.out.println(arr1[0][1]);//输出arr1数组中的2
System.out.println(arr2[1][1]);//输出arr2数组的第二行第二个元素,null
System.out.println(arr3[1][0]);//编译能够通过,但是运行会报空指针异常

arr3[1] = new String[4];
System.out.println(arr3[1][0]);//上面第三行代码报错是因为arr3这个数组中,第二个数组元素没有进行定义,所以定义之后再运行就不会报错空指针

                        3、如何获取数组的长度

System.out.println(arr4.length);//3,数组的长度只计算外层数组的长度
System.out.println(arr4[0].length);//3
System.out.println(arr4[1].length);//2

                        4、如何遍历数组

//几维数组就要嵌套几层for循环
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();//换行
}

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

                                1、针对于初始化方式1,比如: int[][] arr7 = new int[4][3];

                                        1、外层元素的初始化值为:首地址值

                                        2、内层元素的初始化值为:同一维数组

                                2、针对于初始化方式2,比如: double[][] arr10 = new double[4][];

                                        1、外层元素的初始化值为:null

                                        2、内层元素的初始化值为:不能调用,空指针异常

int[][] arr7 = new int[4][3];
System.out.println(arr7[0]);//[I@7ad041f3 <--- 首地址值,[代表是数组,I代表是int型
System.out.println(arr7[0][0]);//0
System.out.println(arr7);//[[I@251a69d7

float[][] arr8 = new float[4][3];
System.out.println(arr8[0]);//[F@7344699f
System.out.println(arr8[0][0]);//0.0
System.out.println(arr8);//[[F@6b95977

String[][] arr9 = new String[4][3];
System.out.println(arr9[0]);//[Ljava.lang.String;@7e9e5f8a
System.out.println(arr9[0][0]);//null
System.out.println(arr9);//[[Ljava.lang.String;@8bcc55f

double[][] arr10 = new double[4][];
System.out.println(arr10[1]);//null
System.out.println(arr10[1][0]);//空指针异常

                        6、 数组的内存解析

                                1、举例说明

                                        1、代码示例:仅为简单解析使用,其实实际执行过程还会有所偏差,先理解即可

int[][] arr11 = new int[4][];
arr11[1] = new int[]{1,2,3};
arr11[2] = new int[4];
arr11[2][1] = 30;

                                        2、解析过程

                                                1、外层同一维数组

                                                2、此时外层4个值都是null

                                                3、通过arr11[1]= new int[]{1,2,3};进行赋值,null变成了new int的首地址值,内部元素先都是0,然后通过{1,2,3}进行赋值变成123 

                                ​​​​​​​        ​​​​​​​        ​​​​​​​4、通过arr11[2]=new int[4];进行赋值,null变成new int的首地址值,由于动态初始化,所以都是0

                                                5、通过arr11[2][1] = 30;进行赋值,0变成30

⚠️数据结构

        1、数据与数据之间的逻辑关系:集合、一对一、一对多、多对多

        2、数据的存储结构:

                1、线性表:主要刻画一对一的数据关系

                        1、顺序表:典型实现——数组

                        2、链表

                        3、栈:特点——先进后出

                        4、队列:特点——先进先出

                2、树形结构:主要刻画一对多的数据关系

                        1、二叉树:主要研究

                                1、应用场景:数据库的索引等等

                3、图形结构:主要刻画多对多的数据关系

⚠️算法:数据结构相关算法类别⬇️

        1、排序算法

        2、搜索算法(检索算法)

⚠️数组中涉及到的常见算法

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

public class YangHui{
    public static void main(String[] args){
        //【练习:使用二维数组打印一个10行的杨辉三角形】
        //提示:
            //1. 第一行有1个元素,第n行有n个元素
            //2. 第一行的第一个元素和最后一个元素都是1
            //3. 从第三行开始,对于非第一个元素和最后一个元素的元素,即yanghui[i][j] = yanghui[i - 1][j - 1] + yanghui[i - 1][j]
        
        //步骤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] = 1;
        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();
        }
    }
}
public class Circle{
    public static void main(String[] args){
        //【练习:】
        //从键盘输入一个整数(1-20),则以该数字为矩阵大小,把1,2,3,...,n*n的数字按照顺时针螺旋的形式填入其中
        //例如:
        //输入数字2,则程序输出
        //1 2
        //4 3
        //输入数字3,则程序输出
        //1 2 3
        //8 9 4
        //7 6 5
        //输入数字4,则程序输出
        //1 2 3 4
        //12 13 14 5
        //11 16 15 6
        //10 9 8 7

        //解法1:
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个数字:");
        int len = scan.nextInt();
        int s = len * len;
        
        /*
		 * k = 1:向右;k = 2:向左;k = 4:向上
		 */
        
		int k = 1;
		int i = 0, j = 0;
		for(int m = 1;m <= s;m++) {
			if(k == 1) {
				if(j < len && number3[i][j] == 0) {
					number3[i][j++] = m;
				}else {
					k = 2;
					i++;
					j--;
					m--;
				}
			}else if(k == 2){
				if(i < len && number3[i][j] == 0) {
					number3[i++][j] = m;
				}else {
					k = 3;
					i--;
					j--;
					m--;
				}
			}else if(k == 3) {
				if(j >= 0 && number3[i][j] == 0) {
					number3[i][j--] = m;
				}else {
					k = 4;
					i--;
					j++;
					m--;
				}
			}else if(k == 4) {
				if(i >= 0 && number3[i][j] == 0) {
					number3[i--][j] = m;
				}else {
					k = 1;
					i++;
					j++;
					m--;
				}
			}
		}
		//遍历
		for(int m = 0;m < number3.length;m++) {
			for(int n = 0;n < number3[m].length;n++) {
				System.out.print(number3[m][n] + "\t");
			}
			System.out.println();
		}
		
		//解法2:
		int a = 7;
		int[][] number4 = new int[a][a];
		
		int count = 0;//要显示的数据
		int maxX = a - 1;//x轴的最大下标
		int maxY = a - 1;//y轴的最大下标
		int minX = 0;//x轴的最小下标
		int minY = 0;//y轴的最小下标
		while(minX <= maxX) {
			for(int x = minX;x <= maxX;x++) {
				number4[minY][x] = ++count;
			}
			minY++;
			for(int y = minY;y <= maxY;y++) {
				number4[y][maxX] = ++count;
			}
			maxX++;
			for(int x = maxX;x >= minX;x--) {
				number4[maxY][x] = ++count;
			}
			maxY--;
			for(int y = maxY; y >= minY;y--) {
				number4[y][minX] = ++count;
			}
			minX++;
		}
    }
}

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

public class Cal{
    public static void main(String[] args){
        //练习:定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值、最小值、和值、平均值,并输出出来
		//要求:所有随机数都是两位数

        //定义指定数组
        int[] arr = new int[10];
        
        //为数组元素赋值
        for(int i = 0;i < 10;i++){
            arr[i] = (int)(Math.random() * (99 - 10 + 1) + 10);
        }

        //求数组最大值
        int max = arr[0];
        for(int i = 0;i < 10;i++){
            if(arr[i] > max){
                max = arr[i];
            }
        }
        System.out.println("最大值为:" + max);

        //求数组最小值
        int min = arr[0];
        for(int i = 0;i < 10;i++){
            if(arr[i] < min){
                min = arr[i];
            }
        }
        System.out.println("最小值为:" + min);

        //求数组所有元素的和
        int sum = 0;
        for(int i = 0;i < 10;i++){
            sum += arr[i];
        }
        System.out.println("数组所有元素的和为:" + sum);

        //求数组元素的平均值
        int avg = sum / arr.length;
        System.out.println("数组元素的平均数为:" + avg);

    }
}

        3、数组的复制、反转、查找

                1、数组的复制:区别于数组变量的赋值,arr1 = arr

public class Copy{
    public static void main(String[] args){
        //复制下面的数组
		//int[] arr = new int[]{34,5,22,-98,6,-76,0,-3}

        //声明指定数组
        int[] arr = new int[]{34,5,22,-98,6,-76,0,-3}

        //创建新数组,新数组的长度与指定数组相等
        int[] newArr = new int[arr.length];

        //用指定数组的值为新数组赋值
        for(int i = 0;i < arr.length;i++){
            newArr[i] = arr[i];
        }

        //遍历输出数组数据
        for(int i = 0;i < newArr.length;i++){
            System.out.print(newArr[i] + "\t");
        }
    }
}

                2、数组的反转:创建中间数组

public class Reverse{
    public static void main(String[] args){
        //反转下面的数组
		//int[] arr = new int[]{34,5,22,-98,6,-76,0,-3}

        //声明指定数组
        int[] arr = new int[]{34,5,22,-98,6,-76,0,-3}

        //创建新数组,新数组的长度与指定数组相等
        int[] newArr = new int[arr.length];

        //遍历新数组,并从第一个数据开始,指定数组反向赋值
        for(int i = 0;i < arr.length;i++){
            newArr[i] = arr[arr.length - 1 - i];
        }

        //让指定数组的名称指向新数组
        arr = newArr;
        
       //遍历输出数组数据
        for(int i = 0;i < arr.length;i++){
            System.out.print(arr[i] + "\t");
        }
    }
}

                3、查找

                        1、线性查找:

public class Search{
    public static void main(String[] args){
        //使用线性查找,从下面数组中查找22是否存在。存在,返回所在位置的索引。不存在,输出提示信息
		//int[] arr = new int[]{34,5,22,-98,6,-76,0,-3}

        //声明指定数组
        int[] arr = new int[]{34,5,22,-98,6,-76,0,-3}

        //查找指定数据
        boolean isFlag = true;
        for(int i = 0;i < arr.length;i++){
            if(arr[i] == 22){
                System.out.println("数字22的索引位置为:" + i);
                isFlag = false;
                break;
            }
        }
        if(isFlag){
            System.out.println("未找到指定数据");
        }
    }
}

                        2、二分法查找:也叫做折半查找,比线性查找要快,使用前提——所要查找的数组必须是有序的,熟悉即可,实际开发中有现成的方法可以调用

public class BinarySearch{
    public static void main(String[] args){
        //二分法查找
        int[] arr = new int[]{-98,-34,2,34,54,66,79,105,210,333}

        //确定查找值
        int dest = -34;

        //定位索引位置
        int head = 0;//初始的首索引
        int end = arr.length - 1;//初始的末索引

        //声明标签
        boolean isFlag = true;
        
        //查找指定数据 ==> 因为题干数组是从小到大排好序的,所以不需要进行排序,如果是乱序的数组,先要进行排序,再进行二分法查找
        while(head <= end){
            int middle = (head + end) / 2;
            if(dest == arr[middle]){
                System.out.println("目标数值的索引位置为:" + middle);
                isFlag = false;
                break;
            }else if(arr[middle] > dest){
                end = middle - 1;
            }else{//arr[middle] < dest
                head = middle + 1;
            }
        }
        if(isFlag){
            System.out.println("没有找到指定数据");
        }
        
    }
}

        4、数组元素的排序算法:假设含有n个记录的序列为{R1,R2,…,Rn},其相应的关键字序列为{K1,K2,…,Kn},将这些记录重新排序为{Ri1,Ri2,…,Rin},使得相应的关键字值满足条件Ki1<=Ki2<=…<=Kin,这样的一种操作称为排序。通常来说,排序的目的是快速查找(二分法查找需要有序,所以排序算是对二分法查找进行铺垫)​​​​​​​

​​​​​​​                ​​​​​​​1、衡量排序算法的优劣

                        1、时间复杂度:分析关键字的比较次数和记录的移动次数

                        2、空间复杂度:分析排序算法中需要多少辅助内存

                        3、稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的

                2、排序算法分类

                        1、内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成

                        2、外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助外部存储器。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成

                3、十大内部排序算法:跟具体哪种编程语言没有关系,是算法层面的排序

                        1、选择排序

                                1、直接选择排序

                                2、堆排序(了解)

                        2、交换排序

                                1、冒泡排序(掌握):

                                        1、原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来

                                        2、排序思想:

                                                1、比较相邻的元素,如果第一个比第二个大(升序),就交换他们两个

                                                2、对每一对相邻元素作相同的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数

                                                3、针对所有的元素重复以上的步骤,除了最后一个

                                                4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止

public class BubbleSort{
    public static void main(String[] args){
        //使用冒泡排序,实现如下的数组从小到大的排序
        //int[] arr = new int[]{34,5,22,-98,6,-76,0,-3};

        //声明指定数组:
        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 - 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");
        }
    }
}

                                2、快速排序(掌握)

                                        1、通常明显比同为O(nlogn)的其他算法更快,因此常被采用而且快速排序采用了分治法的思想,所以在很多笔试面试中能经常看到快速排序的影子。

                                        2、由图灵奖获得者Tony Hoare发明,被列为20世纪十大算法之一,是迄今为止所有内排序算法中速度最快的一种。冒泡排序的升级版,交换排序的一种。快速排序的时间复杂度为O(nlog(n))

                                        3、排序思想

                                                1、从数列中挑出一个元素,称为基准(pivot)

                                                2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任何一边)。这个分区结束后,该基准就处在数列的中间位置,这个称为分区(partition)操作

                                                3、递归(recursive)的把小雨基准值元素的子数列和大雨基准值元素的子数列排序

                                                4、递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了,虽然一直递归下去,但这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去

                                3、插入排序

                                        1、直接插入排序

                                        2、折半插入排序

                                        3、sheel排序(希尔排序)

                                4、归并排序(了解)

                                5、桶式排序

                                6、基数排序

                        4、各种内部排序方法性能比较

                                1、从平均时间而言:快速排序最佳,但在最坏情况下时间性能不如堆排序和归并排序

                                2、从算法简单性看:由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,将其认为是简单算法。对于shell排序、堆排序、快速排序和归并排序算法,其算法比较复杂,认为是复杂排序

                                3、从稳定性看:直接插入排序、冒泡排序和归并排序是稳定的;而直接选择排序、快速排序、shell排序和堆排序是不稳定排序

                                4、从待排序的记录数n大小看:n较小时,宜采用简单排序;而n较大时,宜采用改进排序

                        5、排序算法的选择

                                1、若n较小(如n<=50),可采用直接插入或直接选择排序:当数据规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插入,应选直接插入排序为宜

                                2、若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排序为宜

                                3、若n较大,则应采用时间复杂度为O(nlogn)的排序方法:快速排序、堆排序或归并排序

                        6、算法的5大特征

                                1、输入(input):有0个或多个输入数据,这些输入必须有清楚的描述和定义

                                2、输出(output):至少有1个或多个输出结果,不可以没有输出结果

                                3、有穷性(有限性,finiteness):算法在有限的步骤之后会自动结束而不会无限循环,并且每一步可以在可接受的时间内完成

                                4、确定性(明确性,definiteness):算法中的每一步都有确定的含义,不会出现二义性

                                5、可行性(有效性,effectiveness):算法的每一步都是清楚且可行的,能让用户用纸笔计算而求出答案

                                6、⬆️说明:满足确定性的算法也称为确定性算法。现在人们也关注更广泛的概念,例如考虑各种非确定性的算法,如并行算法、概率算法等。另外,人们也关注并不要求终止的计算描述,这种描述有时被称为过程(procedure)

public class ArraysHomework{
    public static void main(String[] args){
        //【练习1:数组求和】
        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);
        
        //【练习2:】
        //声明int[]x,y[];在给x,y变量赋值后,以下选项允许通过编译的是
        //题目分析:x是int型的一维数组,y是int型的二维数组,这种写法是合并定义。所以int[]x,y[],相当于是int[] x和int[]y[]合并定义了
        //a)    x[0] = y;            不能,因为y是一个二维数组,而x[0]只是一个int型的值
        //b)    y[0] = x;            能,相当于是给二维数组中的一个元素赋了一个一维的值
        //c)    y[0][0] = x;         不能,等号前面是一个int型的数,而x是一个一维数组
        //d)    x[0][0] = y;         不能,等号前面的写法是错误的
        //e)    y[0][0] = x[0];      能,等号两边都是int型的数
        //f)    x = y;               不能,等号前是一维数组,等号后是二维数组

        //【练习4:】
        //创建一个长度为6的int型数组,要求数组的元素的值都在1-30之间,且是随机赋值,同时,要求各元素的值各不相同
        //解法1:
        int[] number = new int[6];
        for(int i = 0;i < number.length;i++){
            number[i] = (int)(Math.random() * 30) + 1;
            boolean flag = false;
            while(true){
                for(int j = 0;j < i;j++){
                    if(number[i] == number[j]{
                        flag = true;
                        break;
                    }
                }
                if(flag){
                    number[I] = (int)(Math.random() * 30) + 1;
                    flag = false;
                    continue;
                }
                break;
            }
        }
        for(int i = 0;i < number.length;i++){
            System.out.println(number[i]);
        }
        
        //解法2:
        int[] number2 = new int[6];
        for(int i = 0;i < number2.length;i++){
            number2[i] = (int)(Main.random() * 30) + 1;
            for(int j = 0;j < i;j++){
                if(number2[i] == number2[j]){
                    i--;
                    break;
                }
            }
        }
        for(int i = 0;i < number2.length;i++){
            System.out.println(number2[i]);
        } 
    }
}

⚠️Arrays工具类的使用

Java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法

        1、boolean equals(int[] a, int[] b):判断两个数组是否相等

        2、String toString(int[] a):输出数组信息

        3、Void fill(int[] a, int val):将指定值填充到数组中

        4、Void sort(int[] a):对数组进行排序

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

import java.util.Arrays;
public class ArraysTest{
    public static void main(String[] args){
        //boolean equals(int[] a,int[] b)
        int[] arr1 = {1,2,3,4};
        int[] arr2 = {1,3,2,4};
        boolean isEquals = Arrays.equals(arr1,arr2);
        System.out.println(isEquals);//输出结果为false,因为数组是有序的

        //String toString(int[] a)
        System.out.println(Arrays.toString(arr1));

        //void fill(int[] a, int val)
        Arrays.fill(arr1,10);
        System.out.println(Arrays.toString(arr1));

        //void sort(int[] a)
        Arrays.sort(arr2);
        System.out.println(Arrays.toString(arr2));

        //int binarySearch(int[],int key)
        int[] arr3 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
        int index = Arrays.binarySearch(arr3,211);
        System.out.println(index);
        if(index >= 0){//返回值负数即为未找到,这个负数的大小与数组的长度有关
            System.out.println(index);
        }else{
            System.out.println("未找到!");
        }
    }
}

⚠️数组使用中的常见异常

        1、数组角标越界的异常:ArrayIndexOutBoundsException

        2、空指针异常:NullPointerException

public class ArraysException{
    public static void main(String[] args){
        //数组角标越界的异常:ArrayIndexOutBoundsException
        int[] arr = new int[]{1,2,3,4,5};
        for(int i = 0;i <= arr.length;i++){//关于i的取值范围多了一个等号
            System.out.println(arr[i]);
        }

        //空指针异常: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());
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值