冒泡排序,选择排序,二分查找算法正则表达式和异常

一.算法

1.冒泡排序

(1)原理

  • 1.从第一个数据开始,与第二个数据相比较,如果第二个数据小于第一个数据,则交换两个数据的位置
  • 2.指针从第一个数据移向第二个数据,第二个数据与第三个数据相比较,如果第三个数据小于第二个数据,则交换两个数据的位置
  • 3.依次类推,完成第一轮排序,第一轮排序结束后,最大的元素别移到了最右面
  • 4.依照上面的过程进行第二轮排序,将第二大的排在倒数第二的位置
  • 5.重复上述过程,每排完一轮,比较次数就减少一次

(2)例子

待排序数据:5,2,3,1
第一轮排序过程:

指针先指向5,5和3比较,5>2,交换2和5的位置,结果为:2,5,3,1
指针指向第二个元素5,5和3比较,5>3,交换5和3的位置,结果为:2,3,5,1
指针指向第三个元素5,5和1比较,5>1,交换5和1的位置,结果为:2, 3,1,5

第一轮排序结束后,最大的值5被移到了最右边
进行第二轮排序,过程同上,第二轮比较结果为:2,1,3,5
第三轮结果为:1,2,3,5
最终结果为:1,2,3,5,由上可知N个数据排序,需要进行N-1轮排序;第i轮排序需要的比较次数为N-i次

(3)编码思想

需要两层循环,第一层循环i表示排序的轮数,第二层循环j表示比较的次数。

(4)代码实现

import java.util.Arrays;

public class Test1 {
        // 掌握冒泡排序的编写:每次从数组中找出最大值放在数组的后面去
        public static void main(String[] args) {
            // 定义一个数组
            int[] arr = {5, 2, 3, 1};

            // 1.确定总共需要做几轮
            for (int i = 0; i < arr.length - 1; i++) {
                // i = 0 1 2              [5, 2, 3, 1]    次数
                // i = 0 第一轮            0   1   2         3
                // i = 1 第二轮            0    1            2
                // i = 2 第三轮            0                 1

                // 2.确定每轮比较几次
                for (int j = 0; j < arr.length - i - 1; j++) {
                    // 定义一个if语句来判断数组前后值的大小,如果前面的数大于后i面,就交换
                    if (arr[j] > arr[j+1]){
                        // 定义一个临时变量
                        int temp = arr[j];
                        arr[j] = arr[j+1];
                        arr[j+1] = temp;
                    }
                }
            }
            System.out.println(Arrays.toString(arr));
        }
}

二.选择排序

(1)基本思想

在长度为N的无须数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换
第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成

在这里插入图片描述

(2)代码实现

第一种:

import java.util.Arrays;

