十种排序方法

文章目录

  • 前言
  • 一、选择排序
    • 1. 原理讲解
    • 2. 代码示例
    • 3. 总结
  • 二、插入排序
    • 1.原理讲解
    • 2.代码示例
    • 3. 总结
  • 三、归并排序
    • 1. 原理讲解
    • 2. 代码示例
    • 3. 总结
  • 四、快速排序
    • 1. 原理讲解
    • 2. 代码示例
  • 五、堆排序
    • 1. 原理讲解
    • 2. 代码示例
  • 六、希尔排序
    • 1. 原理讲解
    • 2. 代码示例
  • 七、冒泡排序
    • 1. 原理讲解
    • 2. 代码示例
  • 八、计数排序
    • 1. 原理讲解
    • 2. 代码示例
  • 九、基数排序
    • 1. 原理讲解
    • 2. 代码示例
  • 十、桶排序
    • 1. 原理讲解
    • 2. 代码示例


前言

排序方法: 选择排序、插入排序、归并排序、快速排序、堆排序、希尔排序、冒泡排序、计数排序、基数排序、桶排序。
重点掌握: 插入排序、归并排序、快速排序、堆排序。
部分内容转载于:912.排序数组精选题解


一、选择排序

1. 原理讲解

重复“使用线性查找从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换”。即:先选出最小的,再选出第 2 小的,放到开头,以此类推。

  • 总比较次数: n 2 2 \frac{n^{2}}{2} 2n2
  • 时间复杂度: O ( n 2 ) O(n^{2}) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)

选择排序

2. 代码示例

class Solution {
    public int[] sortArray(int[] nums) {
        int len = nums.length;
        for(int i = 0; i < len - 1; i++) {
            int minIndex = i;
            for(int j = i + 1; j < len; j++) {
                if(nums[j] < nums[minIndex]) {
                    minIndex = j;
                }
            }
            swap(nums, i, minIndex);
        }
        return nums;
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
    
}

3. 总结

  • 算法思想 1:贪心算法:每一次决策只看当前,当前最优,则全局最优。注意:这种思想不是任何时候都适用。
  • 算法思想 2:减治思想:外层循环每一次都能排定一个元素,问题的规模逐渐减少,直到全部解决,即大而化小,小而化了。运用减治思想很典型的算法就是二分查找
  • 优点:交换次数最少。

二、插入排序

1.原理讲解

插入排序是一种从序列左端开始依次对数据进行排序的算法。在排序过程中,左侧的数据陆续归位,而右侧留下的就是还未被排序的数据。插入排序的思路就是从右侧未排序的区域内选取出一个数据,然后将它插入到已排序区域内合适的位置上。

  • 时间复杂度: O ( n 2 ) O(n^{2}) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)

插入排序

2.代码示例

class Solution {
    public int[] sortArray(int[] nums) {
       int len = nums.length;
       // 循环不变量:将 nums[i] 插入到区间 [0, i) 使之成为有序数组
       for(int i = 0; i < len; i++) {
         // 先暂存这个元素,然后之前元素逐个后移,留出空位
        int temp = nums[i];
        int j = i;
        while(j > 0 && nums[j - 1] > temp) {
            nums[j] = nums[j - 1];
            j--;
        }
        nums[j] = temp;
       }
       return nums;

    }
}

3. 总结

  • 由于插入排序几乎有序的数组上表现良好,特别地,在短数组上的表现也很好。因为短数组的特点是:每个元素离它最终排定的位置都不会太远。为此,在小区间内执行排序任务的时候,可以转向使用插入排序。

三、归并排序

1. 原理讲解

归并排序算法会把序列分成长度相同的两个子序列,当无法继续往下分时(也就是每个子序列中只有一个数据时),就对子序列进行归并。归并是指把两个排好序的子序列合并成一个有序序列。该操作会一直重复执行,直到所有的子序列都归并为一个整体为止。即:借助额外空间,合并两个有序数组,得到更长的有序数组。

  • 时间复杂度: O ( n l o g ( n ) ) O(nlog(n)) O(nlog(n))
  • 空间复杂度: O ( n ) O(n) O(n)

归并排序

2. 代码示例

class Solution {
    int[] tmp;

