Java常见算法_常见的查找算法和排序算法——简介及代码演示

在本文中我将介绍Java中的常见算法,查找算法包括基本查找、二分查找、插值查找和分块查找。排序算法包括冒泡排序、选择排序、插入排序和快速排序

查找算法:

1.基本查找:
代码:
java 复制代码
public class BasicSearchDemo {
    public static void main(String[] args) {
        int[] arr = {1,21,31,41,51,61,71,81};
        Scanner sc = new Scanner(System.in);
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);
        boolean result = basicSearch(arr, num);
        System.out.println(result);
    }
    //基本查找方法
    public static boolean basicSearch(int[] arr, int number) {
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == number) {
                return true;
            }
        }
        return false;
    }
}

这是简单的基本查找,通过遍历数组来查看元素是否存在

运行结果:
基本查找小练习:
代码(含题目要求):
java 复制代码
public class BasicSearchTest {
    public static void main(String[] args) {
        /*
        练习1:
        需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
        要求:不需要考虑数组中元素是否重复
         */

        /*
        练习2:
        需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
        要求:需要考虑数组中元素有重复的可能性
        例如:{1,1,1,2,3,4,5,6,1}
        若查找1,则需要返回所有元素1的索引,即0,1,2,8
         */

        //生成一个数组
        int[] arr = {1,11,21,31,41,51,51,61,51,61};

        //键盘录入一个元素
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您要查找的元素:");
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);
        System.out.println(getIndex(arr, num));
        System.out.println(getAllIndex(arr, num));
    }

    //练习1
    public static int getIndex(int[] arr, int number) {
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == number) {
                return i;
            }
        }

        return -1;
    }

    //练习2
    public static ArrayList<Integer> getAllIndex(int[] arr, int number) {
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == number) {
                list.add(i);
            }
        }

        return list;
    }
}
运行结果:
2.二分查找:

特点:

复制代码
        二分查找的数据必须是按大小顺序排好的
        二分查找可以很大的提高查找效率
代码:
java 复制代码
public class BinarySearchDemo1 {
    public static void main(String[] args) {
        //二分查找的数据必须是按大小顺序排好的
        //二分查找可以很大的提高查找效率

        //定义数组
        int[] arr = {1,21,31,41,51,61,71,81};
        //键盘录入一个要查找的元素
        System.out.println("输入要查找的元素:");
        Scanner sc = new Scanner(System.in);
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);
        System.out.println(binarySearch(arr, num));

    }

    //定义二分查找方法
    public static int binarySearch(int[] arr, int num) {
        //用min和max表示当前查找范围
        int min = 0;
        int max = arr.length - 1;
        while (true) {
            //这种情况说明元素不存在
            if(min > max) {
                return -1;
            }
            //定义中间指针
            int mid = (min + max) / 2;
            //进行判断
            if(arr[mid] < num) {
                //元素在右边
                min = mid + 1;
            } else if(arr[mid] > num) {
                //元素在左边
                max = mid - 1;
            } else {
                //找到了
                return mid;
            }
        }
    }
}
3.插值查找:

改变mid位置时使用数学公式使其更靠近要查找的元素

特点:

复制代码
        适用于数据分布较均匀的情况下
代码:
java 复制代码
public class InterpolationSearch {
    public static void main(String[] args) {
        //适用于数据分布较均匀的情况下
        int[] arr = {1,2,3,5,6,8,9,10};
        System.out.println("请输入要查找的元素值:");
        Scanner sc = new Scanner(System.in);
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);
        int index = interpolationSearch(arr, num);
        System.out.println(index);

    }

    public static int interpolationSearch(int[] arr, int num) {
        //定义查找范围
        int min = 0;
        int max = arr.length - 1;

        while(true) {
            if(min > max) {
                return -1;
            }
            //mid = min + (key - arr[min]) / (arr[max] - arr[min]) * (max - min)
            int mid = min + (num - arr[min]) / (arr[max] - arr[min]) * (max - min);
            if(arr[mid] > num) {
                max = mid - 1;
            } else if(arr[mid] < num) {
                min = mid + 1;
            } else {
                return mid;
            }
        }
    }
}
4.分块查找:

对数据先进行分块,通过先确定要查找的元素属于哪个块,再只需对那个块进行遍历

代码:
java 复制代码
public class BlockSearch {
    public static void main(String[] args) {
        //注意分块的块数跟元素个数的开方差不多即可
        //前一块所有元素都小于后一块中的任意元素
        int[] arr = {16, 5, 9, 12, 21, 18,
                    32, 23, 37, 26, 45, 34,
                    50, 48, 61, 52, 73, 66};

        //分块
        Block b1 = new Block(21, 0, 5);
        Block b2 = new Block(45, 6, 11);
        Block b3 = new Block(73, 12, 17);

        //用数组存储
        Block[] blockArr = {b1,b2,b3};

        //输入要查找的元素
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入要查找的元素");
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);