public class Test2 {
    // 掌握选择排序
    public static void main(String[] args) {
        // 定义一个数组
        int[] arr = {5, 1, 3, 2};

        // 定义一个循环来控制交换几轮
        for (int i = 0; i < arr.length - 1; i++) {

            // 定义一个循环来控制每轮交换几次
            for (int j = i + 1; j < arr.length; j++) {

                // 判断前面与后面数的值的大小,如果前面大于后面,则交换、
                if (arr[i] > arr[j]){
                    // 定义一个临时变量temp
                    int temp = arr[j];
                    arr[j] = arr[i];
                    arr[i] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

第二种:

import java.util.Arrays;

public class Test2pro {
    public static void main(String[] args) {
        // 选择排序算法的优化版
        // 定义一个数组
        int[] arr = {5, 1, 3, 2};

        // 定义一个循环来控制交换几轮
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;

            // 定义一个循环来控制每轮交换几次
            for (int j = i + 1; j < arr.length; j++) {
                // 判断前面与后面数的值的大小,如果前面大于后面,则交换、
                if (arr[minIndex] > arr[j]){
                    minIndex = j;
                }
                // 决定是否交换
                if (i != minIndex){
                    // 定义一个临时变量temp
                    int temp = arr[i];
                    arr[i] = arr[minIndex];
                    arr[minIndex] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

三.二分查找算法

(1)概述

  • 前提条件:数值中的数据必须时有序的
  • 核心思想;每次排除一半的数据,查询数据的性能明显提高很多
    在这里插入图片描述
    定义一个中间值mid与要找的数据n比较,如果mid<n ,则把左边的全部去掉,如果mid>n ,则去掉右边的

(2)代码实现

public class Test3 {
    public static void main(String[] args) {
        // 1.先准备一个数组
        int[] arr = {7, 15, 29, 37, 85, 138, 190};
        System.out.println(binarySearch(arr, 138));
    }

    public static int binarySearch(int[] arr,int data){
        // 2.定义两个变量,分别表示左边和右边
        int left = 0;
        int right = arr.length - 1;

        // 3.定义一个循环来进行二分查找
        while (left <= right){
            // 定义一个中间数来与data比较
            int middle = (left + right) / 2;
            if (data > arr[middle]){
                left = middle + 1;
            } else if (data < arr[middle]) {
                right = middle - 1;
            }else {
                return middle;
            }
        }
        return -1;
    }
}

四.正则表达式

1. 体验一下正则表达式来校验数据的合法性

对于同一个需求,正则表达式的代码展示

    public static boolean checkQQ1(String qq){
        return qq != null && qq.matches("[1-9]\\d{5,19}");
    }

普通写法的代码展示

    public static boolean checkQQ(String qq){
        // 1.判断qq是否为null,0开头,(6-20)之间
        if (qq == null || qq.startsWith("0") || qq.length() < 6 || qq.length() > 20){
            return false;
        }
        // 2.判断出qq至少不是null,不是0开头,长度在6-20之间
        // 判断qq中是否不全是数字
        for (int i = 0; i < qq.length(); i++) {
            char ch = qq.charAt(i);
            if (ch < '0' || ch > '9'){
                return false;
            }
        }
        return true;

2.正则表达式的书写规则

  1. 字符类(只能匹配单个字符)
    [abc]只能匹配a,b,c
    [^abc]不能是abc
    [a-zA-Z]只能是a-zA-Z的字符
        System.out.println("a".matches("[abc]")); // [abc]只能匹配a ,b,c
        System.out.println("e".matches("[abcd]")); // false

        System.out.println("d".matches("[^abc]"));// [^abc]不能是abc
        System.out.println("a".matches("[^abc]"));// false

        System.out.println("b".matches("[a-zA-Z]"));// [a-zA-Z]只能是a-zA-Z的字符
        System.out.println("2".matches("[a-zA-Z]"));// false

        System.out.println("k".matches("[a-z&&[^bc]]"));// a到z 除了b和c
        System.out.println("b".matches("[a-z[^bc]]"));// false

        System.out.println("ab".matches("[a-zA-Z0-9]"));// false 注意:以上带【内容】的规则都只能用与匹配单个字符
  1. 预定义字符(只能匹配单个字符) . \d \D \s \S \w \W
    . 可以匹配任意字符
    \在Java中有特殊意义: \n换行 \t代表一个缩进。如果在Java中,希望\就是\必须转义
    \d:0-9
    \s:代表一个空白字符
    \S:代表一个非空白字符
    \w:[a-zA-Z_0-9]
    \W不能是a-zA-Z_0-9
        System.out.println("徐".matches("."));// .可以匹配任意字符
        System.out.println("徐徐".matches("."));// false

        //  \在Java中有特殊意义: \n换行  \t代表一个缩进
        // 如果在Java中,希望\就是\必须转义
        System.out.println("\"");
        System.out.println("3".matches("\\d"));// \d:0-9
        System.out.println("a".matches("\\d"));// false

        System.out.println(" ".matches("\\s"));// \s:代表一个空白字符
        System.out.println("a".matches("\\s"));// false

        System.out.println("a".matches("\\S"));// \S:代表一个非空白字符
        System.out.println(" ".matches("\\S"));// false

        System.out.println("a".matches("\\w"));// \w:[a-zA-Z_0-9]
        System.out.println("_".matches("\\w"));// true
        System.out.println("徐".matches("\\w"));// false

        System.out.println("徐".matches("\\W"));// \\W不能是a-zA-Z_0-9
        System.out.println("a".matches("\\W"));// false

        System.out.println("23232".matches("\\d"));// false  注意:以上预定义字符都只能匹配单个字符
  1. 数量词:?* + {n} {n,} {n,m}
    ? 代表0次或1次
    *代表0次或多次
    +代表1次或多次
    {3}代表要正好是n次
    {3.}代表是>=3次
    {3,9}代表是 大于等于3次,小于等于9次
        System.out.println("a".matches("\\w?"));// ? 代表0次或1次
        System.out.println("".matches("\\w?"));// true
        System.out.println("abc".matches("\\w?"));// false

        System.out.println("abc12".matches("\\w*"));// * 代表0次或多次
        System.out.println(" ".matches("\\w*"));// true
        System.out.println("abc12张".matches("\\w*"));// false

        System.out.println("abc12".matches("\\w+"));// + 代表1次或多次
        System.out.println(" ".matches("\\w+"));// false
        System.out.println("abc12张".matches("\\w+"));// false

        System.out.println("a3c".matches("\\w{3}"));// {3}代表要正好是n次
        System.out.println("abcd".matches("\\w{3}"));// false
        System.out.println("abc12张".matches("\\w{3,}"));// {3.}代表是>=3次
        System.out.println("ab".matches("\\w{3,}"));// false
        System.out.println("abcde徐".matches("\\w{3,}"));// false
        System.out.println("abc232d".matches("\\w{3,9}"));// {3,9}代表是 大于等于3次,小于等于9次
  1. 其他几个常见的字符:(? !) 忽略大小写 或:| 分组:()
        System.out.println("abc".matches("(?!abc)"));// true
        System.out.println("ABC".matches("(?!abc)"));// true
        System.out.println("aBc".matches("a((?!)b)c"));// false
        System.out.println("ABc".matches("a((?!)b)c"));// false

3.正则表达式爬取

    public static void method1(){
        String data = "来黑马程序员学习Java.\n" +
                "       电话:1866668888.19839014992\n"+
                "或者联系邮箱;boniu@itcast.cn.\n" +
                "座机电话:01036517895.010-98951256\n" +
                "邮箱:boza@itcast.cn\n"+
                "邮箱:dle009@163.com.\n"+
                "热线电话:400-618-9090, 400-618-4000 ,4006184000 ,4006189090";
  1. 先定义爬取规则
        String regex = "(1[3-9]\\d{9}|(0\\d{2,7}-?[1-9]\\d{4,19})|(\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2})"
                + "|(400-?\\d{3,7}-?\\d{3,7}))";
  1. 把正则表达式封装成一个Pattern对象
        Pattern pattern = Pattern.compile(regex);
  1. 通过Pattern对象去获取查找内容的匹配器对象
        Matcher matcher = pattern.matcher(data);
  1. 定义一个循环开始爬取信息
        while (matcher.find()){
            String sc = matcher.group();
            System.out.println(sc);
        }

4.正则表达式做搜素替换,内容分割

public String replaceAll(String regex, String newStr):—>按照正则表达式匹配的内容进行替换

        String s1 = "古力娜扎ai888迪丽热巴999aa5566马儿扎哈fbb卡尔扎巴";
        System.out.println(s1.replaceAll("\\w+","-"));
        String s2 = "我我我喜欢编编编程程";
        System.out.println(s2.replaceAll("(.)\\1+", "$1"));

.public String[] spilt(String regex):—>按照正则表达式匹配的内容进行分割字符串,反向一个字符串数组

        String s3 = "古力娜扎ai888迪丽热巴999aa5566马儿扎哈fbb卡尔扎巴";
        String[] names = s3.split("\\w+");
        System.out.println(Arrays.toString(names));

五.异常

1.概述

异常就是代表程序出现的问题

  • 运行时异常:RuntimeException及其子类,编译阶段不会出现错误提醒,运行时出现的异常(如;数组索引越界异常)
  • 编译时异常:编译阶段就会出现错误提醒的(如:日期解析异常)

2.JVM默认处理异常的方式

当代码出现了异常,那么就会在异常处创建一个异常对象,若程序没有自己处理异常的代码,就会将异常交给本方法的调用者处理。
JVM默认处理异常的方式:

  • 将异常信息以红色字体展示在控制台上(异常原因,名字,位置)
  • 停止程序运行,哪里出现异常就在哪里停止

3.异常处理方式

1.throws声明异常

格式:public void 方法()throws 异常类名

注意事项:

  • 书写位置在方法的括号后面,表示声明一个异常
  • 编译时异常必须要进行处理,throws声明异常表示,谁调用这个方法谁处理异常
  • 运行时异常因为在运行时才会发生,所以在方法后面可以不写,默认交给jvm处理
public class Demo02 {
    public static void main(String[] args) throws ParseException {
        method1();//如果调用者没有处理异常的代码,最终交给Main方法调用者JVM处理异常
    }
 
    //throws声明,告诉调用者调用这个方法可能会发生异常
    //若无异常,方法正常执行;若发生异常将异常交给调用者处理
    private static void method1() throws ParseException {
        String s = "2021年11月11日";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        Date d = sdf.parse(s);//有可能会产生异常
        System.out.println(d);
    }
}

2.throw抛出异常

  • 格式:throw new 异常();
  • 注意;这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了
    在这里插入图片描述
    抛出异常的意义:
  • 在方法中,当传递的参数有误,没有继续运行下去的意义了,则采取抛出处理,表示让该方法结束运行
  • 告诉调用者方法中出现了问题
public class ExceptionDemo {
    public static void main(String[] args) {
        int [] arr = null;
        printArr(arr);//就会 接收到一个异常.
                      //我们还需要自己处理一下异常.
    }
 
    private static void printArr(int[] arr) {
        if(arr == null){
            //调用者知道成功打印了吗?
            //System.out.println("参数不能为null");
            throw new NullPointerException(); 
            //当参数为null的时候,手动创建了一个异常对象,抛给了调用者
            //调用者就知道没有打印成功
        }else{
            for (int i = 0; i < arr.length; i++) {
                System.out.println(arr[i]);
            }
        }
    }
 
}

3.try-catch自己处理异常

此方法处理异常的好处:即使发生了异常,程序还可以执行下去
实例代码:

public class Demo01 {
    public static void main(String[] args) {
        int[] arr = null;
        try {
            //有可能会出现异常的代码
            printArr(arr);
        }catch (NullPointerException e){
            //若出现了这样的异常,我们进行的操作
            System.out.println("数组为空");
        }
        //程序不会终止,会继续执行
        System.out.println("嘿嘿嘿");
    }
 
    private static void printArr(int[] arr) {
        if (arr == null){
            //抛出异常
            throw new NullPointerException();
        }else {
            for (int i = 0; i < arr.length; i++) {
                System.out.println(arr[i]);
            }
        }
    }
}

注意事项:

  • 如果 try 中没有遇到异常,会把try中所有的代码全部执行完毕,不会执行catch里面的代码
  • 如果 try 中遇到了异常,那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了
  • 如果出现的异常没有被捕获,那么try…catch就相当于没有写,异常默认交给虚拟机处理
  • 若出现多个异常就写多个catch,如果多个异常之间存在子父类关系,那么父类要写在子类异常的下面

4.自定义异常类

自定义异常类:

  • 当Java中提供的异常不能满足我们的需求时,我们可以自定义异常,让异常信息更加的简单
  • 实现步骤:1.定义异常类;2.写继承关系;3.提供空参构造器;4.提供有参构造器
public class AgeIllegalException extends Exception{
    public AgeIllegalException(){

    }
    public AgeIllegalException(String message){
        super(message);
    }
}
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值