一维数组的统计,冒泡排序,二维数组的声明、使用和遍历(七)

225 阅读6分钟

数组的算法

1、关于数组元素的统计

(1)求累计和

(2)求平均值

(3)统计偶数的个数

(4)统计素数的个数

(5)统计xx的个数

冒泡排序:是最基础的最经典排序,所有编程人员都要学习的第一个排序算法。

但是不是说它是效率最高。

关键描述:

(1)通过相邻元素的比较,如果相邻的前后元素不符合最终要的顺序,就交换 例如:我们要实现从小到大, {4,5,2,1,6} 相邻元素, 4,5 满足先小后大,不交换 相邻元素, 5,2 不满足先小后大,交换

(2)每一轮只能确定一个元素到达正确的位置 方案一,把大的往后移动,每一轮“大”沉到“底”(本轮参与元素的最后) 方案二,把小的往前移动,每一轮“小”冒到“顶” (本轮参与元素的第一个)

​ 详细描述:arr {4,5,2,1,6} 方案一的过程

第一轮:

​ 第1次,arr[0]<arr[1]比较,就是4<5比较,成立,不交换

​ 第2次,arr[1]<arr[2]比较,就是5<2比较,不成立,交换 {4,2,5,1,6}

​ 第3次,arr[2]<arr[3]比较,就是5<1比较,不成立,交换 {4,2,1,5,6}

​ 第4次,arr[3]<arr[4]比较,就是5<6比较,成立,不交换

​ 第一轮结果:6到达正确位置 {4,2,1,5,6}

第二轮:

​ 第1次,arr[0]<arr[1]比较,就是4<2比较,不成立,交换 {2,4,1,5,6}

​ 第2次,arr[1]<arr[2]比较,就是4<1比较,不成立,交换 {2,1,4,5,6}

​ 第3次,arr[2]<arr[3]比较,就是4<5比较,成立,不交换

​ 第二轮结果:5到达正确位置 {2,1,4,5,6}

第三轮:

​ 第1次,arr[0]<arr[1]比较,就是2<1比较,不成立,交换 {1,2,4,5,6}

​ 第2次,arr[1]<arr[2]比较,就是2<4比较,成立,不交换

第三轮结果:4到达正确位置 {1,2,4,5,6}

第四轮:

​ 第1次,arr[0]<arr[1]比较,就是1<2比较,成立,不交换

5个元素比较4轮,因为每一轮只能确定一个元素的正确位置。

如果m个元素,一共要比较m-1轮。

每一轮比较的次数递减。因为每一轮需要参与比较的元素依次减少。

public class TestBubbleSort {
    public static void main(String[] args) {
        int[] arr =  {4,5,2,1,6};

        //冒泡排序,从小到大
        //外循环控制一共比较几轮
        /*
        arr.length是5, i=1,i<arr.length, i<5
        i=1,2,3,4
         */
        for(int i=1; i<arr.length; i++){
            //内循环控制每一轮比较的次数
            /*
            本题:
            当i=1,比较4次,j=0,1,2,3  j<4
                   arr[0]与arr[1]
                   arr[1]与arr[2]
                   arr[2]与arr[3]
                   arr[3]与arr[4]
                   arr[j]与arr[j+1]
            当i=2,比较3次,j=0,1,2    j<3
                   arr[0]与arr[1]
                   arr[1]与arr[2]
                   arr[2]与arr[3]
            当i=3,比较2次,j=0,1      j<2
                   arr[0]与arr[1]
                   arr[1]与arr[2]
            当i=4,比较1次,j=0        j<1
                   arr[0]与arr[1]
             */
            for(int j=0; j<arr.length - 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] + " ");
        }
        System.out.println();
    }
}

方案二,把小的往前移动,每一轮“小”冒到“顶” (本轮参与元素的第一个)

详细描述:arr {4,5,2,1,6} 方案二的过程

第1轮:

第1次:arr[4]<arr[3]比较,6<1比较,不成立,不换

第2次:arr[3]<arr[2]比较,1<2比较,成立,交换 {4,5,1,2,6}

第3次:arr[2]<arr[1]比较,1<5比较,成立,交换 {4,1,5,2,6}

第4次:arr[1]<arr[0]比较,1<4比较,成立,交换 {1,4,5,2,6}

第一轮的结果,1到达正确位置

第2轮:

