JAVA 核心知识点篇之算法:概述,总结

2023-05-16

JAVA 算法

  • 1.1. 二分查找
  • 1.2. 冒泡排序算法
  • 1.3. 插入排序算法
  • 1.4. 快速排序算法
  • 希尔排序算法
    • 1.1. 归并排序算法
    • 1.2. 桶排序算法
    • 1.3. 基数排序算法
  • 算法( 二 ):补充

1.1. 二分查找

又叫折半查找,要求待查找的序列有序。每次取中间位置的值与待查关键字比较,如果中间位置的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,则在后半部分循环这个查找的过程。直到查找到了为止,否则序列中没有待查的关键字。

public static int biSearch(int []array,int a){
    int lo=0;
    int hi=array.length-1;
    int mid;
    while(lo<=hi){
        mid=(lo+hi)/2;//中间位置
        if(array[mid]==a){
            return mid+1;
        }else if(array[mid]<a){ //向右查找
            lo=mid+1;
        }else{ //向左查找
            hi=mid-1;
        }
    }
    return -1;
}

1.2. 冒泡排序算法

(1)比较前后相邻的二个数据,如果前面数据大于后面的数据,就将这二个数据交换。
(2)这样对数组的第 0 个数据到 N-1 个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1 个位置。
(3)N=N-1,如果 N 不为 0 就重复前面二步,否则排序完成。

public static void bubbleSort1(int[] a, int n) {
    int i, j;
    for (i = 0; i < n; i++) {//表示 n 次排序过程。
        for (j = 1; j < n - i; j++) {
            if (a[j - 1] > a[j]) {//前面的数字大于后面的数字就交换
                //交换 a[j-1]和 a[j]
                int temp;
                temp = a[j - 1];
                a[j - 1] = a[j];
                a[j] = temp;
            }
        }
    }
}

1.3. 插入排序算法

通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应的位置并插入。
插入排序非常类似于整扑克牌。在开始摸牌时,左手是空的,牌面朝下放在桌上。接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌的正确位置,要将它与手中已有的牌从右到左地进行比较。无论什么时候,左手中的牌都是排好序的。
如果输入数组已经是排好序的话,插入排序出现最佳情况,其运行时间是输入规模的一个线性函数。如果输入数组是逆序排列的,将出现最坏情况。平均情况与最坏情况一样,其时间代价是(n2)。

在这里插入图片描述

public void sort(int arr[]) {
    for (int i = 1; i < arr.length; i++) {
        //插入的数
        int insertVal = arr[i];
        //被插入的位置(准备和前一个数比较)
        int index = i - 1;
        //如果插入的数比被插入的数小
        while (index >= 0 && insertVal < arr[index]) {
            //将把 arr[index] 向后移动
            arr[index + 1] = arr[index];
            //让 index 向前移动
            index--;
        }
        //把插入的数放入合适位置
        arr[index + 1] = insertVal;
    }
}

1.4. 快速排序算法

快速排序的原理:选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。一般选择序列的第一个元素。
一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换。找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换。直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值来说,左右两边就是有序的了。

public void sort(int[] a, int low, int high) {
        int start = low;
        int end = high;
        int key = a[low];
        while (end > start) {
            //从后往前比较
            while (end > start && a[end] >= key)
            //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
                end--;
            if (a[end] <= key) {
                int temp = a[end];
                a[end] = a[start];
                a[start] = temp;
            }
            //从前往后比较
            while (end > start && a[start] <= key)
            //如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
                start++;
            if (a[start] >= key) {
                int temp = a[start];
                a[start] = a[end];
                a[end] = temp;
            }
            //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的
            //值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
        }
        //递归
        if (start > low) sort(a, low, start - 1);//左边序列。第一个索引位置到关键值索引-1
        if (end < high) sort(a, end + 1, high);//右边序列。从关键值索引+1 到最后一个
    }
}

在这里插入图片描述

希尔排序算法