    public int[] sortArray(int[] nums) {
        tmp = new int[nums.length];
        mergeSort(nums, 0, nums.length - 1);
        return nums;
    }

    public void mergeSort(int[] nums, int l, int r) {
        if (l >= r) {
            return;
        }
        int mid = (l + r) >> 1;
        // 递归调用函数 mergeSort(nums, l, mid) 对 nums 数组里 [l,mid] 部分进行排序。
        mergeSort(nums, l, mid);
        // 递归调用函数 mergeSort(nums, mid + 1, r) 对 nums 数组里 [mid+1,r] 部分进行排序。
        mergeSort(nums, mid + 1, r);
        int i = l, j = mid + 1;
        int cnt = 0;
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) {
                tmp[cnt++] = nums[i++];
            } else {
                tmp[cnt++] = nums[j++];
            }
        }
        while (i <= mid) {
            tmp[cnt++] = nums[i++];
        }
        while (j <= r) {
            tmp[cnt++] = nums[j++];
        }
        for (int k = 0; k < r - l + 1; ++k) {
            nums[k + l] = tmp[k];
        }
    }
}

3. 总结

  • 归并排序比快速排序好的一点是,它借助了额外空间,可以实现稳定排序

四、快速排序

1. 原理讲解

快速排序首先在序列中随机选择一个基准值,然后将除了基准值以外的数分为“比基准值小的数”和“比基准值大的数”两个类别,即:[比基准值小的数] 基准值 [比基准值大的数],接着对两个[]中的数进行排序之后,整体的排序就完成了。

  • 时间复杂度: O ( n l o g ( n ) ) O(nlog(n)) O(nlog(n))
  • 空间复杂度: O ( n ) O(n) O(n)

快速排序

2. 代码示例


class Solution {
    
    public int[] sortArray(int[] nums) {
      randomizedQuicksort(nums, 0, nums.length - 1);
        return nums;
    }

    // 对 nums 数组里 [l,r] 的部分进行排序
    public void randomizedQuicksort(int[] nums, int l, int r) {
        if (l < r) {
           
            int pos = randomizedPartition(nums, l, r);
            randomizedQuicksort(nums, l, pos - 1);
            randomizedQuicksort(nums, pos + 1, r);
        }
    }

     // 函数对 nums 数组里 [l,r] 的部分进行划分,并返回分界值的下标 pos
     public int randomizedPartition(int[] nums, int l, int r) {
        int i = new Random().nextInt(r - l + 1) + l; // 随机选一个作为我们的主元
        swap(nums, r, i);
        return partition(nums, l, r);
    }

    public int partition(int[] nums, int l, int r) {
        int pivot = nums[r];
        int i = l - 1;
        for (int j = l; j <= r - 1; ++j) {
            if (nums[j] <= pivot) {
                i = i + 1;
                swap(nums, i, j);
            }
        }
        swap(nums, i + 1, r);
        return i + 1;
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

}

五、堆排序

1. 原理讲解

堆是一种图的树形结构,被用于实现优先队列。优先队列是一种数据结构,可以自由添加数据,但取出数据时要从最小值开始按照顺序取出。

  • 时间复杂度: O ( n l o g ( n ) ) O(nlog(n)) O(nlog(n))
  • 空间复杂度: O ( 1 ) O(1) O(1)

堆排序

2. 代码示例

public class Solution {

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        // 将数组整理成堆
        heapify(nums);

        // 循环不变量:区间 [0, i] 堆有序
        for (int i = len - 1; i >= 1; ) {
            // 把堆顶元素(当前最大)交换到数组末尾
            swap(nums, 0, i);
            // 逐步减少堆有序的部分
            i--;
            // 下标 0 位置下沉操作,使得区间 [0, i] 堆有序
            siftDown(nums, 0, i);
        }
        return nums;
    }

    /**
     * 将数组整理成堆(堆有序)
     *
     * @param nums
     */
    private void heapify(int[] nums) {
        int len = nums.length;
        // 只需要从 i = (len - 1) / 2 这个位置开始逐层下移
        for (int i = (len - 1) / 2; i >= 0; i--) {
            siftDown(nums, i, len - 1);
        }
    }