        int index = getIndex(arr, blockArr, num);
        System.out.println(index);

    }

    private static int getIndex(int[] arr, Block[] blockArr, int num) {
        int blockIndex = getBlock(blockArr, num);
        if(blockIndex == -1) {
            return -1;
        }
        //将范围缩小到这块的开始和结束索引
        int startIndex = blockArr[blockIndex].getStartIndex();
        int endIndex = blockArr[blockIndex].getEndIndex();
        //遍历
        for (int i = startIndex; i <= endIndex; i++) {
            if(arr[i] == num) {
                return i;
            }
        }
        return -1;
    }

    private static int getBlock(Block[] blockArr, int num) {
        for (int i = 0; i < blockArr.length; i++) {
            if(num < blockArr[i].getMax()) {
                return i;
            }
        }

        return -1;
    }

}


    class Block {
    private int max;
    private int startIndex;
    private int endIndex;


    public Block() {
    }

    public Block(int max, int startIndex, int endIndex) {
        this.max = max;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }

    /**
     * 获取
     * @return max
     */
    public int getMax() {
        return max;
    }

    /**
     * 设置
     * @param max
     */
    public void setMax(int max) {
        this.max = max;
    }

    /**
     * 获取
     * @return startIndex
     */
    public int getStartIndex() {
        return startIndex;
    }

    /**
     * 设置
     * @param startIndex
     */
    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }

    /**
     * 获取
     * @return endIndex
     */
    public int getEndIndex() {
        return endIndex;
    }

    /**
     * 设置
     * @param endIndex
     */
    public void setEndIndex(int endIndex) {
        this.endIndex = endIndex;
    }

    public String toString() {
        return "Block{max = " + max + ", startIndex = " + startIndex + ", endIndex = " + endIndex + "}";
    }
}

排序算法:

1.冒泡排序:
特点:
复制代码
        相邻的元素两两比较,大的放右边,小的放左边(从小到大情况)
        第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推
        如果数组中有n个数据,那总共执行n-1轮代码就可以
代码:
java 复制代码
public class BubbleSort {
    public static void main(String[] args) {
        //相邻的元素两两比较,大的放右边,小的放左边(从小到大情况)
        //第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推
        //如果数组中有n个数据,那总共执行n-1轮代码就可以

        //创建一个数组
        int[] arr = {1,4,5,2,3,9,5,6};
        int[] resultArr = bubbleSort(arr);
        for (int i = 0; i < resultArr.length; i++) {
            System.out.println(resultArr[i]);
        }
    }

    private static int[] bubbleSort(int[] arr) {
        //外循环:要进行几轮
        for (int i = 0; i < arr.length - 1; i++) {
            //内循环:这一轮需要判断几组数据是否应该交换
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if(arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }

        return arr;
    }
}
2.选择排序:
特点:
复制代码
        从0索引开始,拿着每一个索引上的元素跟后面的元素依次比较
        小的放前面,大的放后面(从小到大情况),以此类推
        第一轮循环结束后,最小的数据已经确定
        第二轮循环从1索引开始,以此类推
代码:
java 复制代码
public class SelectionSort {
    public static void main(String[] args) {
        //从0索引开始,拿着每一个索引上的元素跟后面的元素依次比较
        //小的放前面,大的放后面(从小到大情况),以此类推
        //第一轮循环结束后,最小的数据已经确定
        //第二轮循环从1索引开始,以此类推

        //创建数组
        int[] arr = {4,3,9,5,6,8,2,1};
        int[] resultArr = bubbleSort(arr);
        for (int i = 0; i < resultArr.length; i++) {
            System.out.println(resultArr[i]);
        }

    }

