【java进阶06:数组】使用一维数组模拟栈数据结构 使用二维数组模拟酒店,酒店管理系统 Arrays工具类 冒泡排序算法、选择排序算法、二分法

news2024/11/16 9:48:12

目录

数组

二维数组

总结

作业

Arrays工具类


数组

  1. 数组总结 及 静态初始化一维数组

    在这里插入图片描述

    /*
    Array:
        1、java语言中的数组是一种引用数据类型,不属于基本数据类型,数组的父类是Object
    
        2、数组实际上是一个容器,可以同时容纳多个元素(数组是一个数据的集合)
           数组:字面意思是“一组数据”
    
        3、数组当中可以存储“基本数据类型”的数据,也可以存储“引用数据类型”的数据
    
        4、数组因为是引用类型,所以数组对象存储在 堆内存 中
    
        5、数组当中如果存储的是“java对象”的话,实际上存储的是对象的“引用(内存地址)”
            数组中不能直接存储“java对象”
    
        6、数组一旦创建,在java中规定,长度不可变。(数组长度不可变)
    
        7、数组的分类:一维数组、二维数组、三维数组、多维数组。(一维数组较多,二维数组偶尔使用)
    
        8、所有的数组对象都有length属性(java自带的),用来获取数组中元素的个数
    
        9、java中的数组要求数组中元素的类型统一,如:int类型的数组只能存储int类型,Person类型数组只能存储Person类型
            例如:超市购物,购物袋中装了苹果,就只能装苹果,不能再装橘子。(数组中存储的元素类型统一)
    
        10、数组在内存方面存储的时候,数组元中元素的内存地址是连续的(存储的每一个元素都是有规则的挨着排列的)
            内存地址连续
    
        11、所有的数组都是拿“第一个方框中的内存地址”作为整个数组对象的内存地址。
            (数组中首元素的内存地址作为整个数组对象的内存地址)
    
        12、数组中每一个元素都是有下标的,下标从0开始,以1递增,最后一个元素下标是length-1.
            下标非常重要,因为我们对数组中元素进行“存取”的时候,都需要通过下标来进行。
    
        13、数组这种数据结构的优点和缺点是什么?
            优点:查询/查找/检索某个下标上的元素时效率极高。可以说是查询效率最高的一个数据结构
                为什么效率高?
                    1、每一个元素的内存地址在空间存储上是连续的
                    2、每一个元素类型相同,所以占用空间大小一样
                    3、知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址,直接通过内存地址定位元素,所以数组的检索率是最高的。
    				   数组中存储100个元素,或存储100万个元素,在元素查询/检索方面,效率是相同的。因为数组中元素查找的时候不会一个一个找,是通过数学表达式计算出来的(算出一个内存地址,直接定位的)
            缺点:
                1、由于为了保证数组中每个元素的内存地址连续,所以在数组上随机增加/删除元素时,效率较低,
                因为随机增删会涉及到后面元素统一向前或向后位移的操作。
    
                2、数组不能存储大数据
                    因为很难在内存空间上找到一块特别大的连续的内存空间。
    
                注意:对于数组中最后一个元素的增删,是没有效率影响的。
    
        14、怎么声明/定义一个一维数组
            语法格式:
                int[] array1;
                double[] array2;
                boolean[] array3;
                String[] array4;
                Object[] array5;
    
        15、怎么初始化一个一维数组?
            包括两种方式:静态初始化一维数组,动态初始化一维数组。
                静态初始化语法格式:
                    int[] array = {100,2100,200,30};
                动态初始化语法格式:
                    //初始化一个5长度的int类型数组,每个元素默认值:0
                    int[] array = new int[5];  //这里的5表示数组的元素个数。
    
                    //初始化一个6个长度的String类型数组,每个元素默认值:null
                    String [] names = new String[6]
    
     */
    public class ArrayText01 {
        public static void main(String[] args){
            //声明一个int类型的数据,使用静态初始化的方式
            int[] ii = {1,100,200,30,49,500};
    
            //这是C++风格,虽然可以运行,但不建议在java中使用。
            //int i[] = {1,100,200,30,49,500};
    
            //所有的数组对象都有length属性
            System.out.println("数组i中元素的个数:"+ii.length);
    
            //数组中每一个元素都有下标,通过下标堆数组中的元素进行存和取。
            //取(读)
            System.out.println("i数组中  第一个元素"+ii[0]);
            System.out.println("i数组中 最后一个元素"+ii[5]);
            System.out.println("i数组中 最后一个元素"+ii[ii.length-1]);
    
            //存(改)
            ii[0] = 111;
            ii[ii.length-1] = 888;
            System.out.println("i数组中  第一个元素"+ii[0]);
            System.out.println("i数组中 最后一个元素"+ii[5]);
    
            //一维数组 取遍历
            for(int i = 0;i < ii.length;i++){//i<6,取到5就停止了。
                System.out.println("ii数组中第"+(i+1)+"个元素:"+ii[i]);// i是从 0 到 5,是下标
            }
    
            //下标为6表示第七个元素,第七个元素没有,下标越界了,会出现什么异常呢?
            //System.out.println(ii[6]);//ArrayIndexOutOfBoundsException   下标越界异常
    
            //从最后一个元素遍历到第一个元素。
            for(int i =ii.length-1 ; i>=0 ;i--){
                System.out.println("ii数组中第"+(i+1)+"个元素:"+ii[i]);
            }
        }
    }
    
    
  2. 动态初始化一维数组,以及何时使用静态/动态初始化数组的方式。

    在这里插入图片描述

    /*
        关于每个类型的默认值
        数据类型            默认值
    ------------------------------------
        byte                0
        short               0
        int                 0
        long                0L
        float               0.0F
        double              0.0
        boolean             false
        char                \u0000
        引用数据类型          null
    
        什么时候采用静态初始化方式,什么时候采用动态初始化方式?
            当创建一个数组时:
                确定数组中存储哪些具体的元素时,采用静态初始化的方式。
                不确定将来数组中存储哪些数据,可以采用静态初始化的方式,预先分配空间。
     */
    public class ArrayText02 {
        public static void main(String[] args){
            //声明/定义一个数组,采用动态初始化的方式创建
            int[] ii = new int[4];   //创建一个长度为4的int数组,数组中每个元素的默认值是0
    
            //遍历数组
            for (int i = 0 ; i < ii.length ; i++) {
                System.out.println("ii数组中下标为"+i+"的元素是:"+ii[i]);
            }
    
            //后期赋值
            ii[0] = 111;
            ii[1] = 222;
            ii[2] = 333;
            ii[3] = 444;//注意下标不要越界
            for (int i = 0 ; i < ii.length ; i++) {
                System.out.println("ii数组中下标为"+i+"的元素是:"+ii[i]);
            }
    
            //初始化一个Object类型的数组,采用动态初始化方式
            Object[] objs = new Object[3];    //3个长度,动态初始化,所以每个元素默认值是null
            for (int i = 0 ; i < objs.length ; i++) {
                System.out.println("objs数组中下标为"+i+"的元素是:"+objs[i]);
            }
    
    
            System.out.println("====================");
            //
            String[] strS = new String[3];
            for (int i = 0 ; i < strS.length ; i++) {
                System.out.println("strS数组中下标为"+i+"的元素是:"+strS[i]);
            }
    
            //采用静态初始化的方式
            String[] strS2 = {"abc","def","xyz"};
            for (int i = 0 ; i < strS2.length ; i++) {
                System.out.println("strS2数组中下标为"+i+"的元素是:"+strS2[i]);
            }
    
            //存储Object ,采用静态初始化呢?
            /*
            Object o1 = new Object();
            Object o2 = new Object();
            Object o3 = new Object();
            Object[] objects = {o1,o2,o3};
             */
            //以上还可以简化为:
            Object[] objects = {new Object(),new Object(),new Object()};
    
    
            for (int i = 0 ; i < objects.length ; i++) {
                System.out.println("objects数组中下标为"+i+"的元素是:"+objects[i]);
                /*
                   相当于: Object o = objects[i];
                            System.out.println(o);
                 */
                /*
                输出结果:objects数组中下标为0的元素是:java.lang.Object@1b6d3586
                         objects数组中下标为1的元素是:java.lang.Object@4554617c
                         objects数组中下标为2的元素是:java.lang.Object@74a14482
    
                     object[i] 输出的是此数组中存储的对象,即o1、o2、o3。输出引用会出输出这个对象的内存地址
                     而数组刚好就是存储内存地址的。
    
                 */
            }
        }
    }
    
    
  3. 当一个方法的参数类型为数组时,如何传参数

    //当一个方法上,参数的类型是数组时,我们应该如何传递参数。
    public class ArrayText03 {
        //java的main方法编写方式
        //public static void main(String[] args) {}
        //还可以采用C++的语法格式!
        public static void main(String args[]) {
            //java风格
            int[] ii = {1,2,3};
            for (int i = 0; i <ii.length ; i++) {
                System.out.println(ii[i]);
            }
    
            //C++风格
            int ii2[] = {4,5,6};
            for (int i = 0; i <ii2.length ; i++) {
                System.out.println(ii2[i]);
            }
    
            System.out.println("=====================");
    
            //调用方法时传一个数组进去
            int[] x = {11,22,33,44,55,66};
            printArray(x);
    
            String[] strS = {"hehe","haha","dudu","jiji"};
            printArray(strS);
    
            String[] strArray = new String[2];
            printArray(strArray);
    
            //也可以直接new 一个数组进去
            printArray(new String[4]);
            printArray(new int[3]);
        }
        public static void printArray(int[] array){
            for (int i = 0; i <array.length ; i++) {
                System.out.println(array[i]);
            }
        }
        public static void printArray(String[] args){
            for (int i = 0; i <args.length ; i++) {
                System.out.println("String数组中的元素"+args[i]);
            }
        }
    }
    
  4. 当一个方法的参数是一个数组时,我们还可以采用这种方式传输

    //当一个方法的参数是一个数组时,我们还可以采用这种方式传输
    public class ArrayText04 {
        public static void main(String[] args){
            //静态初始化一维数组
            int[] ii = {1,2,3};
            printArray(ii);
    
            //动态初始化一维数组
            int[] ii2 = new int[2];
            printArray(ii2);
            printArray(new int[3]);
    
            System.out.println("=================");
    
            //没有这种语法
            //printArray({1,2,3,4});
    
            //如果直接传递一个静态数组的话,必须这样写:
            printArray(new int[]{1,2,3,4});
    
        }
    
        //这里为什么用静态方法?
        //方便,不需要new对象。
        public static void printArray(int[] array){
            for (int i = 0; i <array.length ; i++) {
                System.out.println(array[i]);
            }
        }
    }
    
    
  5. main方法中的String[] args 作用:接收用户输入参数

    /*
        main方法上面的String[] args 有什么用?
            分析一下:谁负责调用main方法——JVM
            JVM调用main方法时,会自动传一个String数组过来
     */
    public class ArrayText05 {
        //这个方法是程序员负责写出来,JVM负责调用,JVM调用的时候,一定会传一个String数组过来
        public static void main(String[] args){
            //JVM默认传过来的这个数组对象的长度:默认0
            //通过测试得出:args不为null
            System.out.println("JVM给传递过来的String数组参数,它这个数组长度是:"+ args.length);
    
            //以下这一行代码表示的含义:数组对象创建了,但是数组中没有任何数据。
            String[] strS = new String[0];
            String[] strS2 = {};    //静态初始化数组,里面没有传东西
            printLength(strS);  //0
            printLength(strS2); //0
    
            /*
                这个数组什么时候里面会有值呢?
                    其实这个数组是留给用户的,用户在控制台上输入参数,这个参数会自动被转换为“String[] args”
                    例如在cmd中这样运行程序:java ArrayText05 abc def xyz
                    那么这个时候JVM会自动将“abc def xyz” 通过空格的方式进行分离,分离完之后,自动放到“String[] args”数组当中
                    所以main方法上面的String[] args 数组主要是用来接收用户输入参数的
                    把abc def xyz 转换成字符串数组:{"abc","def","xyz"}
             */
            //遍历数组
            for (int i = 0; i <args.length ; i++) {
                System.out.println(args[i]);
            }
    
        }
    
        public static void printLength(String[] array){
            System.out.println("数组长度为:"+array.length);
        }
    }
    
    
  6. 模拟一个系统,假设这个要使用必须输入用户名和密码

    //模拟一个系统,假设这个系统要使用,必须输入用户名和密码
    public class ArrayText06 {
        //用户名和密码输入到String[] args数组当中
        public static void main(String[] args){
            if(args.length != 2){
                System.out.println("使用该系统时请输入程序参数,参数中包括用户名和密码信息,例如:zhangsan 123");
            }
            //程序执行到这里说明用户确实提供了用户名和密码,接下来应该判断用户名和密码是否正确
            //取出用户名
            String useName =args[0];
            //取出密码
            String password =args[1];
    
            //假设用户名是admin,密码是123的时候表示登录成功,其他一律失败。
            //判断两个字符串是否相等,需要使用equals方法
            //(useName.equals("admin")与(password.equals("123")
            //以下这样编写可以避免空指针异常
            //采用以下编码风格,即使userName和password都是null,也不会出现空指针异常。
            if("admin".equals(useName)){
                 if("123".equals(password)){
                     System.out.println("登录成功");
                 }else {
                     System.out.println("密码输入有误,请确认后重新输入");
                 }
            }else {
                System.out.println("用户名输入错误");
            }
        }
    }
    
    
  7. 数组中存储的类型为:引用数据类型时

    //一维数组的深入,数组中存储的类型为:引用数据类型。
    //对于数组来说,实际上只能存储java对象的“内存地址”,数组中存储的每个元素都是“引用”
    public class ArrayText07 {
        public static void main(String[] args){
            //创建一个Animal类型的数组
            Animal a1 = new Animal();
            Animal a2 = new Animal();
            Animal[] animals = {a1,a2};
    
            //对Animal数组进行遍历
            for (int i = 0; i <animals.length ; i++) {
                /*Animal a = animals[i];
                a.move();*/
                //代码合并
                animals[i].move();
                //animals[i]取出下标为i的数据,因为这个数组是Animal类型的,所以可以调用Animal类中的move()方法
                //这个move方法不是数组的,而是数组中存储的Animal对象的move方法
            }
            //上与下原理相同
    //                int[] array = {1,2,3};
    //                for (int i = 0; i <array.length ; i++) {
    //                    /*int temp =array[i];
    //                    System.out.println(temp); */
    //                    //合并:
    //                    System.out.println(array[i]);
    //                }
    
            //动态初始化要给长度为2的Animal类型数组
            Animal[] animals1 = new Animal[2];
            //创建一个Animal对象,放在数组的第一个盒子中
            animals1[0] = new Animal();
    
            //animals1[1] = new Product();  //Error: 不兼容的类型: Product无法转换为Animal
            //Animal数组中只能存放Animal类型,不能存放Product类型。
            animals1[1] = new Cat();
            animals1[1].move();
    
            //创建一个Animal类型的数组,数组中存储Cat和Bird
            Animal[] animals2 ={new Cat(),new Bird()};      //该数组中存储了两个对象的内存地址
            for(int i = 0 ; i <animals2.length ; i++){
                //如果调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用调用即可
                animals2[i].move();
    
                //Cat c = animals2[i];
                //Error: Animal无法转换为Cat     编译器只知道这个数组中存储的是Animal类型的对象,向下转型需要加强制类型转换
    
                //Cat c = (Cat)animals2[i];
                //Exception in thread "main" java.lang.ClassCastException: Bird cannot be cast to Cat
                //强制类型转换后报错,因为:Bird也是Animal类型的,也存储在Animal类型的数组中,需要动态判断
    
                //当要调用子类中的特有方法时,需要向下转型,并加动态判断。
                if(animals2[i] instanceof Cat){
                    Cat c = (Cat)animals2[i];
                    c.catchMouse();
                }else if(animals2[i] instanceof Bird){
                    Bird b =(Bird)animals2[i];
                    b.sing();
    
                }
                //animals2[i].sing();
                //Error:(57, 28) java: 找不到符号符号:   方法 sing()  位置: 类 Animal
            }
    
    
    
    
        }
    }
    
    class Animal{
        public void move(){
            System.out.println("Animal move......");
        }
    }
    
    //商品类
    class Product{
    
    }
    
    //Cat是Animal的子类
    class Cat extends Animal{
        @Override
        public void move() {
            System.out.println("猫走猫步!");
        }
        public void catchMouse(){
            System.out.println("猫抓老鼠");
        }
    }
    
    class Bird extends Animal{
        @Override
        public void move() {
            System.out.println("Bird Fei Fei Fei!");
        }
        public void sing(){
            System.out.println("鸟儿在唱歌!!");
        }
    }
    
    
  8. 数组的扩容,数组的拷贝

    在这里插入图片描述

    在这里插入图片描述

    /*
        关于一维数组的扩容
        在java开发中,数组长度一旦确定后不可再改变,那么数组满了之后怎么办?
            数组满了,需要扩容
            java中对数组的扩容:
                先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中。
    
        结论:数组扩容效率较低,因为涉及到了拷贝的问题,所以在以后的开发中请注意:尽可能少的进行数据的拷贝。
        可以在创建数组对象的时候预估计一下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率。
     */
    public class ArrayText08 {
        public static void main(String[] args){
            //java中数组扩容时使用System.arraycopy()方法进行拷贝
            // System.arraycopy(5个参数);
    
    //        public static native void arraycopy(
    //        Object src,   //拷贝源,需要扩容的小容量数组
    //        int  srcPos,  //从哪个位置开始,起始元素下标
    //        Object dest,  //拷贝目标:要拷贝到的那个大容量数组中
    //        int destPos,  //从哪个位置开始存放
    //        int length);  //要拷贝的长度
    
            //拷贝源(从这个数组中拷贝,需要扩容的数组)
            int[] src = {1,22,33,4,5};
            //拷贝目标(拷贝到这个目标数组中)
            int[] dest = new int[10];   //初始化一个长度为10的数组,每一个元素默认值为0
    
            //调用JDK中System类中的arraycopy方法,来完成数组的拷贝
            System.arraycopy(src,1,dest,3,2);
    
            //遍历目标数组
            for(int i = 0; i<dest.length;i++){
                System.out.println(dest[i]);    //0 0 0 22 33 ......
            }
    
            //如要拷贝整个数组:
            System.arraycopy(src,0,dest,0,src.length);
            for (int i = 0; i <dest.length ; i++) {
                System.out.println(dest[i]);
            }
    
            //数组中如果存储的元素是 引用 ,可以拷贝吗?当然可以
            String[] strings = {"hello","world","study","java","oracle","mysql","jdbc"};
            String[] strings1 = new String[10];
            System.arraycopy(strings,0,strings1,0,strings.length);
            for (int i = 0; i <strings1.length ; i++) {
                System.out.println(strings1[i]);
            }
    
            //Object类型的数组拷贝
            Object[] objects = {new Object(),new Object(),new Object()};
            Object[] objects1 = new Object[5];
            //这里拷贝的时候不是拷贝对象,而是拷贝对象的内存地址。因为数组里存储引用数据类型时,存储的就是对象的内存地址。
            System.arraycopy(objects,0,objects1,0,objects.length);
            for (int i = 0; i <objects1.length ; i++) {
                System.out.println(objects1[i]);
            }
        }
    
    }
    
    

