Java学习笔记--数组常见算法:数组翻转,冒泡排序,二分查找

一,数组翻转

1.概述:数组对称索引位置上的元素互换,最大值数组序号是数组长度减一

创建跳板temp,进行min和max的互换,然后min自增,max自减,当min>=max的时候停止互换,代表到中间值

用代码实现

java 复制代码
public class Demo01Reverse {
    public static void main(String[] args) {
        //定义一个静态数组 
        int arr [] ={1,2,3,4,5,6,7};
        for(int min=0,max = arr.length-1;min<max;min++,max--){
            //进行换位
            int temp = arr[min];
            arr[min]= arr[max];
            arr[max]= temp;

        }


        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
    }
}

二,冒泡排序

数组的排序,是将数组中的元素按照大小进行排序,默认都是以升序的形式进行排序,数组排序的方法很多,我们讲解的是数组的冒泡排序。

排序,都要进行数组 元素大小的比较,再进行位置的交换。冒泡排序法是采用数组中相邻元素进行比较换位。

arr[i](前一个元素) arr[i+1](后一个元素)

比如以下数组

5 4 3 2 1

进行0,1号位的数字比较

4 5 3 2 1

然后又进行1,2号位的数字比较

4 3 5 2 1

然后2,3号位比较

4 3 2 5 1

最后3,4号位比较

4 3 2 1 5

实现位置的交换依然和前面数组翻转一样,创建一个跳板temp进行交换

代码实现

首先,定义数组

java 复制代码
public class Demo02Bubble {
    public static void main(String[] args) {
        int[] arr = {5,4,3,2,1};

进行第一轮冒泡

java 复制代码
/* 第一圈 */
        for (int i = 0; i < arr.length; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] = arr [i+1];
                arr[i+1] = temp;

            }
        }

测试,出现警告

这是为什么呢

其实是循环的时候突破了数组的最大序号

因为arr.length就等于5,所以i能取到的最大值是4,所以i+1=5,突破了最大限制

改为arr.length-1

成功,然后进行第二圈

java 复制代码
//第二圈
        for (int i = 0; i < arr.length-1; i++) {
             if(arr[i]>arr[i+1]){
                 int temp = arr[i];
                 arr[i] = arr [i+1];
                 arr[i+1] = temp;

             }
         }

第二圈代码和第一圈一样,也没问题,但也和第一圈一样比较了4次,但我们可以不必做这个重复功,因为第一次比较完了一个数,所以我们可以减去一次循环来表示可以少比较的次数,所以可以写成arr.length-1-1,最后面减的这个数可以看成是前面冒泡过的数的个数(圈数)

java 复制代码
//第二圈
        for (int i = 0; i < arr.length-1-1; i++) {
             if(arr[i]>arr[i+1]){
                 int temp = arr[i];
                 arr[i] = arr [i+1];
                 arr[i+1] = temp;

             }
         }

现在进行第三圈第四圈,同样我们减去前面冒泡过的数的个数

java 复制代码
//第三圈

        for (int i = 0; i < arr.length-1-2; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] = arr [i+1];
                arr[i+1] = temp;

            }
        }

//第四圈
        for (int i = 0; i < arr.length-1-3; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] = arr [i+1];
                arr[i+1] = temp;

            }
        }

运行结果

但我们可以再进行优化,这几圈的变化非常细微,只有一个数一个位置在变

如果最后面减的数是前面的圈数的话,那也就等于i啊,我们可以再在外面套一层循环,利用自加i来代替这几圈唯一变的减数

java 复制代码
/*
外层循环代表比较了几圈
           n-1圈
*/
        for (int j = 0; j < arr.length-1; j++) {
            for (int i = 0; i < arr.length-1-j; i++) {
            /*
              内层循环代表每一圈比较的次数
              每圈都少比较一次
            */
                if(arr[i]>arr[i+1]){
                    int temp = arr[i];
                    arr[i] = arr [i+1];
                    arr[i+1] = temp;

                }
            }
        }

由此而来,化繁为简,减小了时间,空间复杂度

完整代码如下

