Java学习笔记——day09 排序算法

StringBuffer类

线程安全效率低

StringBuilder类

线程安全效率高

是一个长度可变的字符序列容器,那么使用它进行拼接,比+=拼接较好;

  • 构造方法

    • StringBuffer();

      • capacity(); 获取容量
      • append(); 往字符串缓冲区中添加内容。返回的还是容器本身;
      • insert(); 在指定索引处插入内容;返回的还是容器本身;
      • delete(); 根据起始索引和终止索引删除容器内一段字符;含头不含尾;返回的还是容器本身;
      • deleteCharAt(); 根据索引删除容器内某个字符;返回的还是容器本身;
      • replace(起始字符索引,终止字符索引,替换内容);替换功能,把起始索引和终止索引中间的内容,替换成一个新的内容;返回还是容器本身;
      • reverse(); 翻转容器中的内容;返回的还是容器本身;
      • subString(); 返回值是String类型;
    • StringBuffer(int capacity);

      当你超过容量后,会自动扩容;

    • String–>StringBuffer

      • StringBuffer sb = new StringBuffer(str);
      • StringBuffer sb = new StringBuffer().append(str);
    • StringBufferr---->String

      • String str = sb.toString();
  • 基本类型作为参数传递,值传递,形参改变不影响实参 String符合值传递特点

  • 引用类型传递,形参改变会影响实参