    /**
     * @param nums
     * @param k    当前下沉元素的下标
     * @param end  [0, end] 是 nums 的有效部分
     */
    private void siftDown(int[] nums, int k, int end) {
        while (2 * k + 1 <= end) {
            int j = 2 * k + 1;
            if (j + 1 <= end && nums[j + 1] > nums[j]) {
                j++;
            }
            if (nums[j] > nums[k]) {
                swap(nums, j, k);
            } else {
                break;
            }
            k = j;
        }
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

六、希尔排序

1. 原理讲解

思想来源:插入排序的优化。在插入排序里,如果靠后的数字较小,它来到前面就得交换多次。「希尔排序」改进了这种做法。带间隔地使用插入排序,直到最后「间隔」为 1 的时候,就是标准的「插入排序」,此时数组里的元素已经「几乎有序」了;希尔排序的「间隔序列」其实是一个超参数。

2. 代码示例

public class Solution {

    // 希尔排序

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        int h = 1;

        // 使用 Knuth 增量序列
        // 找增量的最大值
        while (3 * h + 1 < len) {
            h = 3 * h + 1;
        }

        while (h >= 1) {
            // insertion sort
            for (int i = h; i < len; i++) {
                insertionForDelta(nums, h, i);
            }
            h = h / 3;
        }
        return nums;
    }

    /**
     * 将 nums[i] 插入到对应分组的正确位置上,其实就是将原来 1 的部分改成 gap
     *
     * @param nums
     * @param gap
     * @param i
     */
    private void insertionForDelta(int[] nums, int gap, int i) {
        int temp = nums[i];
        int j = i;
        // 注意:这里 j >= deta 的原因
        while (j >= gap && nums[j - gap] > temp) {
            nums[j] = nums[j - gap];
            j -= gap;
        }
        nums[j] = temp;
    }
}

七、冒泡排序

1. 原理讲解

冒泡排序是重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置”。

  • 时间复杂度: O ( n 2 ) O(n^{2}) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)

冒泡排序

2. 代码示例

public class Solution {
    public int[] sortArray(int[] nums) {
        int len = nums.length;
        for (int i = len - 1; i >= 0; i--) {
            // 先默认数组是有序的,只要发生一次交换,就必须进行下一轮比较,
            // 如果在内层循环中,都没有执行一次交换操作,说明此时数组已经是升序数组
            boolean sorted = true;
            for (int j = 0; j < i; j++) {
                if (nums[j] > nums[j + 1]) {
                    swap(nums, j, j + 1);
                    sorted = false;
                }
            }
            if (sorted) {
                break;
            }
        }
        return nums;
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

八、计数排序

1. 原理讲解

「计数排序」是把每个出现的数值都做一个计数,然后根据计数从小到大输出得到有序数组。
这种做法丢失了稳定性,如果是本题这种基本数据类型的话没有关系。如果是对象类型,就不能这么做了。
保持稳定性的做法是:先对计数数组做前缀和,在第 2 步往回赋值的时候,根据原始输入数组的数据从后向前赋值,前缀和数组保存了每个元素存放的下标信息。

2. 代码示例

public class Solution {

    // 计数排序

    private static final int OFFSET = 50000;

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        // 由于 -50000 <= A[i] <= 50000
        // 因此"桶" 的大小为 50000 - (-50000) = 10_0000
        // 并且设置偏移 OFFSET = 50000,目的是让每一个数都能够大于等于 0
        // 这样就可以作为 count 数组的下标,查询这个数的计数
        int size = 10_0000;

        // 计数数组
        int[] count = new int[size];
        // 计算计数数组
        for (int num : nums) {
            count[num + OFFSET]++;
        }

        // 把 count 数组变成前缀和数组
        for (int i = 1; i < size; i++) {
            count[i] += count[i - 1];
        }

        // 先把原始数组赋值到一个临时数组里,然后回写数据
        int[] temp = new int[len];
        System.arraycopy(nums, 0, temp, 0, len);

        // 为了保证稳定性,从后向前赋值
        for (int i = len - 1; i >= 0; i--) {
            int index = count[temp[i] + OFFSET] - 1;
            nums[index] = temp[i];
            count[temp[i] + OFFSET]--;
        }
        return nums;
    }
}

九、基数排序

1. 原理讲解

基本思路:也称为基于关键字的排序,例如针对数值排序,个位、十位、百位就是关键字。针对日期数据的排序:年、月、日、时、分、秒就是关键字。
「基数排序」用到了「计数排序」。

2. 代码示例

public class Solution {