第1次:arr[4]<arr[3]比较,6<2比较,不成立,不换

第2次:arr[3]<arr[2]比较,2<5比较,成立,交换 {1,4,2,5,6}

第3次:arr[2]<arr[1]比较,2<4比较,成立,交换 {1,2,4,5,6}

第3轮:

第1次:arr[4]<arr[3]比较,6<5比较,不成立,不换

第2次:arr[3]<arr[2]比较,5<4比较,不成立,不换

第4轮:

第1次:arr[4]<arr[3]比较,6<5比较,不成立,不换

public class TestBubbleSort2 {
    public static void main(String[] args) {
        int[] arr =  {4,5,2,1,6};

        //外循环控制轮数
        for(int i=1; i<arr.length; i++){
            //内循环控制每一轮的次数
            /*
            当i=1, j=4,3,2,1     j>=i
                arr[4]与arr[3]
                arr[3]与arr[2]
                arr[2]与arr[1]
                arr[1]与arr[0]
                arr[j]<arr[j-1]
             当i=2, j=4,3,2
                arr[4]与arr[3]
                arr[3]与arr[2]
                arr[2]与arr[1]
             当i=3, j=4,3
                arr[4]与arr[3]
                arr[3]与arr[2]
             当i=4, j=4
                arr[4]与arr[3]
             */
            for(int j=arr.length-1; j>=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] + " ");
        }
        System.out.println();
    }
}

冒泡排序:优化 当我们某一轮比较完,数组已经有序了,考虑后面就可以不再继续比较了。

思路:如何确定数组是有序的? 当我们某一轮比较下来,发现没有任何一次交换,说明数组已经是有序了。

显示一下每一次比较完后的结果?

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

        //方案一:从前往后比较,大的往右移动
        for(int i=1; i<arr.length; i++){
            boolean flag = true;//假设数组已经是有序了
            System.out.println("第"+ i + "轮:");
            for(int j=0; j<arr.length-i; j++){
                if(arr[j] > arr[j+1]){
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1]= temp;
                    flag = false;//一旦发生交换,说明本轮仍然有元素需要调整位置,说明数组还没有确定顺序
                }
                //位置①每一次比较完的结果
                System.out.print("第" + (j+1) + "次比较:");
                for(int k=0; k<arr.length; k++){
                    System.out.print(arr[k] + " ");
                }
                System.out.println();
            }
            //位置②每一轮的结果
            if(flag){
                break;
            }
        }
        //位置③所有元素排序完的结果
    }
}

二维数组

二维数组的声明

package com.atguigu.two;

/*
1、认识二维数组
一维、二维数组,理论上可以有三维、思维数组。但是实际中到二维数组就够了。

一维数组:[]     一组数据
            {1,2,5,6,7}
二维数组:[][]   多组数组,
            {{1,2,5,6,7}
            {11,24,5}
            {50,2,55,6,75,78}}

2、如何声明二维数组
    元素的数据类型[][] 数组名;
 */
public class TestArray {
    public static void main(String[] args) {
        //存int的二维数组
        int[][] arr;

        //存储String的二维数组
        String[][] strings;


        /*
        数组的写法:(了解)
         */
        //一维数组
        int[] arr1;//标准写法
        int arr2[]; //非标准写法

        //二维数组
        int[][] arr3;//标准写法
        int arr4[][];//非标准写法
        int[] arr5[];//非标准写法

        //面试题
        int[] x , y[];
        //x和y分别是一维还是二维数组
        //答案:x是一维数组,y是二维数组
    }
}

二维数组的初始化

package com.atguigu.two;

/*
3、静态初始化:
直接指定行数以及每一行的元素的个数和值。
行数根据{}里面的{}的个数决定。

4、动态初始化
写法一:每一行的列数是相同的,即每一行的元素个数是相同
    元素的数据类型[][] 数组名 = new 元素的数据类型[行数][列数];
写法二:每一行的列数是不同的,或不确定
    元素的数据类型[][] 数组名 = new 元素的数据类型[行数][];
      还需要指定每一行的列数,即每一行元素的个数。
      数组名[行下标] = new 元素的数据类型[该行元素的总个数,或行长度];
 */