二维数组

  1. 二维数组的初始化

    /*
        关于java中的二维数组
            1、二维数组其实是一个特殊的一维数组,特殊在这个一维数组当中的每一个元素是一个一维数组。
            2、三维数组是什么?
                三维数组是一个特殊的二维数组,特殊在这个二维数组中每一个元素是一个一维数组。
                实际的开发中使用最多的就是一维数组。二维数组也很少使用。三维数组几乎不用。
    
            3、二维数组静态初始化
                int[][] array = {{1,1,1},{10,20,30},{4,3,65,12,3,3}}
     */
    public class ArrayText09 {
        public static void main(String[] args){
            //一维数组
            int[] array = {100,200,300};
            System.out.println(array.length);//3
    
            //二维数组
            //里面的是四个一维数组,可以有n多个一维数组。
            int[][] a = {
                    {100,200,300},
                    {10,30,50},
                    {99,44,66,75,23},
                    {0}
            };
            System.out.println("------------------");
            System.out.println(a.length);//4
            System.out.println(a[0].length);//3     这是a这个二维数组中下标为0的元素的那个一维数组的长度
            System.out.println(a[1].length);//3
            System.out.println(a[2].length);//5
            System.out.println(a[3].length);//1
    
            int[][] a2 = {
                    {100,200,300},
                    {10,30,50},
                    {99,44,66,75,23},
                    {0},
                    {93,234,2938,493},
                    {102,3948,2}
            };
            System.out.println(a2.length);//6
        }
    }
    
    
  2. 二维数组中元素的读和改

    /*
        关于二维数组中元素的:读和改
            a[二维数组中一维数组的下标][二维数组中的一维数组中的元素下标]
    
            a[0][0]:表示第一个一维数组中的第一个元素。
    
            a[3][100]:表示第四个一维数组中的第101个元素。
    
            对于a[3][100]来说,其中a[3]是一个整体,[100]是前面a[3]直接结束的结果然后再下标100,
     */
    public class ArrayText10 {
        public static void main(String[] args){
            //二维数组
            int[][] a = {
                    {102,192,394},
                    {123,293,49},
                    {10,203,30}
            };
    
            //请取出以上二维数组中的第一个一维数组,以及第一个一维数组中的第一个元素
            int[] a1 = a[0];
            System.out.println(a1[0]);//第一个元素
    
            //合并:
            System.out.println(a[0][0]);
    
            //取出第二个一维数组中的第三个元素
            System.out.println("第二个一维数组中的第三个元素:"+a[1][2]);
    
            //取出第3个一维数组中的第1个元素
            System.out.println("第3个一维数组中的第1个元素:"+a[2][0]);
    
    
            //改
            a[2][0] = 1111111;
            //修改数组3中的第一个元素后再次取出
            System.out.println("修改后的第3个一维数组中的第1个元素:"+a[2][0]);
    
            //注意下标不能越界
        }
    }
    
  3. 二维数组的遍历

    //二维数组的遍历
    public class ArrayText11 {
        public static void main(String[] args) {
            String[][] strings ={
                    {"java","oracle","c++","python","C#"},
                    {"张三","李四","王五","赵七"},
                    {"lucy","ben","jack"},
            };
    
            //遍历二维数组
            for (int i = 0; i <strings.length ; i++) {//二维数组中有几个一维数组循环几次,负责纵向
                //负责遍历一维数组中的二维数组
                for (int j = 0; j <strings[i].length ; j++) {//每个一维数组中有几个元素循环几次,string[i]表示二维数组中的一维数组
                    System.out.print(strings[i][j]+" ");//strings[i][j]表示二维数组中每个一维数组的元素
                }
    
                //输出换行
                System.out.println();
            }
        }
    }
    
    
  4. 动态初始化二维数组

    //动态初始化二维数组
    public class ArrayText12 {
        public static void main(String[] args){
            //3行四列
            //三个一维数组,每一个一维数组中有四个元素
            int[][] ints = new int[3][4];
            printArray(ints);
    
            //二维数组的遍历
    //        for (int i = 0; i <ints.length ; i++) {
    //            for (int j = 0; j <ints[i].length ; j++) {
    //                System.out.print(ints[i][j]+" ");
    //            }
    //            System.out.println();
    //        }
    
            //静态初始化
            int[][] ints1 = {
                    {1,1,1,1},
                    {2,2,2},
                    {3,3},
                    {4}
            };
            printArray(ints1);
            //不能直接传这个进去,没有这种语法
            //printArray({{1,1,1,1}, {2,2,2}, {3,3}, {4}});
    
            //可以这样写
            printArray(new int[][]{{1,1,1,1}, {2,2,2}, {3,3}, {4}});
    }
        public static void printArray(int[][] array){
            //遍历二维数组
            for (int i = 0; i <array.length ; i++) {
                for (int j = 0; j <array[i].length ; j++) {
                    System.out.print(array[i][j]+" ");
                }
                System.out.println();
            }
        }
    }
    
    