    // 基数排序:低位优先

    private static final int OFFSET = 50000;

    public int[] sortArray(int[] nums) {
        int len = nums.length;

        // 预处理,让所有的数都大于等于 0,这样才可以使用基数排序
        for (int i = 0; i < len; i++) {
            nums[i] += OFFSET;
        }

        // 第 1 步:找出最大的数字
        int max = nums[0];
        for (int num : nums) {
            if (num > max) {
                max = num;
            }
        }

        // 第 2 步:计算出最大的数字有几位,这个数值决定了我们要将整个数组看几遍
        int maxLen = getMaxLen(max);

        // 计数排序需要使用的计数数组和临时数组
        int[] count = new int[10];
        int[] temp = new int[len];

        // 表征关键字的量:除数
        // 1 表示按照个位关键字排序
        // 10 表示按照十位关键字排序
        // 100 表示按照百位关键字排序
        // 1000 表示按照千位关键字排序
        int divisor = 1;
        // 有几位数,外层循环就得执行几次
        for (int i = 0; i < maxLen; i++) {

            // 每一步都使用计数排序,保证排序结果是稳定的
            // 这一步需要额外空间保存结果集,因此把结果保存在 temp 中
            countingSort(nums, temp, divisor, len, count);

            // 交换 nums 和 temp 的引用,下一轮还是按照 nums 做计数排序
            int[] t = nums;
            nums = temp;
            temp = t;

            // divisor 自增,表示采用低位优先的基数排序
            divisor *= 10;
        }

        int[] res = new int[len];
        for (int i = 0; i < len; i++) {
            res[i] = nums[i] - OFFSET;
        }
        return res;
    }

    private void countingSort(int[] nums, int[] res, int divisor, int len, int[] count) {
        // 1、计算计数数组
        for (int i = 0; i < len; i++) {
            // 计算数位上的数是几,先取个位,再十位、百位
            int remainder = (nums[i] / divisor) % 10;
            count[remainder]++;
        }

        // 2、变成前缀和数组
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }

        // 3、从后向前赋值
        for (int i = len - 1; i >= 0; i--) {
            int remainder = (nums[i] / divisor) % 10;
            int index = count[remainder] - 1;
            res[index] = nums[i];
            count[remainder]--;
        }

        // 4、count 数组需要设置为 0 ,以免干扰下一次排序使用
        for (int i = 0; i < 10; i++) {
            count[i] = 0;
        }
    }

    /**
     * 获取一个整数的最大位数
     *
     * @param num
     * @return
     */
    private int getMaxLen(int num) {
        int maxLen = 0;
        while (num > 0) {
            num /= 10;
            maxLen++;
        }
        return maxLen;
    }
}

十、桶排序

1. 原理讲解

基本思路:一个坑一个萝卜,也可以一个坑多个萝卜,对每个坑排序,再拿出来,整体就有序。

2. 代码示例

public class Solution {

    // 桶排序
    // 1 <= A.length <= 10000
    // -50000 <= A[i] <= 50000

    // 10_0000

    private static final int OFFSET = 50000;

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        // 第 1 步:将数据转换为 [0, 10_0000] 区间里的数
        for (int i = 0; i < len; i++) {
            nums[i] += OFFSET;
        }

        // 第 2 步:观察数据,设置桶的个数
        // 步长:步长如果设置成 10 会超出内存限制
        int step = 1000;
        // 桶的个数
        int bucketLen = 10_0000 / step;

        int[][] temp = new int[bucketLen + 1][len];
        int[] next = new int[bucketLen + 1];

        // 第 3 步:分桶
        for (int num : nums) {
            int bucketIndex = num / step;
            temp[bucketIndex][next[bucketIndex]] = num;
            next[bucketIndex]++;
        }

        // 第 4 步:对于每个桶执行插入排序
        for (int i = 0; i < bucketLen + 1; i++) {
            insertionSort(temp[i], next[i] - 1);
        }