    public static int[] bubbleSort(int[] arr) {
        //外循环:表示几轮
        for (int i = 0; i < arr.length - 1; i++) {
            //内循环:i后面的所有数据与i进行比较
            for (int j = i + 1; j < arr.length; j++) {
                if(arr[i] > arr[j]) {
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }

        return arr;
    }
}
3.插入排序:
特点:
复制代码
        将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个元素当成是无序的。
        遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。
代码:
java 复制代码
public class InsertionSort {
    public static void main(String[] args) {
        //将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个元素当成是无序的。
        //遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。

        //创建数组
        int[] arr = {1,6,5,3,9,7,16,1,22,3};
        int[] resultArr = insertionSort(arr);
        for (int i = 0; i < resultArr.length; i++) {
            System.out.println(resultArr[i]);
        }
    }

    public static int[] insertionSort(int[] arr) {
        //判断有序元素个数
        int index = 0;
        for (int i = 1; i < arr.length; i++) {
            if(arr[index] < arr[index + 1]) {
                index++;
            } else {
                break;
            }
        }
        //index为最后一个有序元素的索引

        //有序元素后面的每个元素要插入有序元素中   插入后有序元素加1   索引也++

        //我的其他思路   复杂了。。
        /*
        for (; index < arr.length - 1; index++) {
            int i = index + 1;
            for(int j = index; j >= 0; j--) {
                if(arr[i] >= arr[j]) {
                    break;
                } else {
                    //有序元素后面的无序元素只要比前面的小就交换位置
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                    i--;
                    continue;
                }
            }
        }
        */

        //从有序数组后的第一个元素到最后一个元素
        for (int i = index + 1; i < arr.length; i++) {
            int j = i;
            while (j > 0 && arr[j] <arr[j - 1]) {
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
                j--;
            }
        }

        return arr;
    }
}
4.快速排序

这里展示快速排序之前要先学会递归思想,我先来放两个递归思想的小练习

递归练习一 题目及代码:
java 复制代码
public class RecursionAlgorithmTest1 {
    public static void main(String[] args) {
        //核心:找出口 找规律
        //方法中再次调用方法时,参数应更接近出口

        //求1~100所有整数的和
        int sum = getSum(100);
        System.out.println(sum);
    }

    //1~100所有整数的和 = 100 + 1~99的和
    //1~99的和 = 99 + 1~98的和
    //............
    public static int getSum(int num) {
        //出口
        if(num == 1) {
            return 1;
        }
        return num + getSum(num - 1);
    }
}
递归练习二 题目及代码:
java 复制代码
public class RecursionAlgorithmTest2 {
    public static void main(String[] args) {
        //需求:用递归求5的阶乘,并把结果在控制台输出
        int factorail = getFactorail(5);
        System.out.println(factorail);
    }

    //5的阶乘 = 5 * 4的阶乘
    //4的阶乘 = 4 * 3的阶乘
    //............
    public static int getFactorail(int num) {
        //出口
        if(num == 1) {
            return 1;
        }
        return num * getFactorail(num - 1);
    }
}

接下来开始讲解快速排序:

过程:
复制代码
//将排序范围中的第一个数字作为基准数,在定义两个变量start,end
//start从前往后找比基准数大的,end从后往前找比基准数小的。
/*找到之后交换start和end指向的元素,并循环这一过程,直到start和end处于同一个位置,
该位置是基准数在数组中应存入的位置,再让基准数归位*/
//归为后的效果:基准数左边的都比基准数小,右边的都比基准数大
代码演示:
java 复制代码
public class QuickSort {
    public static void main(String[] args) {
        //创建数组
        int[] arr = {6,2,3,1,7,5,8};
        int start = 0;
        int end = arr.length - 1;
        quickSort(arr, start, end);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

    }

    private static void quickSort(int[] arr, int i, int j) {
        //出口
        if(i >= j) {
            return;
        }
        int start = i;
        int end = j;
        //基准数
        int baseNumber = arr[i];
        while(start != end) {
            //end从右往左开始找比基准数小的数
            while(true) {
                if(end <= start || arr[end] < baseNumber) {
                    break;
                }
                end--;
            }
            //start从左往右开始找比基准数大的数
            while(true) {
                if(end <= start || arr[start] > baseNumber) {
                    break;
                }
                start++;
            }
            //交换位置
            int temp = arr[end];
            arr[end] = arr[start];
            arr[start] = temp;
        }
        //将基准数与当前start和end索引所在位置交换
        int temp = arr[i];
        arr[i] = arr[start];
        arr[start] = temp;
        //基准数左边继续重复刚才所做的事
        quickSort(arr, i, start - 1);
        //基准数右边继续重复刚才所做的事
        quickSort(arr, start + 1, j);


    }
}
相关推荐
芒果披萨1 分钟前
El表达式和JSTL
java·el
白榆maple9 分钟前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少14 分钟前
数据结构——线性表与链表
数据结构·c++·算法
duration~42 分钟前
Maven随笔
java·maven
zmgst1 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD1 小时前
前后端分离,Jackson,Long精度丢失
java
此生只爱蛋1 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
blammmp1 小时前
Java:数据结构-枚举
java·开发语言·数据结构
暗黑起源喵2 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong2 小时前
Java反射
java·开发语言·反射