排序

  • 数组排序:把数组中的元素,通过比较移位和替换,使之变成一个有序序列;

    • 冒泡排序法:

      • 原理:数组元素两两比较,大的往后放,经过一轮比较后,最大的元素会出现在最后面;如此往复;

      • 代码:

        import java.util.Arrays;
        
        public class Test1 {
            public static void main(String[] args){
                //冒泡排序法
                int[] arr = {11, 23, 4443, 2, 545, 213};
        
                //外层控制循环次数,判断冒泡排序要走几轮
                for (int j = 0; j < arr.length-1; j++) {
                    //内层控制数组元素交换,每次循环结束都会将最大值排在末尾
                    for (int i = 0; i < arr.length-1-j; i++) {
                        int temp; //定义一个临时变量,用来做交换使用;
                        if(arr[i] > arr[i + 1]){
                            temp = arr[i];
                            arr[i] = arr[i + 1];
                            arr[i + 1] = temp;
                        }
                    }
                }
                System.out.println(Arrays.toString(arr));  //数组遍历
        
            }
        }
        
    • 选择排序法:

      • 原理:每次拿一个元素和后面所有的元素挨个比较,小的往前放,经过一轮比较后,最小的元素会出现最前面,如此往复,整个数组就排好序;

      • 代码:

        import java.util.Arrays;
        
        public class Test2 {
            public static void main(String[] args) {
                //选择排序法
                int[] arr = {11, 23, 4443, 2, 545, 213};
        
                //外层控制循环次数,index表示数组的下表索引
                for (int index = 0; index < arr.length - 1; index++) {
        
                    //内层控制元素比较于与交换,从1开始是因为第一个数字不和自己比较,
                    // i<arr.length而不是-1是因为要和最后一个比较
                    for (int i = 1 + index; i < arr.length ; i++) {
                        int temp;//定义一个临时变量,用来数据交换
                        if(arr[index] > arr[i]) {
                            temp = arr[index];
                            arr[index] = arr[i];
                            arr[i] = temp;
                        }
                    }
                }
                //数组遍历
                System.out.println(Arrays.toString(arr));
            }
        }
        
    • 直接插入排序法:

      • 原理:每次将后面一个元素插入到之前的一个有序序列中,使之仍保持有序;

      • 代码:

        • 内层为while

          import java.util.Arrays;
          
          public class Test4 {
              public static void main(String[] args) {
                  //直接排序法
                  int[] arr = {11, 23, 4443, 2, 545, 213};
                  //外层控制循环次数
                  for (int i = 1; i < arr.length; i++) {
                      int temp; //定义一个临时变量,用来交换
                      int j = i; //为了避免使用i导致内外层冲突,一边i++,一边i--影响程序进程;
                      //内层控制比较;如果当前的值比之前的值小,那么往前移;并且索引小于0就不进行比较
                      while(j > 0 && arr[j] < arr[j-1]){
                          temp  = arr[j-1];
                          arr[j-1] = arr[j];
                          arr[j] = temp;
                          j--;//当前元素和前一个元素比较之后,若前边还有元素,则继续与之前元素比较
                      }
                  }
                  System.out.println(Arrays.toString(arr));
              }
          }
          
        • 内层为for

          import java.util.Arrays;
          
          public class Test3 {
              public static void main(String[] args) {
                  //直接排序法 for循环
                  int[] arr = {11, 23, 4443, 2, 545, 213};
                  //外层控制循环次数
                  for (int index = 1; index < arr.length; index++) {
                      int temp; //用来作交换的临时变量
                      //内层控制比较,每当当前的值比前一次的值小,就将之往前移;
                      for (int i = index; i > 0; i--) {
                          if(arr[i] < arr[i-1]){
                              temp = arr[i-1];
                              arr[i-1] = arr[i];
                              arr[i] = temp;
                          }
                      }
                  }
                  System.out.println(Arrays.toString(arr));
              }
          }
          
    • 快速排序法:

      • 原理:

        • 先从数组中找一个数当做基准数,一般会以数组最左边的数为基准数,然后从两边进行检索;
      • 先从右边检索比基准数小的(一般基准数定义在最左边,那就从最右边开始检索,反之亦然;)

        • 如果从右边检索到了比基准数小的,先停下,再从左边检索比基准数大的,如果从左边找到了比基准数大的,则交换检索到的这两个元素位置,再继续检索;
        • 如果左右检索一旦相遇,就停止检索;然后将基准数和相遇位置的元素交换;
        • 第一轮排完之后,基准数左边的都比它小,右边的都比它大;
        • 以后先排基准数左边,排完之后,再排右边,方式和第一轮一样;
      • 代码:

        class QuickSor{
            public  void quickSort(int[] arr, int left, int right){
                if(left > right){
                    return;
                }
                int BaseNumber = arr[left]; //定义变量保存基准数,
                int LeftIndex = left; //定义变量LeftIndex指向左边;
                int RightIndex = right; //定义变量RightIndex指向右边;
        
                //当LeftIndex与RightIndex不相遇的时候,将会在循环中实现检索
                while(LeftIndex != RightIndex){
                    //1, 因为定义最左边为基准数,故而先从右边检索比基准数小的,
                    while(arr[RightIndex] >= BaseNumber && RightIndex < LeftIndex){
                        RightIndex--; //从右往左移动
                    }
                    //2.从左往右检索,找到比基准数大的,就停止检索
                    while(arr[LeftIndex] <= BaseNumber && RightIndex < LeftIndex){
                        LeftIndex++; //从左往右移动
                    }
                    //当执行到此处,证明RightIndex和LeftIndex相遇,此时代表检索停止,
                    //该交换两个索引对应位置的元素;
                    int temp = arr[LeftIndex];
                    arr[LeftIndex] = arr[RightIndex];
                    arr[RightIndex] = temp;
                }
                //当执行到此处的时候,说明外层while循环已经结束,此时LeftIndex=RightIndex
                //交换基准数位置和相遇位置的元素
                arr[left] = arr[RightIndex];
                arr[RightIndex] =  BaseNumber;
                //交换完成之后,基准数就归位了,此时基准数左边比基准数小,基准数右边比基准数大
                //下来对基准数两边进行排序
               //先对左边排序
               quickSort(arr, left, LeftIndex - 1);
               //再对右边排序
                quickSort(arr, RightIndex + 1, right);
            }
        }
        
    • 希尔排序法:是对直接插入排序的优化;

    • 基数排序法:不比大小,收集再分配;

    • 堆排序法:平衡二叉树;大顶堆(升序),小顶堆(降序)

      • 前提:完全二叉树, 父节点大于子节点
      • parent (i-1)/2
      • c 2i+1 2i+2
    • 归并排序:

      • 递归:一个方法在自身里边执行

      • 代码:

        import java.util.Arrays;
        
        public class MergeSort {
            /*
            *分治
            */
            public static void mergeSort(int[] arr, int left, int right){
                //递归条件出口
                if(left >= right){
                    return;
                }
                //中间元素下标
                int center = (left + right) / 2;
                //分治左边数组
                mergeSort(arr, left, center);
                //分治右边数组
                mergeSort(arr, center + 1, right);
                //调用合并函数
                merge(arr, left, center, right);
            }
            /*
            *排序 合并
            */
            private static void merge(int[] arr,  int leftStart, int center, int rightEnd) {
                //定义临时数组
                int[] tempArr = new int[rightEnd - leftStart + 1];
                //左开始下标
                int leftIndex = leftStart;
                //右开始下标
                int rightIndex = center + 1;
                //临时数组起始下标;
                int tempIndex = 0;
        
                //左右数组进行比较,按序放入辅助数组
                while(leftIndex <= center && rightIndex <= rightEnd){
                    if(arr[leftIndex] <= arr[rightIndex]){
                        tempArr[tempIndex++] = arr[leftIndex++];
                    }else{
                        tempArr[tempIndex++] = arr[rightIndex++];
                    }
                }
                //判断左边子数组是否还有元素 ,有的话直接拷贝到temp剩余的后边
                while(leftIndex <= center){
                    tempArr[tempIndex++] = arr[leftIndex++];
                }
                //判断右边子数组是否还有元素 ,有的话直接拷贝到temp剩余的后边
                while(rightIndex <= rightEnd){
                    tempArr[tempIndex++] = arr[rightIndex++];
                }
                //将临时数组中的值赋值回原数组
                for (int i = 0; i < tempArr.length; i++) {
                    arr[i + leftStart] = tempArr[i];
                }
            }
        
            public static void main(String[] args) {
                int[] arr = {1, 31, 45, 27, 22,  16, 33, 90,  9,  11,  6};
                mergeSort(arr, 0, arr.length-1);
                System.out.println(Arrays.toString(arr));
            }
        }
        