总结

数组总结:
    1、数组的优点和缺点,并且要理解为什么。
        空间存储上,内存地址是连续的
        每个元素占用的空间大小相同
        知道首元素的内存储地址
        通过下标可以计算出偏移量
        通过一个数学表达式,就可以快速计算出某个下标位置上元素的内存地址,直接通过内存地址定位,效率非常高

        优点:检索效率高
        缺点:随机增删效率低,数组无法存储大数据量
        注意:数组最后一个元素的增删效率不受影响。

    2、一维数组的静态初始化和动态初始化
        静态初始化:
            int[] array = {1,2,3,4};
            Object[] objs ={new Object(),new Object(),new Object()};
        动态初始化:
            int[] array = new int[4];   //四个长度的一维数组,每个元素默认值0
            Object[] objs = new Object(4);  //四个长度,每个元素默认值null

    3、一维数组的遍历:
        for(int i = 0; i< array.length ; i++){
            System.out.println(array[i]);
        }

    4、二维数组的静态初始化 、动态初始化:
        静态初始化:
            int[][] array = {
                                {1,2,3,4},
                                {29,293,04,3984,38},
                                {10,293,84,85,919},
                                {0,4,3}
                            }

            Object[][] array = {
                                    {new Object(),new Object()},
                                    {new Object(),new Object(),new Object(),new Object()},
                                    {new Object(),new Object(),new Object()},
                                    {new Object(),new Object(),new Object(),new Object(),new Object()}
                                }

        动态初始化:
            int[][] array = new int[3][4];
            Object[][] array = new Object[4][4];
            //Animal类型数组,里面可以存储Animal类型对象,以及Animal类型的子类型都可以。
            Animal[][] array = new Animal[5][2];

    5、二维数组的遍历
        for(int i = 0; i < array.length ; i++){ //外层for循环负责遍历二维数组中的元素。
            //内层for循环负责遍历一维数组里的元素
            for(int j = 0 ; j <array[i].length ; i++){
                System.out.print(array[i][j])
            }
            //换行
            System.out.println();
        }

    6、main方法上“String[] args”参数的使用,(非重点,了解即可)

    7、数组的拷贝:System.arraycopy()方法的使用
        数组有一个特点:长度一旦确定,不可变
        所以数组长度不够的时候,需要扩容,扩容的机制是:新建一个大数组。
        将小数组中的数据拷贝到大数组,然后小数组对象被垃圾回收。

    8、对数组中的数据拷贝到大数组,然后小数组对象被垃圾回收

    9、对数组中存储引用数据类型的情况,要会画他的内存结构图。