基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

  1. 操作方法:
    选择一个增量序列 t1,t2,…,tk,其中 ti>tj,tk=1;
  2. 按增量序列个数 k,对序列进行 k 趟排序;
  3. 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
    在这里插入图片描述
private void shellSort(int[] a) {
    int dk = a.length / 2;
    while (dk >= 1) {
        ShellInsertSort(a, dk);
        dk = dk / 2;
    }
}

private void ShellInsertSort(int[] a, int dk) {
    //类似插入排序,只是插入排序增量是 1,这里增量是 dk,把 1 换成 dk 就可以了
    for (int i = dk; i < a.length; i++) {
        if (a[i] < a[i - dk]) {
            int j;
            int x = a[i];//x 为待插入元素
            a[i] = a[i - dk];
            for (j = i - dk; j >= 0 && x < a[j]; j = j - dk) {
                //通过循环,逐个后移一位找到要插入的位置。
                a[j + dk] = a[j];
            }
            a[j + dk] = x;//插入
        }
    }
}

1.1. 归并排序算法

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
在这里插入图片描述

public class MergeSortTest {
    public static void main(String[] args) {
        int[] data = new int[]{5, 3, 6, 2, 1, 9, 4, 8, 7};
        print(data);
        mergeSort(data);
        System.out.println("排序后的数组:");
        print(data);
    }

    public static void mergeSort(int[] data) {
        sort(data, 0, data.length - 1);
    }

    public static void sort(int[] data, int left, int right) {
        if (left >= right)
            return;
        // 找出中间索引
        int center = (left + right) / 2;
        // 对左边数组进行递归
        sort(data, left, center);
        // 对右边数组进行递归
        sort(data, center + 1, right);
        // 合并
        merge(data, left, center, right);
        print(data);
    }

    /**
     * 将两个数组进行归并,归并前面 2 个数组已有序,归并后依然有序
     * 13/04/2018 Page 239 of 283
     *
     * @param data   数组对象
     * @param left   左数组的第一个元素的索引
     * @param center 左数组的最后一个元素的索引,center+1 是右数组第一个元素的索引
     * @param right  右数组最后一个元素的索引
     */
    public static void merge(int[] data, int left, int center, int right) {
        // 临时数组
        int[] tmpArr = new int[data.length];
        // 右数组第一个元素索引
        int mid = center + 1;
        // third 记录临时数组的索引
        int third = left;
        // 缓存左数组第一个元素的索引
        int tmp = left;
        while (left <= center && mid <= right) {
            // 从两个数组中取出最小的放入临时数组
            if (data[left] <= data[mid]) {
                tmpArr[third++] = data[left++];
            } else {
                tmpArr[third++] = data[mid++];
            }
        }
        // 剩余部分依次放入临时数组(实际上两个 while 只会执行其中一个)
        while (mid <= right) {
            tmpArr[third++] = data[mid++];
        }
        while (left <= center) {
            tmpArr[third++] = data[left++];
        }
        // 将临时数组中的内容拷贝回原数组中
        // (原 left-right 范围的内容被复制回原数组)
        while (tmp <= right) {
            data[tmp] = tmpArr[tmp++];
        }
    }

    public static void print(int[] data) {
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i] + "\t");
        }
        System.out.println();
    }
}

1.2. 桶排序算法

桶排序的基本思想是: 把数组 arr 划分为 n 个大小相同子区间(桶),每个子区间各自排序,最后合并 。计数排序是桶排序的一种特殊情况,可以把计数排序当成每个桶里只有一个元素的情况。
1.找出待排序数组中的最大值 max、最小值 min
2.我们使用 动态数组 ArrayList 作为桶,桶里放的元素也用 ArrayList 存储。桶的数量为(maxmin)/arr.length+1
3.遍历数组 arr,计算每个元素 arr[i] 放的桶
4.每个桶各自排序

