【Java数组算法17】

一、冒泡排序:找到最大数,然后摘出来,在找出第二大数摘出来,依次进行

举例了解原理:

int[] data = {3,1,6,2,5}

比较之前的数据:3,1,6,2,5     (比较的时候都是按照第一个数和第二个数进行比较,如果第一个数大于第二个数调换顺序、否则保持不变,第二个数和第三个数进行比较,依次类推)

第一轮:

1,3,6,2,5(第1个数和第2个数比较的结果)

1,3,6,2,5(第2个数和第3个数比较的结果)

1,3,2,6,5(第3个数和第4个数比较的结果)

1,3,2,5,6(第4个数和第5个数比较的结果)

比较完第1轮以后把最大的一个数(6)摘出来,进行第2轮的比较

第二轮原数据:1,3,2,5

第二轮:

1,3,2,5

1,2,3,5

1,2,3,5

比较完第2轮以后把最大的一个数(5)摘出来,进行第3轮的比较

第三轮原数据:1,3,2

第三轮:

1,3,2

1,2,3

比较完第3轮以后把最大的一个数(3)摘出来,进行第4轮的比较

第四轮原数据:1,2

第4轮:

1,2

通过上面的比较可以清楚的知道:data数组内有5个数,对比了4轮,10次

由此可以得出一个公式:轮数:5-1;次数:5*(5-1)/2=10。如果数组内有n个数,那么比较的轮数为:n-1,每一轮进行的次数:n-1-1,总共次数:n*(n-1)/2

所以冒泡排序有两个动作:进行了几轮,进行了几次

在程序上解决方法:

1、双层for循环,外层for循环控制轮数,内层for循环控制次数。

2、内层for语句通过if判断来进行具体的转换:

AB进行转换,先把A赋值给C,然后把B赋值给A,最后把C赋值给B

 

3、遍历数组,输出转换后的结果

package com.JavaStudy.studyArray0604;

/**
 * @Author wufq
 * @Date 2020/6/4 15:00
 * 冒泡排序
 */
public class BubbleShort01 {
    public static void main(String[] args){
        int[] data = {3,1,6,5,2};

        //双层for循环来进行排序
        for(int i=data.length-1;i>0;i--){ 

            for(int j =0;j<i;j++){

                if(data[j]>data[j+1]){
                    int temp = data[j];
                    data[j]= data[j+1];
                    data[j+1]=temp;
                }
            }
        }
        //遍历数组,输出结果
        for(int i=0;i<data.length;i++){
            System.out.print(data[i]+" ");
        }
    }
}
package com.JavaStudy.studyArray0604;

/**
 * @Author wufq
 * @Date 2020/6/4 16:29
 */
public class Data {
    public static void main(String[] args){
        int[] data = {3,1,6,5,2,7};

        //双层for循环来进行排序
        for(int i=1;i<=data.length-1;i++){

            for(int j =0;j<data.length-1;j++){

                if(data[j]>data[j+1]){
                    int temp = data[j];
                    data[j]= data[j+1];
                    data[j+1]=temp;
                }
            }
        }
        //遍历数组,输出结果
        for(int i=0;i<data.length;i++){
            System.out.print(data[i]+" ");
        }
    }
}

以上两段代码的结果是一样的,区别在于两层for循环,第一种的外层for循环是按照先第4轮-->第1轮,而内层for循环是在小于外层for循环数的基础上进行的次数的计算;第二种的外层for循环是按照先第1轮-->第4轮,而内层for循环是在小于数组长度-1(即:数组下标)的基础上进行次数的计算。所以不管按照那种方式原理都是一样的,即:外层循环控制轮数,内层循环控制次数。但是第二种计算的次数明显多于第一种,所以还是建议采用第一种方式进行排序

二、选择排序

原理:找出最小数然后与数组的第一个元素进行对比然后互换。所以内层for循环分两步:1、找到最小数的下标,2、最小数的下标与第一个元素的下标进行对比然后互换

举例了解原理:

int[] arr={3,1,5,7,4}

比较之前的数据:3,1,5,7,4    (第一轮把第一个数赋值给最小数,然后最小数依次进行比较,找到最小数取出来,第二轮把第二个数当做最小数,然后进行比较,找出第二个最小数,依次寻找。。。)

第一轮:

原数:3,1,5,7,4