作业

  1. 第一题:使用一维数组,模拟栈数据结构

    自己做的

    /*
    第一题:
    	编写程序,使用一维数组,模拟栈数据结构。
    	要求:
    		1、这个栈可以存储java中的任何引用类型的数据。
    		2、在栈中提供push方法模拟压栈。(栈满了,要有提示信息。)
    		3、在栈中提供pop方法模拟弹栈。(栈空了,也有有提示信息。)
    		4、编写测试程序,new栈对象,调用push pop方法来模拟压栈弹栈的动作。
    
    		public class MyStack{ // 栈类
    
    			// 提供一个数组来存储栈中的元素
    			Object[] elements;
    
    			// 栈帧(永远指向栈顶部的元素)
    			// 每加1个元素,栈帧+1
    			// 每减1个元素,栈帧-1
    			int index;
    
    			// 构造方法
    			// 构造方法是不是应该给一维数组一个初始化容量。
    
    			// push方法(push方法压栈)
    			// 压栈表示栈中多一个元素。
    			// 但是栈如果已满,压栈失败。
    			// 这个方法的参数以及返回值类型自己定义。
    
    			// pop方法(pop方法弹栈)
    			// 弹栈表示栈中少一个元素。
    			// 但是栈如果已空,弹栈失败。
    			// 这个方法的参数以及返回值类型自己定义。
    
    		}
    
    		main(){
    			测试...
    		}*/
    
    
    public class ArrayHomeWork1 {
        public static void main(String[] args) {
            MyStack ms1 = new MyStack();
    
            System.out.println("压栈————————————————");
            //压栈
            ms1.push(new Object());
            System.out.println(ms1.elements[0]);
            System.out.println(ms1.index);
    
            ms1.push(new Object());
            System.out.println(ms1.elements[1]);
            System.out.println(ms1.index);
    
            System.out.println(ms1.elements[ms1.index-1]);
    
    
            ms1.push(new Object());
            ms1.push(new Object());
            ms1.push(new Object());
            ms1.push(new Object());
            ms1.push(new Object());
            ms1.push(new Object());
            ms1.push(new Object());
            ms1.push(new Object());
            System.out.println(ms1.elements[9]);
            ms1.push(new Object());
    
            System.out.println(ms1.elements[ms1.index-1]);
    
            System.out.println("-------------------------------------------");
            MyStack ms2 = new MyStack(2);
            System.out.println(ms2.elements.length);
    
            ms2.push(new Object());
            ms2.push(new Object());
            ms2.pop();
            ms2.pop();
    
    
        }
    }
    
    //每创建一个栈对象,
    class MyStack{  //栈类
        //因为要求java中所有的数据类型都可以存储,所以数组类型要定义为Object类型的数组
        Object[] elements ;
    
        //栈帧,指向最顶部的元素。
        int index;
    
        //默认创建一个长度为10的一维数组
        public MyStack(){
            this.elements =new Object[10];
        }
    
        //创建栈对象时,传进来一个数,把这个数作为栈的容量
        public MyStack(int i){
            //默认创建一个一位数组
             this.elements = new Object[i];
    
        }
    
        //压栈方法:push,表示在数组中增加一个元素
        public void push(Object object){
            if(this.index ==this.elements.length){
                System.out.println("栈满了,压栈失败");
            }else{
                //压栈时,栈帧每次+1,此时传递一个元素进去,用下标接收,下标=栈帧-1,
                elements[index] = object;
                this.index += 1;
                System.out.println("压栈成功");
            }
        }
    
    
        //弹栈方法 :pop,表示在数组中删除一个元素
        public void pop(){
            //弹栈时,帧里有东西才会弹,如果没有,则弹栈失败。即:index大于0时才会弹栈,如果index为0,则说明栈中没有元素了
            //所以大于0才会弹栈,弹栈后,栈里的元素-1,
    
            if(this.index > 0){
                this.index -= 1;
                elements[index] = null;
                System.out.println("弹栈成功");
                if(index == 0){
                    System.out.println("栈干净了");
                }
            }else {
                System.out.println("栈已空,弹栈失败");
            }
        }
    }
    

    根据视频做出来的

    /*
    	编写程序,使用一维数组,模拟栈数据结构。
    	要求:
    		1、这个栈可以存储java中的任何引用类型的数据。
    		2、在栈中提供push方法模拟压栈。(栈满了,要有提示信息。)
    		3、在栈中提供pop方法模拟弹栈。(栈空了,也有有提示信息。)
    		4、编写测试程序,new栈对象,调用push pop方法来模拟压栈弹栈的动作。
    		5、假设栈的默认初始化容量是10,(请注意无参构造方法的编写方式)
     */
    public class MyStack {
        //向栈中存储元素,我们这里使用一维数组模拟。存到栈中,就表示存储到数组中。因为数组是我们学习java的第一个容器
        //为什么选择Object类型数组?因为这个栈可以存储java中的任何引用数据类型的数据。
        //new Animal() 对象可以放进去,new Person()对象也可以放进去,因为Animal和Person的超级父类就是Object。
        //包括String也可以放进去,因为String父类也是Object。
        //注意:“abc”这是一个字符串对象,字符串在java中有优待,不需要new也是一个对象。“abc”字符串也是java对象,属于String类型。
        private Object[] elements ;//private Object[] elements = new Object[10]; 也可以在这里直接赋值。
    
        //栈帧,永远指向栈顶部元素   赋值-1,与下标同步增加。
        private int index = -1;
    
    
        //无参构造方法
        public MyStack() {
            //一维数组动态初始化,默认初始化为10。
            this.elements = new Object[10];
        }
    
        public MyStack(int i) {
            this.elements = new Object[i];
        }
    
        //set和get也许用不上,但你必须写上,这是规矩。使用IDEA生成就可以。
        //封装第一步:属性私有化,第二步:对外提供set和get方法。
        public Object[] getElements() {
            return elements;
        }
        public void setElements(Object[] elements) {
            this.elements = elements;
        }
    
    
        //压栈的方法,object:被压入的元素
        public void push(Object object){
            if(this.index >= this.elements.length-1){
                System.out.println("栈已满,压栈失败");
                return;
            }
            //程序执行到这里,说明栈里还有空间,可以继续加元素
            //this.index++ ;
            //elements[index] = object;
            //可合并为:         ++index ,表示先加1再赋值,默认index为-1,压入后index为0,与压入元素的下标相同
            elements[++index] = object;
    
            //所有的System.out.println()方法执行时,如果输出引用的话,自动调用引用的toString()方法。
            System.out.println("元素  "+object+"  压栈成功,栈帧此时指向"+index);
    
            }
        //弹栈方法
        public void pop(){
            if(index <= -1){
                System.out.println("栈已空,弹栈失败");
                return;
            }
            //程序执行到这里说明栈还没空,
            System.out.println("元素  " + elements[index] +"  弹栈成功,此时栈帧指向:"+ --index);
        }
    
    }
    
    

    测试

    public class MyStackText {
        public static void main(String[] args){
            //创建一个栈对象
            MyStack stack = new MyStack();
    
            //调用方法压栈
            stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());
            stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());
            //压满之后
            stack.push(new Object());   //栈已满,压栈失败
    
            //弹栈
            stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();
            stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();
            //栈空后
            stack.pop();//栈已空,弹栈失败
    
            //调用有参构造创建一个栈对象
            MyStack stack2 = new MyStack(3);
    
            //压栈
            stack2.push(new Object());stack2.push(new Object());stack2.push(new Object());
            //栈满
            stack2.push(new Object());//栈已满,压栈失败
    
            //弹栈
            stack2.pop();stack2.pop();stack2.pop();
            //栈空
            stack2.pop();//栈已空,弹栈失败
    
        }
    }
    
    
  2. 第二题:酒店管理系统

    自己做没什么思路,根据老师说的做出来的

    房间类

    // 酒店房间
    public class Room {
        /*
        * 房间编号:
        *     1楼:101 102 103 104 105.....
        *     2楼:201 202 203 204 205......
        *     3楼:......
        *     ......
        * */
        private int no;
        //房间类型:单人间  双人间  总统套房
        private String type;
         /*
         * 房间状态:
         * true:表示空闲,房间可以被预定
         * flase:表示房间已被使用,不能再被订
         * */
        private boolean status;
    
        //构造方法
        public Room() {
    
        }
        public Room(int no, String type, boolean status) {
            this.no = no;
            this.type = type;
            this.status = status;
        }
    
        //set和get方法
        public int getNo() {
            return no;
        }
    
        public void setNo(int no) {
            this.no = no;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        //idea工具类型的boolean类型的变量,生成的get方法的方法名:isXxx()
        //public boolean isStatus() { return status; }
        //如果你不喜欢,可以修改为:getXxx()
        public boolean getStatus() {
            return status;
        }
    
        public void setStatus(boolean status) {
            this.status = status;
        }
    
    
        /**
     * 自己做的时候没想到这里,不知道如何打印房间状态。
     */
        //equals方法重写
        //equals是用来比较两个对象是否相等的
        //如何比较,自己定。你认为两个房间编号相同,就表示同一个房间,那么你写代码编写比较房间编号就可以。
        public boolean equals(Object obj) {
            if (obj == null ||!(obj instanceof Room)) return false;
            if (this ==obj) return true;
            Room room =(Room)obj;
            //如果两个房间的房间号相同,我们就说他们是同一个房间
            return this.getNo() == room.getNo() ;
        }
    
    
        //toString方法重写
        //toString方法的目的是将java对象转换成字符串形式。
        //如何转,转成什么格式,自己定。目的:简单,清晰明了。
        //如:这里不要看对象的内存地址。要看具体的信息
        public String toString() {
            //return "[101,单人间,使用中]";
            //return "[102,双人间,空闲]";
            //动态打印出房间状态信息(把一个变量塞到一个字符串当中,口诀:加一个双引号,双引号中间加 + ,两个加号中间加变量名 【"+name+"】)
            //return "["+no+","+type+","+status+"]";
            //status这里true时输出:空闲,false时输出:使用中,所以使用三目运算符
            return "["+no+","+type+","+(status ? "空闲":"使用中")+"]";
    
            //语法规则:布尔表达式?表达式1:表达式2
            //当布尔表达式的结果是true时,选择表达式1作为整个表达式的执行结果。
            //当布尔表达式的结果是false时,选择表达式2作为整个表达式的执行结果。
        }
    
        //编写一个临时程序测试一下,测试完删除
    
    /*      public static void main(String[] args) {
            Room room = new Room(101,"单人间",true);
            Room room1 = new Room(102,"豪华VIP套间",false);
    
            System.out.println(room.toString());
            System.out.println(room1);//room1是一个引用,输出引用时,会自动调用引用的toString()方法。
    
            System.out.println(room.equals(room1));
    
            //查看一个类中的所有的属性和方法快捷键:ctrl +F12
        }*/
    }
    
    

    酒店类

    import java.util.Scanner;
    
    //酒店对象,酒店中有二维数组,二维数组模拟大厦
    public class Hotel {
        //二维数组,模拟大厦的房间
        private Room[][] rooms;
    
        //盖楼通过构造方法来盖
        public Hotel(){
            //一共有几层,每层的房间是什么,每个房间的编号是什么。
            //我们可以先写死,一共三层,一层是单人间,二层是双人间,三层是总统套房。每层有10个房间
            rooms = new Room[3][10];
    
            //创建30个对象,放到数组当中。
            //怎么放?二维数组遍历
            for(int i = 0; i <rooms.length ;i++){//i是下标,i+1是楼层
                    //自己写的,还可以简化
    //                            for(int j = 0 ; j <rooms[i].length;j++){
    //                                rooms[i][j] = new Room();
    //                                //初始化房间编号
    //                                rooms[i][j].setNo((i+1)*100+j+1);
    //                                //每个房间初始时是空闲的
    //                                rooms[i][j].setStatus(true);
    //                                //初始化房间类型
    //                                if(i+1 ==1){
    //                                    rooms[i][j].setType("单人间");
    //                                }else if(i+1 == 2){
    //                                    rooms[i][j].setType("双人间");
    //                                }else if(i+1 == 3){
    //                                    rooms[i][j].setType("总统套间");
    //                                }
    //                            }
                for (int j = 0; j <rooms[i].length ; j++) {
                    if(i == 0){//一层
                        rooms[i][j] = new Room((i+1)*100+j+1,"单人间",true);
                    }else if(i == 1){//二层
                        rooms[i][j] = new Room((i+1)*100+j+1,"双人间",true);
                    }else if(i == 2){//三层
                        rooms[i][j] = new Room((i+1)*100+j+1,"总统套房",true);
                    }
                }
    
            }
    
        }
        //想盖几层盖基层的有参构造,类型初始化尚待写入,无思路,以后再写
    /*                    public Hotel(int a,int b){
                            System.out.println("已将酒店盖好,酒店共"+a+"层,每层有"+b+"个房间");
                            //二维数组,模拟大厦
                            rooms = new Room[a][b];
    
                            //使用二维数组遍历初始化房间。每一层房间的类型相同。
                            Scanner s = new Scanner(System.in);
    
    
                            for (int i = 0; i <rooms.length ; i++) {
                                for (int j = 0; j <rooms[i].length ; j++) {
    
    
                                    //在这里为每一层楼的每一个房间初始化
                                    rooms[i][j] = new Room();
    
                                    //初始化房间编号
                                    //每一层的房间编号=这一层的层数*100+这个房间的房间号。
                                    //因为数组下标都是从0开始,层数=i+1,房间号=j+1
                                    rooms[i][j].setNo((i+1)*100+j+1);
    
                                    //所有的房间状态为:空闲
                                    rooms[i][j].setStatus(true);
    
    
                                }
                            }
                        }*/
    
        //打印酒店房间状态的方法
        public void printStatus(){
            for(int i = 0; i <rooms.length ;i++){
                for(int j = 0 ; j <rooms[i].length;j++){
                    System.out.print(rooms[i][j]+"  ");
                }
                System.out.println();
            }
        }
        //查看正在使用中的房间:
        public void printFalse(){
            for(int i = 0; i <rooms.length ;i++){
                for(int j = 0 ; j <rooms[i].length;j++){
                    if(rooms[i][j].getStatus() == false) System.out.print(rooms[i][j]+"  ");
                }
                System.out.println();
            }
        }
    
        /*
        订房退房方法,调用时需要传递一个房间编号进来,这个编号是酒店前台输入的.
            订房就是将房间状态false,退房是将房间状态true。
            假设房间编号101,下标:rooms[0][0]
            通过房间编号推出下标,获取房间对象
         */
    
        //订房方法
    
        public void order(int roomNo){
            Room r = rooms[roomNo/100-1][roomNo%10-1];
            if(r.getStatus() == true){
                r.setStatus(false);
                System.out.println(r);
            }else{
                System.out.println("该房间已被使用,请确认要订的房间后重新输入");
            }
    
        }
        //退房方法
        public void out(int roomNo){
            Room r = rooms[roomNo/100-1][roomNo%10-1];
            if( r.getStatus()== false){
                r.setStatus(true);
                System.out.println(r);
            }else {
                System.out.println("该房间已为空,请不要重复退房");
            }
    
        }
    }
    

    测试类

    import java.lang.reflect.Parameter;
    import java.util.Scanner;
    
    /*
        第二题:(java软件工程师人生路上第一个小型项目。锻炼一下面向对象。)
            为某个酒店编写程序:酒店管理系统,模拟订房、退房、打印所有房间状态等功能。
            1、该系统的用户是:酒店前台。
            2、酒店使用一个二维数组来模拟。“Room[][] rooms;”
            3、酒店中的每一个房间应该是一个java对象:Room
            4、每一个房间Room应该有:房间编号、房间类型、房间是否空闲.
            5、系统应该对外提供的功能:
                可以预定房间:用户输入房间编号,订房。
                可以退房:用户输入房间编号,退房。
                可以查看所有房间的状态:用户输入某个指令应该可以查看所有房间状态。
     */
    public class HotelManagementSystem {
        public static void main(String[] args) {
            Hotel hotel = new Hotel();
    //        hotel.printStatus();
    //
    //        hotel.order(102);
    //        System.out.println("=-------------------------------====");
    //        hotel.printStatus();
    
            //首先输出一个欢迎界面
            System.out.println("欢迎使用酒店管理系统,请认真阅读使用说明");
            while (true) {
                System.out.println("编号对应相应功能:【1】表示查看房间列表、【2】订房、【3】退房、【4】打印正在使用中的房间、【0】退出系统");
                Scanner s = new Scanner(System.in);
    
                int i = s.nextInt();
                if(i == 1){
                    hotel.printStatus();
                }else if(i == 2){
                    System.out.println("请输入所要订的房间号");
                    Scanner roomNo = new Scanner(System.in);
                    hotel.order(roomNo.nextInt());
                }else if(i == 3){
                    System.out.println("请输入要退的房间号");
                    Scanner roomNo = new Scanner(System.in);
                    hotel.out(roomNo.nextInt());
                }else if(i == 0){
                    System.out.println("谢谢使用本系统,欢迎下次再来");
                    return;
                }else if(i == 4){
                    System.out.println("正在使用中的房间:");
                    hotel.printFalse();
                }else{
                    System.out.println("输入有误,请重新输入");
                }
            }
    
        }
    }
    
    

Arrays工具类

常见的算法:
    排序算法:
        冒泡排序算法
        选择排序算法
    查找算法:
        二分法查找

    以上算法在以后的java实际开发中我们不需要使用的。因为java已经封装好了,直接调用就可以。以后面试时可能会碰到。
算法实际上在java中不需要精通,因为java中已经封装好了,要排序就调用方法就行。例如:java中提供了一个数组工具类:
    java.util.Arrays
        Arrays是一个工具类
        其中有一个sort方法,可以排序。静态方法,直接使用类名调用就可以。
  1. 简单的排序

    import java.util.Arrays;
    //使用一下SUN公司提供的数组工具类:java.util.arrays;
    public class ArraysText01 {
        public static void main(String[] args){
            int[] ints = {2,8,4,6,193,123,39};
    
            //工具类中的方法大部分都是静态的
            Arrays.sort(ints);
            //遍历输出
            for (int i = 0; i <ints.length ; i++) {
                System.out.println(ints[i]);//2 4 6 8 39 123 193
            }
        }
    }
    
    
  2. 冒泡排序算法

    /*
        冒泡排序算法
        1、每一次循环结束之后,都要找出最大的数据,放到参与比较的这堆数据的最右边。(冒出最大的那个气泡)
        2、核心:
            拿着左边的数字和右边的数字比对,当 左边 > 右边 的时候,交换位置。
    
        原始数据:
        3,2,7,6,8
        第一次循环:(最大的跑到最右边)
        2,3,7,6,8       3和2比较,2<3,所以2和3交换位置
        2,3,7,6,8       虽然不需要交换位置:但是3和7还是需要比较一次
        2,3,6,7,8       6<7 6和7交换位置
        2,3,6,7,8       虽然不需要交换位置:但是7和8还是需要比较一次
    
        经过第一次循环,此时剩下参与比较的数据:2,3,6,7
        第二次循环
        2,3,6,7         2和3比较,不需要交换位置
        2,3,6,7         3和6比较,不需要交换位置
        2,3,6,7         6和7比较,不需要交换位置
    
        经过第二次循环,此时剩下参与比较的数据:2,3,6
        第三次循环
        2,3,6       2和3比较,不需要交换位置
        2,3,6       3和6比较,不需要交换位置
    
        经过第三次循环,此时剩下参与比较的数据:2,3
        第四次循环
        2,3         2和3比较,不需要交换位置
    
    
        原始数据:9 8 10 7 6 0 11
        第一次循环:
        8 9 10 7 6 0 11     第1次比较后:交换
        8 9 10 7 6 0 11     第2次比较后:不交换
        8 9 7 10 6 0 11     第3次比较后:交换
        8 9 7 6 10 0 11     第4次比较后:交换
        8 9 7 6 0 10 11     第5次比较后:交换
        8 9 7 6 0 10 11     第6次比较后:不交换
        最终冒出的最大数据在右边:11
    
        经过第一次循环,此时剩下参与比较的数据:  8 9 7 6 0 10
        第二次循环
        8 9 7 6 0 10        第1次比较后:不交换
        8 7 9 6 0 10        第2次比较后:交换
        8 7 6 9 0 10        第3次比较后:交换
        8 7 6 0 9 10        第4次比较后:交换
        8 7 6 0 9 10        第5次比较后:不交换
        最终冒出的最大数据在右边:10
    
        经过第二次循环,此时剩下参与比较的数据:  8 7 6 0 9
        第三次循环
        7 8 6 0 9       第1次比较后:交换
        7 6 8 0 9       第2次比较后:交换
        7 6 0 8 9       第3次比较后:交换
        7 6 0 8 9       第4次比较后:不交换
        最后冒出的最大数据在右边:9
    
        经过第三次循环,此时剩下参与比较的数据:7 6 0 8
        第四次循环
        6 7 0 8     第1次比较后:交换
        6 0 7 8     第2次比较后:交换
        6 0 7 8     第3次比较后:不交换
        最后冒出的最大数据在右边:8
    
        经过第四次循环,此时剩下参与比较的数据:6 0 7
        第五次循环
        0 6 7   第1次比较后:交换
        0 6 7   第2次比较后:不交换
        最后冒出的最大数据在右边:7
    
        经过第五次循环,此时剩下参与比较的数据:0 6
        第六次循环
        0 6     第1次比较后:不交换
    
            //7条数据比6次
            //6条数据比5次
            //5条数据比4次
            //4条数据比3次
            //3条数据比2次
            //2条数据比1次
    
    
    
    
    
    
     */
    public class BubbleSort {
        public static void main(String[] args){
            //这是int类型的数组对象
    //        int[] arr = {3,2,7,6,8};
            int[] arr = {9,8,10,7,6,0,11};
    
            //经过冒泡排序算法对以上数组中元素进行排序
            //冒泡排序算法的核心是什么?
    
            //对arr数组中的七条数据进行冒泡排序
            /*
                数组中有七条数据,第一次循环7条数据要比较6次,第二次循环6条数据要比较5次,第三次循环5条数据要比较4次...第6次循环2条数据要比较1次
                意思是:最外层循环要循环6次,内层循环每经过一次循环要根据所要比较的数据相应减少一次。
                外层的是要控制需要进行6次循环比较,内层控制的是数组中数据的比较。
    
             */
            //查看循环几次
            int count = 0;
            for (int i = arr.length-1; i >0 ; i--) {
                //i刚开始是6,循环到1,刚好是循环了6次
                for (int j =0 ; j < i ; j++) {
                    //不管是否交换,只要循环一次,就加1;
                    count++;
                    //内层循环里,j < i,就是几条数据循环几条-1次,如有5条数据,就循环四次
                    //交换位置
                    if(arr[j] >arr[j+1]){
                        int temp ;
                        temp = arr[j];
                        arr[j] =arr[j+1];
                        arr[j+1] =temp;
                    }
                }
            }
            for (int i = 0; i <arr.length ; i++) {
                System.out.println(arr[i]);
            }
            System.out.println("共比较了"+count+"次");
    
        }
    }
    
  3. 选择排序:

    ​ 选择排序比冒泡排序的效率高,高在交换位置的次数上。选择排序的交换位置是有意义的

    ​ 循环一次,然后找出参加比较的这堆数据中最小的,拿着这个最小的值和最前面的数据交换位置。

    /*
        选择排序:每一次从 这堆参与比较的数据 当中找出 最小值
            拿着这个 最小值 和 参与比较的这堆数据中最前面的元素 交换位置
    
        选择排序比冒泡排序好在:每一次的交换位置都是有意义的。
    
        参与比较的数据:3 1 6 2 5       (这一堆参加比较的数据中最左边的元素下标是0)
        第一次循环之后的结果是:1 3 6 2 5
    
        参与比较的数据: 3 6 2 5        (这一堆参加比较的数据中最左边的元素下标是1)
        第二次循环之后的结果是:2 6 3 5
    
        参与比较的数据是: 6 3 5        (这一堆参加比较的数据中最左边的元素下标是2)
        第三次循环之后的结果是:3 6 5
    
        参与比较的数据是:6 5        (这一堆参加比较的数据中最左边的元素下标是3)
        第四次循环之后的结果是:5 6
    
        注意:5条数据,循环4次。
    
        关键点:选择排序中的关键在于:怎么找出一堆数据中最小的
            3 1 6 2 5
                假设:
                    第一个3是最小的
                    3和2比较,发现2更小,所以此时最小的是2
                    继续拿着2往下比对,2和6比较,2仍是最小的
                    继续拿着2往下比对,2和1比较,发现1更小,所以此时最小的是1
                    继续拿着1往下比对,1和5比较,1仍是最下的。
    
                    拿着1和最左边的3交换位置
    
            2 6 3 5
                假设:
                    第一个2是最小的
                    。。。
    
                6 3 5
                    假设6是最小的:
                    6和3比对,发现3更小,所以此时最小的是3
    
     */
    
    public class SelectSort {
        public static void main(String[] args){
            //int[] arr = {3,1,6,2,5};
            int[] arr = {9,8,10,7,6,0,11};
            //选择排序算法  5条数据循环4次
            //每次循环取出最小的值与第一个值交换(外层循环4次)
            //设置个变量,查看比较次数
            int count =0;
            //查看交换次数
            int count2 = 0;
            for (int i = 0; i <arr.length-1 ; i++) {
                //i的值是 0 1 2 3  ,正好是参加比较的这堆数据中 最左边那个元素的下标
                //假设起点i下标位置上的元素是最小的,把这个与所有的作比较,最后取出比这个小的
                int min = i;
                //比较的时候,把第一个值与所有的值比较一遍后取出最小的与第一个值交换
                for(int j = i+1 ; j < arr.length ;j++){//内层循环是:第一个值与所有的值相比较
                    count++;
                    if(arr[j] < arr[min]){
                        //假设i是最小的值后,如果j的比最下的还小,则把j设为最小
                        min = j;
                    }
                }
                //当i和min相等时,表示猜测是对的,
                //当i和min不相等时,表示猜测是错的,有比这个元素更小的元素,需要拿着这个更小的元素和最左边的元素交换位置
                if(min != i){
                    count2++;
                    //当最小的不是i时,最小的为min,
                    int middle = arr[i];    //第左手给中间
                    arr[i] = arr[min];      //把右手给左手
                    arr[min] = middle;      //中间(存放了左手)给右手
    
                }
            }
            for (int i = 0; i <arr.length ; i++) {
                System.out.println(arr[i]);     //1 2 3 5 6    //0 6 7 8 9 10 11
            }
    
            //冒泡排序和选择排序实际上比较的次数没有变,交换位置的次数变少了
            System.out.println("比较次数:"+count);
            System.out.println("交换次数:"+count2);
        }
    }
    
    

    结论:

    冒泡排序和选择排序实际上比较的次数没有变,但选择排序的交换位置的次数变少了
    
  4. 数组元素的查找

    挨着找:效率低

    /*
        数组的元素查找
            数组元素查找有两种方式:
                第一种方式:一个一个挨着找
                第二种方式:二分法查找法(算法),这个效率比较高。
     */
    public class ArraySearch {
        public static void main(String[] args) {
            //这个例子演示一下第一种方式
            int[] arr ={4,5,5,6,87,8};
            //如果有两个相同的元素,则返回的是第一个。因为是挨着找,找到后就结束了,不会再去找剩下的。
    
    
    /*      //找出87的下标,如果没有返回-1。
            //一个一个挨着找
            for(int i = 0; i < arr.length;i++){
                if(arr[i] == 87){
                    System.out.println("87的元素的下标为:"+i);
                    return;
                }
            }
            //程序执行到这里,表示没有87
            System.out.println("数组中不存在87这个元素");*/
    
        /*
            最好以上的程序封装一个方法,思考:传什么参数?返回什么值?
            传递的参数:第一个参数是数组,第二个参数是需要查找的元素。
            返回值:返回被查找的这个元素的下标。如果找不到返回-1。
         */
        int index = arraySearch(arr,5);
        System.out.println(index == -1 ?"该元素不存在":"该元素的下标是:"+index);
        }
    
        /**
         * 从数组中检索某个元素
         * @param arr   被检索的数组
         * @param element   被检索的元素
         * @return  返回大于等于0的数表示元素的下标,-1表示该元素不存在
         */
        public static int arraySearch(int[] arr, int element) {
            for(int i = 0 ; i < arr.length;i++){
                if(arr[i] == element){
                    return i;
                }
            }
            return -1;
        }
    }
    
  5. 二分法查找:

    第一:二分法查找建立在排序的基础之上。
    第二:二分法查找效率要高于“一个挨着一个”的这种查找方式
    第三:二分法查找原理
    	10(下标0) 23 56 89 100 111 222 235 500 600(下标9)   arr数组
    	
    	目标:找出600的下标
    		(0+9)/2 --------->4 (中间元素的下标)
    		
        arr[4] 这个元素就是中间元素:arr[4]是100.
        100 < 600
        说明被查找的元素在100的右边。那么此时开始下标变成:4+1.
        
        	(5+9) / 2 ---> 7(中间元素的下标)
        	arr[7]对应的是:235
        	235 < 600
        	说明被查找的元素在235的右边
        	
        开始下标又进行了转变:7 + 1
        	( 8 + 9 ) /2 ---> 8
        	arr[8] ---> 500
        	500 < 600
        	开始元素的下标又发生了变化:8+1
        	(9 + 9) / 2 --->9
        	arr[9] 是600,正好和600相等,此时找到了。
    	
    

    使用二分法进行查找

    /*
        1、数组工具类:自己写的,不是SUN的。
    
        2、二分法查找算法是基于排序的基础上的(没有排序的数据是无法查找的。)
    
        3、关于查找算法中的:二分法查找
            10(下标0) 11 12 13 14 15 16 17 18 19 20(下标10) arr数组
    
            通过二分法查找,找18这个元素的下标:
             (0 + 10)/2 ------>  中间元素的下标:5
            拿着中间这个元素和目标要查找的元素进行对比:
                中间元素是:arr[5]--> 15
                15 < 18(被查找的元素)
                被查找的元素18在目前中间元素15的右边。
                所以开始元素的下标从0变成5+1
    
            再重新计算一个中间元素的下标:
                开始下标: 5+1
                结束下标:10
                (6 + 10)/2  --> 8
    
            8下标对应的元素arr[8] 是18
                找到的中间元素正好和被查找的元素18相等,表示找到了:下标为8
    
            二分法查找的终止条件:一面折半,直到中间的按个元素恰好是被查找的元素。
    
            第一:二分法查找建立在排序的基础之上。
            第二:二分法查找效率要高于“一个挨着一个”的这种查找方式
            第三:二分法查找原理
                10(下标0) 23 56 89 100 111 222 235 500 600(下标9)   arr数组
    
                目标:找出600的下标
                    (0+9)/2 --------->4 (中间元素的下标)
    
                arr[4] 这个元素就是中间元素:arr[4]是100.
                100 < 600
                说明被查找的元素在100的右边。那么此时开始下标变成:4+1.
    
                    (5+9) / 2 ---> 7(中间元素的下标)
                    arr[7]对应的是:235
                    235 < 600
                    说明被查找的元素在235的右边
    
                开始下标又进行了转变:7 + 1
                    ( 8 + 9 ) /2 ---> 8
                    arr[8] ---> 500
                    500 < 600
                    开始元素的下标又发生了变化:8+1
                    (9 + 9) / 2 --->9
                    arr[9] 是600,正好和600相等,此时找到了。
    
                如果是在前半个里面,则元素下标-1,这个作为终止下标,起始下标不变。
    
     */
    public class ArrayUtil {
        public static void main(String[] args){
            int[] arr = {100,200,230,235,600,1000,2000,9999};
            //找出arr这个数组中200所在的下标
            //调用方法
            int index = binarySearch(arr,200);
            System.out.println(index == -1 ? "该元素不存在":"该元素的下标:"+index);
        }
    
        /**
         * 使用二分法从数组中查找元素的下标
         * @param arr   被查找的数组(这个必须是已经排序的)
         * @param dest  目标元素
         * @return
         */
        public static int binarySearch(int[] arr, int dest) {
            //开始下标
            int begin = 0;
            //结束下标
            int end =arr.length-1;
    
            //开始元素下标只要在结束元素下标的左边,就一直循环
            while(begin <= end){
    
                //中间元素下标
                int mid = (begin+end) / 2;
    
                if(arr[mid] == dest){
                    return mid;
                }else if(arr[mid] < dest){
                    //目标在中间元素的右边
                    //起始元素下标 = 中间元素+1
                    begin = mid + 1 ;//增
                }else{
                    //arr[mid] > dest
                    //目标在“中间”的左边,修改结束元素的下标
                    end = mid - 1 ;//减
                }
            }
            return -1;
        }
    }
    
    
  6. java.util.Arrays 工具类

    所有的方法都是静态的,直接使用类名调用。使用时要文档,不要死记硬背。

    主要使用的是两个方法:排序、二分法查找

    import java.util.Arrays;
    
    /*
        SUN公司已经为我们程序员写好了一个数组工具类
            java.util.Arrays
     */
    public class ArraysText02 {
        public static void main(String[] args) {
            //java.util.Arrays; 工具类中有哪些方法,我们开发的时候要参考API帮助文档
    
            int[] arr = {3,6,4,7,12,1,2,32,5,5};
            //排序
            Arrays.sort(arr);
            //输出
            for (int i = 0; i <arr.length ; i++) {
                System.out.println(arr[i]);
            }
            //二分法查找(建立在排序的基础上)
            int index = Arrays.binarySearch(arr,511);
            //输出的index如果是大于等于0的,就存在这个元素,如果小于0,则表示不存在
            System.out.println(index < 0 ? "该元素不存在":"该元素下标为:" + index);
            //如果有两个值是相同的,则碰到哪个就输出哪个元素的下标,跟原理有关。
        }
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32349.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【负荷预测、电价预测】基于神经网络的负荷预测和价格预测(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

Webpack DevServerExpress 中间件

前言 webpack-dev-server 底层是 express webpack-dev-middleware。 express是基础。 webpack-dev-middleware是中间件&#xff0c;以监听模式启动 webpack&#xff0c;将编译后的文件输出到内存&#xff08;使用fs-memory&#xff09;&#xff0c;沟通webpack的HRM&#xf…

机器学习之特征提取

Question Orientied:来自论文的一个学习点 Feature extraction 定义&#xff1a; 特征提取是指使用计算机提取图像中属于特征性的信息的方法及过程。 简言之 提取图像关键信息。 特征提取出来的结果叫特征向量。 进入主题之前 普及几个常识&#xff1a; 像素的英文名称:Pixe…

Flutter 完全手册

小册介绍 Flutter 作为一个跨平台的框架&#xff0c;其开发技术栈融合了 Native 和前端的技术&#xff0c;不仅涉及到了 Native&#xff08;Android、iOS &#xff09;的开发知识&#xff0c;又吸取了很多前端&#xff08;例如 React&#xff09;的技术理念和框架&#xff0c;并…

甘露糖-聚乙二醇-CY3 Cy3-PEG-mannose

甘露糖-聚乙二醇-CY3 Cy3-PEG-mannose 中文名称&#xff1a;甘露糖-荧光染料CY3 英文名称&#xff1a;mannose-Cyanine3 别称&#xff1a;CY3标记甘露糖&#xff0c;CY3-甘露糖 溶解性&#xff1a;溶于大部分有机溶剂&#xff0c;如&#xff1a;DCM、DMF、DMSO、THF等等。在…

业务数据分析-Excel数据透视表(四)

目录 1、什么是数据透视表 2、如何操作 3、数据透视表的优势 4、适用什么场景 5、使用前注意事项 1、什么是数据透视表 先来举个例子 看下面这段对话 下午5点30 boss&#xff1a;把这张表给我整理成如下格式&#xff0c;就是根据平台给我汇总一下销量和收入&#xff0c…

机械工程基础笔记整理

第一章 绪论 第一节 课程的特点 1. 综合性 本课结合了工程力学&#xff0c;机械工程材料&#xff0c;常用机构&#xff0c;支撑零部件&#xff0c;机械传动&#xff0c;液压传动&#xff0c;气压传动的相关知识。 2. 基础性 无论从事机械制造&#xff0c;还是使用研究机械&…

OpenCV图像处理——(实战)答题卡识别试卷

总目录 图像处理总目录←点击这里 二十、答题卡识别试卷 20.1、预处理 灰度图 输出灰度图高斯滤波去噪 gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred cv2.GaussianBlur(gray, (5, 5), 0)边缘检测 edged cv2.Canny(blurred, 75, 200)20.2、轮廓检测 找到原…

快速构建一个简单的对话+问答AI (上)

文章目录前言part0 资源准备基本功能语料停用词问答闲聊语料获取part01句的表达表达one-hot编码词嵌入大致原理实现简单版复杂版如何训练转换后的形状part02 循环神经网络RNNRNN投影图RNN是三维立体的LSTM&GRUpart03意图识别分词FastText分类FastText网络结构优化点构造Fas…

http请求走私漏洞原理,利用,检测,防护

目录 什么是请求走私 漏洞成因与常见类型 Keep-Alive&Pipeline CL&TE 常见走私类型 1.CL不为0 2.CL CL 3.CL TE 4.TE CL 5.TE TE 走私攻击应用实例&#xff08;漏洞利用&#xff09; 使用CL TE走私获取其他用户的请求、Cookie 2.泄露请求头重写请求实现未…

UE4贴图自适应屏幕大小

游戏开发中&#xff0c;不同屏幕下的分辨率不同&#xff0c;模型/物品被拉伸之后贴图也会随之拉伸。 如果需要在不同屏幕下面实现贴图真实大小不变&#xff08;以下简称为自适应&#xff09;&#xff0c;需要对UV进行缩放处理之后再取得对应贴图的颜色。 本文提供一种能够实现不…

为什么国外程序员的创造力比中国程序员强?

1川口耕介是个日本程序员&#xff0c;他曾在Sun公司从事Java、XML和Solaris相关的开发。2004年&#xff0c;他用Java写了叫做一个Hudson的开源工具&#xff0c;专门做持续集成&#xff08;CI&#xff09;。Hudson安装、配置、使用都非常方便&#xff0c;并且支持用插件的形式扩…

有求必应 | 听说这个管线排布,横竖都行?

大家好&#xff0c;今天还是被 yi 情反复拿捏的建模助手。 拿捏归拿捏&#xff0c;企微客服还是很认真得在给大家答疑解惑记bug&#xff0c;刚好有求知若渴的盆友问到管线排布这个角度&#xff0c;是否能有小数点&#xff0c;比如1.2&#xff0c;或者0.8。 对待此类问题&#x…

无线传感器网络:排队论(Queueing Theory)模型

文章目录The arrival ProcessQueueing SystemThe M/M/1 queueThe M/M/1/N queueReferences排队理论已被用于评估通信网络的性能很多年了。早在1917年&#xff0c;丹麦数学家 Erlang 就将该理论用于电话交换机的设计&#xff0c;并开创了现在著名的 Erlang-B 和 Erlang-C 公式&a…

DevData Talks | 知乎艾辉:从工具建设到运营,千人团队研发提效最佳实践

在千人级别的组织层级提升研发效能&#xff0c;是一种什么体验&#xff1f;可以确定的是&#xff0c;千人级组织的效能提升&#xff0c;并不是百人级团队的等比放大。 在数十人乃至小百人的团队&#xff0c;统一规范研发工具与流程的门槛相对较低&#xff0c;参与方也比较简单…

07 索引

1.索引 概述 1. 简介 索引是一种帮助数据库高效获取数据的数据结构&#xff1b;通过索引可以快速获取到符合条件的数据的内存地址&#xff0c;避免全表扫描 2. 索引的优缺点 优点&#xff1a; 可以快速地检索数据&#xff0c;降低数据IO成本通过索引可以对数据进行排序&…

jenkins 共用宿主机中的docker自动化部署

目录 第一节 jenkins 共用宿主机中的docker自动化部署 1.docker命令安装启动jenkins 2.查询jenkins内是否可以执行宿主机中的docker 第二节.jenkins 配置自动化部署 1.界面配置 1.配置mave 2.配置gitee 第三节 创建springboot多模块项目 1.相关配置 1.pom 2.编写docke…

【面试题】作用域和闭包

1. 作用域 作用域是指变量的合法使用范围。 例如下图中&#xff0c;函数fn3内定义的变量a3&#xff0c;无法在函数fn3以外的区域使用。 作用域分为全局作用域&#xff0c;函数作用域&#xff0c;块级作用域&#xff08;ES6新增&#xff09; 全局作用域&#xff1a;变量没有受…

HTML+CSS+JS个人网页设计期末课程大作业 web前端开发技术 web课程设计 网页规划与设计

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

MYSQL索引数据结构----B+树

索引数据结构的考量 我们在考虑数据结构的时候&#xff0c;应该首先要知道数据存放在哪里&#xff1f; 而MYSQL的数据是持久化的&#xff0c;所以其数据&#xff08;数据记录索引&#xff09;应该是保存在磁盘里面的。因此当我们要查询某条数据记录时&#xff0c;就会先从磁盘…