public static void bucketSort(int[] arr) {
    int max = Integer.MIN_VALUE;
    int min = Integer.MAX_VALUE;
    for (int i = 0; i < arr.length; i++) {            
        max = Math.max(max, arr[i]);
        min = Math.min(min, arr[i]);
    }
    //创建桶
    int bucketNum = (max - min) / arr.length + 1;
    ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
    for (int i = 0; i < bucketNum; i++) {
        bucketArr.add(new ArrayList<Integer>());
    }
    //将每个元素放入桶
    for (int i = 0; i < arr.length; i++) {
        int num = (arr[i] - min) / (arr.length);
        bucketArr.get(num).add(arr[i]);
    }
    //对每个桶进行排序
    for (int i = 0; i < bucketArr.size(); i++) {
        Collections.sort(bucketArr.get(i));
    }
}

1.3. 基数排序算法

将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

public class radixSort {
    int a[]=

    {
        49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 101, 56, 17, 18, 23, 34, 15, 35, 2
        5, 53, 51
    }

    ;

    public radixSort() {
        sort(a);
        for (inti = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
    }

    public void sort(int[] array) {
        //首先确定排序的趟数;
        int max = array[0];
        for (inti = 1; i < array.length; i++) {
            if (array[i] > max) {
                max = array[i];
            }
        }
        int time = 0;
        //判断位数;
        while (max > 0) {
            max /= 10;
            time++;
        }
        //建立 10 个队列;
        List<ArrayList> queue = newArrayList < ArrayList > ();
        for (int i = 0; i < 10; i++) {
            ArrayList<Integer> queue1 = new ArrayList<Integer>();
            queue.add(queue1);
        }
        //进行 time 次分配和收集;
        for (int i = 0; i < time; i++) {
            //分配数组元素;
            for (intj = 0; j < array.length; j++) {
                //得到数字的第 time+1 位数;
                int x = array[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
                ArrayList<Integer> queue2 = queue.get(x);
                queue2.add(array[j]);
                queue.set(x, queue2);
            }
            int count = 0;//元素计数器;
            //收集队列元素;
            for (int k = 0; k < 10; k++) {
                while (queue.get(k).size() > 0) {
                    ArrayList<Integer> queue3 = queue.get(k);
                    array[count] = queue3.get(0);
                    queue3.remove(0);
                    count++;
                }
            }
        }
    }
}



算法( 二 ):补充

JAVA 核心知识点篇之算法( 二 ):补充

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA 核心知识点篇之算法:概述,总结 的相关文章

  • Java 正则表达式 String.matches 工作不一致

    我有一个正则表达式来检查字符串是否是数字 该格式的千位分隔符是空格 小数分隔符是点 小数点后部分是可选的 问题是 在某些时候 String matches 函数会停止按预期工作 以前有效的方法现在不再有效了 例如 JUnit 代码 impo
  • 如何使 JTextArea 可滚动但仍设置高度?

    我有一个 Java 应用程序 它连接到设备并在JTextArea 我想要JTextArea可滚动 我通过将其放入JScrollPane The JScrollPane含有JTextArea在里面CENTER的一部分BorderLayout
  • Dom解析器和Xerces解析器之间的区别

    嘿 谁能告诉我 Dom 解析器 和 Xerces 解析器 之间有什么区别 两者各有什么优点和缺点 Xerces isDOM 解析器 它是 Java 或 C 中的 Apache 实现 您需要考虑的两个是 SAX 和 DOM DOM 在内存中创
  • 用 Java 创建 PDF 的缩略图

    我正在寻找一个 Java 库 它可以获取 PDF 并从第一页创建缩略 图 PNG 我已经看过 JPedal 但其疯狂的许可费完全令人望而却步 我目前正在使用 iText 来操作 PDF 文件 但我相信它不会生成缩略图 我可以在命令行上使用
  • 在intellij中为java启用ssl调试

    从我的问题开始 上一期尝试通过 tls ssl 发送 java 邮件 https stackoverflow com questions 39259578 javamail gmail issue ready to start tls th
  • Android ArrayList 的 IndexOutOfBoundsException [重复]

    这个问题在这里已经有答案了 我遇到了一个非常烦人的问题 一些代码抛出 IndexOutOfBoundsException 我真的不明白为什么 logcat 指向以下代码的 addTimetableItem 我们将对此进行更多解释 if so
  • Spring Boot 动态重置数据源

    当 Spring 配置文件或自定义数据库属性文件中的数据库名称 密码或主机名等数据库属性发生更改时 我尝试更新 Spring Boot 中的数据源 当属性更改时 应用程序必须通过侦听属性更改来自行更新 一旦数据库配置发生更改 我就使用 Sp
  • 使用 pdfbox 1.8.8 进行视觉签名

    我正在尝试生成带有视觉签名和 pdfbox 的 PDF 我有两个流 似乎 pdfbox 只能处理文件 如果没有三个临时文件 我就无法使其工作 我可以看到从here https github com apache pdfbox blob b7
  • 如何在画布的右上角绘制位图

    我正在尝试绘制位图top right hand corner of the Canvas 到目前为止我已经做了以下事情 100x40 dimensions for the bitmap bitmap BitmapFactory decode
  • 如何使用 maven 在 JBoss AS 7 的 MANIFEST.MF 中生成模块依赖关系?

    在 JBoss AS 7 中 依赖于 AS 中包含的库的 Web 应用程序必须在 META INF MANIFEST MF 中声明这些依赖关系 如下所示 Dependencies
  • Java 中的额外导入会减慢代码加载时间吗?

    向 Java 代码中添加更多 import 语句是否可能会减慢将类加载到 JVM 中所需的时间 不 导入仅在编译中用于查找类引用 添加未使用的导入 它们不会执行任何操作 换一种方式 import java util 只是意味着你可以写 Ma
  • HashSet 中的并行流不并行运行

    我有想要并行处理的元素集合 当我使用List 并行性有效 但是 当我使用Set 它不并行运行 我编写了一个代码示例来显示该问题 public static void main String args ParallelTest test ne
  • Java方法关键字“final”及其使用

    当我创建复杂类型层次结构 多个级别 每个级别几种类型 时 我喜欢使用final实现某些接口声明的方法上的关键字 一个例子 interface Garble int zork interface Gnarf extends Garble Th
  • 序列化的 lambda 且没有serialVersionUID?

    我正在尝试了解 Java 及其最新版本的序列化如何工作 我正在尝试像这样序列化 lambda Runnable r Runnable Serializable gt System out println This is a test 但我注
  • Java中使用什么方法来销毁你的对象[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 你能为我的问题举一个例子吗 抱歉 J
  • 如何使用 DynamicJasper 在 JasperReports 的页脚处显示每列的总和而不进行分组?

    我尝试使用下面的方法 drb addGlobalFooterVariable totalAmount DJCalculation SUM drb addGlobalFooterVariable basicAmount DJCalculati
  • Java 中的 lambda 目标类型和目标类型上下文是什么意思?

    我正在阅读 Herbert Schildt 的 Java 完整参考 中关于 lambda 的一章 其中有很多对 lambda 目标类型 和 目标类型上下文 的引用 函数式接口定义了目标类型的一个 拉姆达表达式 这里有一个关键点 只能使用 l
  • MultipartEntity 类型已弃用

    文档说org apache http entity mime MultipartEntity http hc apache org httpcomponents client ga httpmime apidocs org apache h
  • Java多线程和安全发布[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 看完之后 Java并发实践 http jcip net and OSGI 实践 http neilbartlett name blog osgi
  • Spring Security 实体字段级安全

    我有一个 Spring MVC 应用程序 它提供了一个视图 其中显示了来自Customer实体 例如姓名 地址 电话号码等 该应用程序具有各种角色 例如ROLE USER and ROLE ADMIN 用户具有ROLE USER只能看到客户

随机推荐