java 复制代码
public class Demo02Bubble {
    public static void main(String[] args) {
        int[] arr = {5,4,3,2,1};


        /*
           第一圈
             越界原因:当i变化到4的时候-> arr[4]>arr[5] -> 直接操作了5索引,所以越界了
             越界解决:我们可以让arr.length-1
                     如果arr.length-1-> 比较就是i<4 -> 此时i最大可以变化到3
                     当i变化到3时 -> arr[3]>arr[4] -> 正好是最后两个元素进行比较
         */
        for (int i = 0; i < arr.length-1-0; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] = arr [i+1];
                arr[i+1] = temp;

            }
        }

        
        //第二圈
        /*for (int i = 0; i < arr.length-1-1; i++) {
             if(arr[i]>arr[i+1]){
                 int temp = arr[i];
                 arr[i] = arr [i+1];
                 arr[i+1] = temp;

             }
         }*/
        //第三圈


        /*for (int i = 0; i < arr.length-1-2; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] = arr [i+1];
                arr[i+1] = temp;

            }
        }*/

        //第四圈
        /*for (int i = 0; i < arr.length-1-3; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] = arr [i+1];
                arr[i+1] = temp;

            }
        }*/


        /*
           外层循环代表比较了几圈
           n-1圈
         */
        for (int j = 0; j < arr.length-1; j++) {
            for (int i = 0; i < arr.length-1-j; i++) {
                /*
              内层循环代表每一圈比较的次数
              每圈都少比较一次
             */
                if(arr[i]>arr[i+1]){
                    int temp = arr[i];
                    arr[i] = arr [i+1];
                    arr[i+1] = temp;

                }
            }
        }


        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
    }
}

三,二分查找(一尺之锤,日取其半,万世不竭)

1.前提:数组中的数据必须是有序的

2.查询思想:

a.老式查询:遍历数组,一个一个比较 -> 查询效率慢

b.二分查找:每次找中间索引对应的元素进行比较查询(每一次查询少一半数据)

首先,因为min和max会因为查找数所在数组的位置不同而改变所以不能定义min就是arr[0]或max就是arr[8],min默认为0,max为arr.length-1,mid就是二者取中。

key为查询数,是指想查的数组中的数,查询出的是数组序数代表 含的数。

前提:当min<=max时

当查询数大于或小于数组序数上所代表的数时,通过移动min和max直接排掉一半的数,来不断的锁定范围,直到找到查询数所在的位置(这个方法很像一尺之锤,日取其半,万世不竭,不过是有目标的取),当查询数等于数组序数上所代表的数时,停止查找,返回序数表示找到了。

当然还有特殊情况,就是查询数不存在在数组中,那么当min>max时,就不找了,返回-1表示找不到。

代码实现

java 复制代码
public static int binary(int[] arr,int data){
        //定义三个变量,分别代表最大索引,最小索引,中间索引
        int min = 0;
        int max = arr.length-1;
        int mid = 0;
        //查找
        while (min<=max){
            mid = (min+max)/2;
            if(data>arr[mid]){
                min = mid+1;
            }else if(data<arr[mid]){
                max = mid-1;
            }else{
                return mid;
            }
        }

        return -1;

    }

我们发现代码实现和理论方法步骤不同,没有在一开始表示mid = (min+max)/2,因为要循环的算中间索引,在一进入循环时,在while(外层循环)内,再进行计算。

在main函数内调用方法进行输出,完整代码如下

java 复制代码
public class Demo03Binary {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7,8,9};
        int index = binary(arr, 7);
        System.out.println(index);

    }

    public static int binary(int[] arr,int data){
        //定义三个变量,分别代表最大索引,最小索引,中间索引
        int min = 0;
        int max = arr.length-1;
        int mid = 0;
        //查找
        while (min<=max){
            mid = (min+max)/2;
            if(data>arr[mid]){
                min = mid+1;
            }else if(data<arr[mid]){
                max = mid-1;
            }else{
                return mid;
            }
        }

        return -1;

    }
}

输入7

相关推荐
雯0609~3 分钟前
c#:winform调用bartender实现打印(学习整理笔记)
开发语言·c#
C++忠实粉丝4 分钟前
计算机网络socket编程(5)_TCP网络编程实现echo_server
网络·c++·网络协议·tcp/ip·计算机网络·算法
2301_7752811940 分钟前
当日本人说「お疲れ様」时,该怎么回?柯桥日语培训零基础学习
学习
kim565941 分钟前
excel版数独游戏(已完成)
算法·游戏·excel·数独
cv君1 小时前
【AI最前线】DP双像素sensor相关的AI算法全集:深度估计、图像去模糊去雨去雾恢复、图像重建、自动对焦
算法
E___V___E1 小时前
CSAPP学习
学习
胜天半子_王二_王半仙1 小时前
c++源码阅读__smart_ptr__正文阅读
开发语言·c++·开源
Ocean☾1 小时前
C语言-详细讲解-P1217 [USACO1.5] 回文质数 Prime Palindromes
c语言·数据结构·算法
沐泽Mu1 小时前
嵌入式学习-C嘎嘎-Day08
开发语言·c++·算法
Non importa1 小时前
汉诺塔(hanio)--C语言函数递归
c语言·开发语言·算法·学习方法