        // 第 5 步:从桶里依次取出来
        int[] res = new int[len];
        int index = 0;
        for (int i = 0; i < bucketLen + 1; i++) {
            int curLen = next[i];
            for (int j = 0; j < curLen; j++) {
                res[index] = temp[i][j] - OFFSET;
                index++;
            }
        }
        return res;
    }

    private void insertionSort(int[] arr, int endIndex) {
        for (int i = 1; i <= endIndex; i++) {
            int temp = arr[i];
            int j = i;
            while (j > 0 && arr[j - 1] > temp) {
                arr[j] = arr[j - 1];
                j--;
            }
            arr[j] = temp;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/553390.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CSS3 伪元素与伪类选择器区别、详解与应用实例

伪元素与伪类两者都是通过在选择器后附加一个特定的关键字来定义&#xff0c;遵循相似的语法规则&#xff0c;并在 CSS 规则块中设置相应的样式。伪元素 能够通过 content 属性添加或替换内容。例如&#xff0c;:before 和 :after 可以插入文本、图像或其他生成的内容。伪类 仅…

如何安装MacOS的虚拟机?mac安装虚拟机的步骤 虚拟机安装MacOS VMware Fusion和Parallels Desktop19

要在Mac上运行MacOS的虚拟机&#xff0c;常用的方法是使用虚拟化软件如VMware Fusion或Parallels Desktop。 以下是安装MacOS的虚拟机的主要步骤&#xff1a; 1. 检查系统要求&#xff1a;确定您的Mac硬件和操作系统满足安装要求。您需要一台具备足够性能的Mac&#xff0c;并…

NLP学习(1)-搭建环境

前言 仅记录学习笔记&#xff0c;如有错误欢迎指正。 环境搭建 一、环境软件安装&#xff1a; 1、Anaconda安装&#xff08;一款可以同时创建和管理多个python环境的软件&#xff09; (1) 安装链接&#xff1a; https://blog.csdn.net/m0_61531676/article/details/126290…

04 MySQL --DQL 专题--Union、exists

1. UNION、UNION ALL UNION 关键字的作用&#xff1f; 合并两个或多个 SELECT 语句的结果。发挥的作用与 or 非常相似 UNION关键字生效的前提&#xff1f; 每个 SELECT 语句必须拥有相同数量的列。每个 SELECT 语句中的列的顺序必须相同。列必须拥有相似的数据类型。 SELEC…

ASP.NET Core 标识(Identity)框架系列(四):闲聊 JWT 的缺点,和一些解决思路

前言 前面的几篇文章讲了很多 JWT 的优点&#xff0c;但作为技术人员都知道&#xff0c;没有一种技术是万能的 “银弹”&#xff0c;所谓有矛就有盾&#xff0c;相比 Session、Cookie 等传统的身份验证方式&#xff0c;JWT 在拥有很多优点的同时&#xff0c;也有着不可忽视的缺…

第二部分 Python提高—GUI图形用户界面编程(五)

事件处理 文章目录 鼠标和键盘事件多种事件绑定方式汇总组件对象的绑定组件类的绑定 一个GUI 应用整个生命周期都处在一个消息循环(event loop) 中。它等待事件的发生&#xff0c;并作出相应的处理。 Tkinter 提供了用以处理相关事件的机制. 处理函数可被绑定给各个控件的各种…

Go 单元测试之Mysql数据库集成测试

文章目录 一、 sqlmock介绍二、安装三、基本用法四、一个小案例五、Gorm 初始化注意点 一、 sqlmock介绍 sqlmock 是一个用于测试数据库交互的 Go 模拟库。它可以模拟 SQL 查询、插入、更新等操作&#xff0c;并且可以验证 SQL 语句的执行情况&#xff0c;非常适合用于单元测试…

Java基础 - 10 - IO流(二)

一. IO流 - 字符流 1.1 FileReader&#xff08;文件字符输入流&#xff09; 作用&#xff1a;以内存为基准&#xff0c;可以把文件中的数据以字符的形式读入到内存中去 构造器说明public FileReader(File file)创建字符输入流管道与源文件接通public FileReader(String pathn…

Linux系统编程开发环境搭建

开发环境搭建 桥接网络&#xff08;Bridged Network&#xff09;、网络地址转换&#xff08;NAT, Network Address Translation&#xff09;和主机模式网络&#xff08;Host-only Networking&#xff09; 在虚拟化环境中&#xff0c;常见的三种网络模式是桥接网络&#xff08…

[Linux_IMX6ULL驱动开发]-总线设备驱动模型

目录 框架分层 总线驱动模型实现 上层驱动代码(leddrv.c)的实现以及解析 交叉依赖的避免 下层驱动的设备文件(board_A_led.c)的实现 下层驱动的驱动文件(chip_demo_gpio.c)的实现 框架分层 在之前&#xff0c;我们对于驱动的框架有过两种不同的框架。第一种框架&#xf…

如何爬出 Kotlin 协程死锁的坑?

作者&#xff1a;悬衡 一、前言 在 Java 中有一个非常经典的死锁问题, 就是明明自己已经占用了线程池, 却还继续去申请它, 自己等自己, 就死锁了, 如下图和代码: // 这段代码将死锁到天荒地老final ExecutorService executorService Executors.newSingleThreadExecutor();exe…

科学突破可能开创6G通信新时代

格拉斯哥大学开发的火柴盒大小的天线可以为全息通话、改进自动驾驶和更好的医疗保健的世界铺平道路。 格拉斯哥大学表示&#xff0c;这种创新的无线通信天线将超材料的独特特性与复杂的信号处理相结合&#xff0c;有助于构建未来的 6G 网络。 数字编码动态超表面天线&#xf…

前端请求发送成功,后端收到null

1、dishId为64&#xff0c;有数据 2、但是后端调试接不到数据&#xff0c;为null 3、形参部分缺少RequestBody接收JSON数据&#xff0c;加上即可

Kimichat炒股:7个提示词案例

●了解股票投资基本概念和知识 什么是有息负债率&#xff1f;用浅显明白的话语针对没有财务会计基础的小白进行解释 Kimi的回答&#xff1a; 有息负债率是一个财务指标&#xff0c;用来衡量一家公司在其负债中有多少是需要支付利息的。简单来说&#xff0c;就是公司借的钱中&…

获取公募基金持仓【数据分析系列博文】

摘要 从指定网址获取公募基金持仓数据&#xff0c;快速解析并存储数据。 &#xff08;该博文针对自由学习者获取数据&#xff1b;而在投顾、基金、证券等公司&#xff0c;通常有Wind、聚源、通联等厂商采购的数据&#xff09; 1. 导入必要的库&#xff1a; pandas 用于数据处理…

【第1节】书生·浦语大模型全链路开源开放体系

目录 1 简介2 内容&#xff08;1&#xff09;书生浦语大模型发展历程&#xff08;2&#xff09;体系&#xff08;3&#xff09;亮点&#xff08;4&#xff09;全链路体系构建a.数据b 预训练c 微调d 评测e.模型部署f.agent 智能体 3 相关论文解读4 ref 1 简介 书生浦语 InternLM…

深度Q-Learning在算法交易中的应用

一、说明 在《华尔街的随机漫步》一书中&#xff0c;作者伯顿马尔基尔&#xff08;Burton G. Malkiel&#xff09;声称&#xff1a;“一只蒙着眼睛的猴子向报纸的财经版面投掷飞镖&#xff0c;可以选择一个与专家精心挑选的投资组合一样好的投资组合。 如果我们让巴甫洛夫的狗接…

RabbitMQ-交换机

文章目录 交换机fanoutDirecttopicHeadersRPC 交换机 **交换机 **是消息队列中的一个组件&#xff0c;其作用类似于网络路由器。它负责将我们发送的消息转发到相应的目标&#xff0c;就像快递站将快递发送到对应的站点&#xff0c;或者网络路由器将网络请求转发到相应的服务器…

使用prompt_toolkit构建交互式命令行工具

prompt_toolkit是一个python库&#xff0c;用于构建命令行工具和终端应用。其官网介绍如下&#xff0c; prompt_toolkit is a library for building powerful interactive command line and terminal applications in Python. 安装命令如下&#xff0c; pip install prompt_to…

CCIA信息系统业务安全服务资质证书介绍条件要求

CCIA&#xff08;中国通信工业协会&#xff09;证书是由中国通信工业协会颁发的一种专业资质证书&#xff0c;旨在评估和认证信息化建设企业在信息化项目建设中提供的服务能力。该证书不涉及技术和产品标准&#xff0c;而是重点强调企业在行业服务方向、安全服务意识和专业服务…