对比后:1,3,5,7,4

第二轮:

原数:3,5,7,4

对比后:3,5,7,4

第三轮:

原数:5,7,4

对比后:4,7,5

第四轮:

原数:7,5

对比后:5,7

通过上面的比较可以清楚的知道:选择排序也是先确定几轮,然后每一轮找到最小数,并摘出来。

 

package com.JavaStudy.studyArray0604;

/**
 * @Author wufq
 * @Date 2020/6/4 17:02
 * 选择排序:找到最小数然后和数组的第一个元素进行对比
 */
public class SelectShort01 {
    public static void main(String[] args){
        int[]  arr={2,1,7,5,3,8};

        for(int i=0;i<arr.length-1;i++){

            //第一次循环都是和arr[i]元素交换位置,将剩余数据中的第一个元素看做最小元素
            int min = i;

            //这个循环负责找出最小元素的下标
            for(int j = i+1;j<arr.length;j++){
                if(arr[min]>arr[j]){
                    min = j;
                }
            }

            //一定要找出最小元素的下标
            //arr[min]和arr[i]交换位置
            if(min!=i){
                int temp = arr[min];
                arr[min] = arr[i];
                arr[i]=temp;
            }
        }

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

不管是冒泡排序还是选择排序,次数都是在轮的基础上进行的调换,所以内层循环时j都要在i控制的轮次里面进行次数的调换

如:冒泡排序:

for(int i=data.length-1;i>0;i--){ 
  for(int j =0;j<i;j++){

选择排序:

for(int i=0;i<arr.length-1;i++){

            for(int j = i+1;j<arr.length;j++){
 

 三、二分法根据下标查找数据元素

使用二分法查找算法在数组中查找某个元素,前提该数组已经排序

例如:int[] arr = {1,5,8,12,56,89,99}

算法:begin=0

end = 7

mid = (begin+end) /2

mid = 被查找元素  --->return mid

mid > 被查找元素  ---> end = mid-1

mid < 被查找元素  --->begin= mid +1

package com.JavaStudy.studyArray0608;

/**
 * @Author wufq
 * @Date 2020/6/8 11:22
 */
public class IndexArray0608 {

    public static void main(String[] args){
        int[] arr = {1,6,9,22,55,56,99};
        int index =myIndex(arr,100);
        System.out.println(index!=-1?"被查找的元素在arr数组中的下标是"+index:"被查找的元素不存在");
    }

    //myIndex方法两个元素,一个是arr数组,另外一个是需要查找的数
    public static int myIndex(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){
                begin= mid+1;
            }else if(arr[mid]>dest){
                end= mid -1;
            }
        }

        return -1;
    }
}
======执行结果=====
被查找的元素在arr数组中的下标是4

四、数组的工具类:Arrays类 --->java.until.Arrays

常用方法:

sort方法:可以进行排序

binarySearch方法:可以进行二分法排序查找

package com.JavaStudy.studyArray0608;

import java.util.Arrays;

/**
 * @Author wufq
 * @Date 2020/6/8 16:20
 Arrays工具类,可以进行数组的查询和排序
 */
public class ArraysTest01 {
    public static void main(String[] args){
        int[] arr = {1,7,9,2,6,3};
        //Arrays类里面sort方法进行排序
        Arrays.sort(arr);

        //逆向遍历数组
        for(int j=arr.length-1;j>=0;j--){
            System.out.print(arr[j]+" ");
        }

        System.out.println("\n");

        //正向遍历数组
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }

        System.out.println("\n");

        //Arrays类中的binarySearch方法可以进行二分法查找数组下标
        int index = Arrays.binarySearch(arr,3);
        System.out.println("arr数组的下标:"+index);
    }
}
=====执行结果=====
9 7 6 3 2 1 

1 2 3 6 7 9 

arr数组的下标:2

 五、对一个字符串中的数值进行从小到大的排序

"20 78 9 -7 88 36 29"

思路:

1、排序我很熟,但是只熟int

2、如何获取到这些字符串中这些需要排序的数值

  发现这些字符串都是用空格来对数值进行分隔的,

  所以我们就想到用字符串对象的切割方法将大串切割成小串

3、数值最终变成小字符串,但是怎么变成int类型呢

字符串-->基本类型可以使用包装类

package com.JavaStudy01;

import java.util.Arrays;

/**
 * @Author wufq
 * @Date 2020/7/29 10:57
 * 字符串"20 6 -1 50 9 7"  排序
 * 思路:
 * 之前排序的都是int类型,但是没有把string类型的数值排序过
 * 1、发现字符串是由空格进行分隔的,所以需要把大的字符串切割成小字符串
 * 2、小字符串转换成int类型进行排序
 * 3、排序后在转换成字符串
 */
public class WrapperTest {
    private static final String SPACE_SEPARATOR = " "; //大小写切换快捷方式:⌘⇧U

    public static void main(String[] args){
        String numstr = "20 6 -1 50 9 7";
        System.out.println(numstr);//转换前
        numstr = toStringNum(numstr);  //自定义了一个方法名,但是想自动转换成方法,快捷方式为:option+enter/alt+enter
        System.out.print(numstr);//转换后

    }

    private static String toStringNum(String numstr) {


/*   String [] str_num = numstr.split(" ");   --> 想把此段代码变成一个方法,需要在idea内进行重构:全部选中右键->Refactor->Extract->Method
     或者用快捷方式option+command+M
*/
        //1、将字符串变成字符串数组
        String[] str_num = stringToArray(numstr);
        //2、将字符串数组变成int数组
        int [] int_num = toIntArray(str_num);
        //3、对int数组进行排序
        mySortArray(int_num);
        //4、将排序后的int数组,转换成字符串
        String temp = arrayToString(int_num);

        return temp;
    }

    private static String arrayToString(int[] int_num) {
        StringBuilder sb = new StringBuilder();
        for(int j=0;j<int_num.length;j++){
            if(j!=int_num.length-1){
                sb.append(int_num[j]+SPACE_SEPARATOR);
            }else {
                sb.append(int_num[j]);
            }
        }
        return sb.toString();
    }

    private static void mySortArray(int[] int_num) {
        Arrays.sort(int_num);
    }

    public static int[] toIntArray(String[] str_num) {
        int[] arr = new int[str_num.length];
        for(int i=0;i<arr.length;i++){
             arr[i]= Integer.parseInt(str_num[i]);
        }
        return arr;
    }

    public static String[] stringToArray(String numstr) {
        String [] str_num = numstr.split(SPACE_SEPARATOR);
        return str_num;
    }


}
======执行结果======
转换前:20 6 -1 50 9 7
转换后:-1 6 7 9 20 5

 如果字符串是这样类型的:String str = "312347890",排序的思路是不变的,区别在于先把String类型转换成char类型的数组,然后把char类型的数组转换成String类型,然后在转换成int类型的数组

package com.wufq.demo.demo8;

import java.util.Arrays;

/**
 * @Description  排序
 * @Author wufq
 * @Version
 * @Date 2021/5/18 14:06
 */
public class Sort_test {

    public static void main(String[] args){
        String str= "312347890";
        String s=Str_sort(str);
        System.out.println(s);

    }

    private static String Str_sort(String str) {

        char[] chars=strToChar(str);

        int[] i = charToInt(chars);

        arraySort(i);

        String ss = intToStr(i);

        return ss;
    }

    private static String intToStr(int[] tt) {
        StringBuilder sb = new StringBuilder();

        for(int i=0;i<tt.length;i++){
            sb.append(tt[i]+" ");
        }

        return sb.toString();
    }

    private static void arraySort(int[] i) {
        Arrays.sort(i);
    }

    private static int[] charToInt(char[] chars) {
        int[] tt = new int[chars.length];
        for(int i=0;i<tt.length;i++){
            tt[i]=Integer.parseInt(String.valueOf(chars[i]));
        }

        return tt;
    }

    private static char[] strToChar(String str) {
        char[] chars = str.toCharArray();
        return chars;
    }

}

知识补充:

String、StringBuffer和StringBuilder的区别:

String类时不可变类,定义以后所占的内容空间不能修改

StringBuffer和StringBuilder功能差不多,都是代表了字符序列可变的字符串,

StringBuffer和StringBuilder创建以后,提供append(),insert(),reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列,一旦生成想要的字符串,就可以通过toString()方法将其转换成一个String对象

 

两者之间的曲边:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。

参考文章:https://blog.csdn.net/csxypr/article/details/92378336

posted @ 2020-06-04 15:47  尘封~~  阅读(148)  评论(0编辑  收藏  举报