public class TestInitArray {
    public static void main(String[] args) {
        int[][] arr1 = {{1,2,3,4,5},{6,7,8},{9,10,11,12,13}};

        int[][] arr2 = new int[3][5];
        //有3行,每一行有5个元素
/*        {
            {0,0,0,0,0},
            {0,0,0,0,0},
            {0,0,0,0,0}
        }*/

        int[][] arr3 = new int[3][];
        //有3行
        //每一行有几个元素不清楚
/*        {
            null,
            null,
            null
        }
        如果此时把int[]看成一个整体,即是一维数组类型。 int[]是一个数据类型。
        int[][] arr3;就可以看成元素类型是int[]的一维数组。
        int[][] arr3 = new int[3][];  可以看成:  int[][] arr3 = new int[][3];
                                        等价于声明了一个一维数组,元素类型是int[],长度是3
                                        如果此时访问第一个元素, arr3[0]
        */
        System.out.println(arr3[0]);//null , 此时把int[]看成数据类型,int[]是引用数据类型,arr3这个数组元素的默认值是null

        //第1行有5个元素
        arr3[0] = new int[5]; //左边的[0]表示行下标,右边[5]表示该行有5个元素
        //第2行有3个元素
        arr3[1] = new int[3];
        //第3行有4个元素
        arr3[2] = new int[4];
        /*
        arr3到这里为止
        {
            {0,0,0,0,0},
            {0,0,0},
            {0,0,0,0}
        }
         */
    }
}

二维数组的使用

package com.atguigu.two;

/*
5、使用数组
(1)获取二维数组的总行数
  二维数组名.length

(2)获取二维数组某一行
    第1行:二维数组名[0]
    第2行:二维数组名[1]
    ...

    总结:二维数组名[行下标]
    行下标的范围[0, 二维数组名.length-1]
 (3)获取某一行的长度,或者某一行的元素个数
        第1行:二维数组名[0].length   把一行看成一个一维数组
        第2行:二维数组名[1].length   把一行看成一个一维数组
        。。。
    总结:二维数组名[行下标].length

 (4)获取其中一个元素
    int[][] arr = {{1,2,3,4,5},{6,7,8},{9,10,11,12,13}};
    假设获取8,先确定它属于{6,7,8},arr[1]行,然后确定它第3个元素,arr[1][2]

    总结:二维数组名[行下标][列下标]
 */
public class TestUseArray {
    public static void main(String[] args) {
        int[][] arr = {{1,2,3,4,5},{6,7,8},{9,10,11,12,13}};

        System.out.println("总行数:" + arr.length);

        System.out.println("二维数组名:" + arr);//[[I@4554617c
        //[[:表示二维数组,I表示int类型,@4554617c本质是对象的hashCode值,可以看成是地址值

        System.out.println("第1行:" + arr[0]);//[I@74a14482
            //[:一维数组,I表示int类型,@74a14482本质是对象的hashCode值,可以看成是地址值
            //arr1[0]存储的是{1,2,3,4,5}组数据的首地址
        System.out.println("第2行:" + arr[1]);//[I@1540e19d
        System.out.println("第3行:" + arr[2]);//[I@677327b6

        System.out.println("--------------------");
        System.out.println("第1行的元素个数:" + arr[0].length);
        System.out.println("第2行的元素个数:" + arr[1].length);
        System.out.println("第3行的元素个数:" + arr[2].length);

        System.out.println("使用for循环遍历每一行的长度:");
        for (int i=0; i<arr.length; i++){//arr1.length:总行数
            System.out.println("第" + (i+1) +"行的长度:" + arr[i].length);//arr1[i].length某一行的长度
        }

        System.out.println("--------------------");
        System.out.println("第1行的第1个元素:" + arr[0][0]);
        System.out.println("第1行的第2个元素:" + arr[0][1]);
        System.out.println("第3行的第2个元素:" + arr[2][1]);
    }
}

二维数组的遍历

package com.atguigu.two;

/*
6、二维数组的遍历
    for(int i=0; i<二维数组名.length; i++){
        for(int j=0; j<二维数组名[i].length; j++){
            元素:二维数组名[i][j]
        }
    }
 */
public class TestIterate {
    public static void main(String[] args) {
        int[][] arr = {{1,2,3,4,5},{6,7,8},{9,10,11,12,13}};

        //外循环控制行
        for (int i=0; i<arr.length; i++){
            //内循环遍历每一行的元素
            for(int j=0; j<arr[i].length; j++){
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
    }
}