查找思想:

二分查找

  • 每次查找一 半;

  • 前提:数组元素必须有序;

  • 根据元素,查找该元素第一次在数组中出现的索引;

    • 基本查找:
  • 原理:每次去找中间索引所对应的元素;最小索引为0,最大索引为arr.length-1;中间索引为最大加最小除以2;

    • 第一种:所要找的元素正好等于中间索引对应的元素,那就返回中间索引;
    • 第二种:所要找的元素比中间索引所对应的元素大,令最小索引为中间索引加1;继续寻找中间索引;
    • 第三种:所要找的元素比中间索引所对应的元素小,令最大索引为中间索引减1,继续寻找中间索引;
  • 代码:

    public class Test6 {
        public static void main(String[] args) {
            int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
            int index = getIndex(arr, 8);
            System.out.println("索引是:"+index);
        }
    
        private static int getIndex(int[] arr, int ele) {
            //定义三个索引
            int minIndex = 0;
            int maxIndex = arr.length - 1;
            int centerIndex = (minIndex + maxIndex) / 2;
    
            while(minIndex <= maxIndex){
              //第一种:所要找的元素正好等于中间索引对应的元素,那就返回中间索引;
              //第二种:所要找的元素比中间索引所对应的元素大,令最小索引为中间索引加1;继续寻找中间索引;
              //第三种:所要找的元素比中间索引所对应的元素小,令最大索引为中间索引减1,继续寻找中间索引;
                if(ele == arr[centerIndex]){
                    return centerIndex;
                }else if(ele > arr[centerIndex]){
                    minIndex = centerIndex + 1;
                }else {
                    maxIndex = centerIndex - 1;
                }
                //重新计算中间索引
                centerIndex = (minIndex + maxIndex) / 2;
            }
            return -1;
        }
    }
    

Arrays类

  • java中针对数组的操作;
  • 此类包含用来数组操作的各种方法;
    • Arrays.sort(arr); 排序
    • Arrays.toString(arr); 数组遍历
    • Arrays.binarySearch(); 二分查找:前提数组有序
    • Arrays.equals(arr, arrr1); 比较数组元素是否形同
    • Arrays.copyOf(arr, arr.length);以原长度拷贝
    • Arrays.copyOfRange(arr, from, to);从指定索引处,拷贝旧数组指定的终止索引处,含头不含尾;

包装类

byte -128 ------ 127

int -2^31 ------- 2^31 -1

  • java为了方便去操作这些基本类型的数据,那么针对每个基本数据类型,都提供了所对应的包装类(引用类型);
  • 基本类型-----包装类型
    • byte -----Byte
    • short ---- Short
    • int ----- Integer
      • Integer.toBinaryString(num) ----> 转换为2进制;
      • Integer.toOctalString(num) ----> 转换为8进制;
      • Integer.toHexString(num) ----> 转换为16进制;
      • 构造方法:
        • Integer(int value); 将基本类型包装为引用类型
        • Integer(String s); 只能给字面上是数字的字符串;
          • 数字格式化异常 NumberFormatException
    • long -----Long
    • float ----- Float
    • double ---- Double
    • char ----- Character
    • boolean ---- Boolean
  • String和int类型的相互转换:
    • int -----> String
      • 方式1:拼接空串 str = num + " ";
      • 方式2:String中的静态方法 valueOf();可以将多种类型转换为字符串;
        • valueOf(num);
      • 方式3: Integer.toString();
    • String ------> int
      • 方式1:new Integer, .intValue(); 把包装类型转换为基本类型
      • 方式2:Integer.parseInt(strNum); 静态方法;

自动开装箱

jDk1.5之后

自动装箱:

  • 将基本类型自动转换成对应的包装类型;
    • .intValue(); 手动拆箱

自动拆箱:

  • 将包装类型,自动转换成对应的基本类型;
    • .valueOf(); 手动装箱;
	//超过一个字节的范围
	Integer i5 = 128; //自动装箱
	Integer i6 = 128; 
	System.out.println(i5 == i6);
	System.out.println(i5.equals(i6));
	System.out.println("-----------");

	//没有超过一个字节的范围
	Integer i7 = 127;
	Integer i8 = 127;
	System.out.println(i7 == i8);
	System.out.println(i7.equals(i8));

	//Integer i7 = 127; 自动装箱,底层要调用
	//手动装箱
	//valueOf();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值