排序学习整理(1)

news2024/11/28 16:14:24

1.排序的概念及运用

1.1概念

排序:所谓排序,就是使⼀串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作,以便更容易查找、组织或分析数据。

1.2运用

 购物筛选排序

院校排名

1.3常见排序算法

2.实现常见排序算法

int a[] = {5, 3, 9, 6, 2, 4, 7, 1, 8};

2.1 插入排序

把待排序的记录按其关键码值的大小逐个插入到⼀个已经排好序的有序序列中,直到所有的记录插入完为止,得到⼀个新的有序序列 。

2.1.1 直接插入排序

直接插入排序(Direct Insertion Sort)是一种简单直观的排序算法,它通过逐步构建有序序列,将未排序部分的元素插入到已排序部分的适当位置,直到整个数组排序完成。

基本思想

1.将数组分为 已排序部分 和 未排序部分。

                初始时,已排序部分只有第一个元素。

                未排序部分为剩余的元素。

2.依次从未排序部分取出一个元素,插入到已排序部分的正确位置。

3.重复以上操作,直到未排序部分为空。

算法步骤

1.从数组的第二个元素(索引为 1)开始,依次向后遍历。

                对当前元素,在已排序部分从后向前查找其插入位置:

                如果已排序部分的元素大于当前元素,则将其向后移动。

2.找到插入位置后,将当前元素放入。

3.重复此过程,直到所有元素排序完成。

当插入第 i(i>=1) 个元素时,前⾯的 array[0],array[1],…,array[i-1] 已经排好序,此时用 array[i] 的排序码与 array[i-1],array[i-2],… 的排序码顺序进行比较,找到插入位置即将 array[i] 插入,原来位置上的元素顺序后移
代码实现
void InsertSort(int* a, int n) {
    for (int i = 1; i < n; i++) {
        // 当前要插入的元素
        int tmp = a[i];
        // 已排序部分的最后一个元素的索引
        int j = i - 1;

        // 从后向前查找插入位置
        while (j >= 0 && a[j] > tmp) {
            a[j + 1] = a[j]; // 后移元素
            j--;
        }

        // 将当前元素插入到正确的位置
        a[j + 1] = tmp;
    }
}
特性总结
算法复杂度
  1. 时间复杂度
    • 最坏情况(数组逆序):O(n^2)
    • 最好情况(数组已排序):O(n)
    • 平均情况:O(n^2)
  2. 空间复杂度:原地排序,不需要额外的辅助空间,空间复杂度为 O(1)
  3. 稳定性:直接插入排序是稳定的,因为在插入过程中不会改变相等元素的相对顺序。

优缺点

优点

  1. 简单直观:实现容易,适合小规模数据。
  2. 性能良好:当数组接近有序时,插入排序的效率很高,接近 O(n)

缺点:

  1. 效率低下:对大规模、随机分布的数组排序效率较低,时间复杂度较高。
  2. 大量数据移动:当数组逆序时,几乎每次插入都需要移动大量元素。

适用场景
  1. 数据量较小(如 n <= 100)时,插入排序是一种简单有效的选择。
  2. 数据本身接近有序时(如几乎按升序排列),插入排序效率很高。

2.1.2 希尔排序 

希尔排序又称缩小增量法是一种基于插入排序的改进算法,得名于其发明者 Donald Shell。它通过分组和逐步缩小分组间距(增量),使得数据能够更快地接近有序,从而提高排序效率。

基本思想

先选定⼀个整数(通常是gap = n/3 + 1),把待排序文件所有记录分成各组,所有的距离相等的记录分在同⼀组内,并对每⼀组内的记录进⾏排序,然后gap = gap/3 + 1得到下⼀个整数,再将数组分成各组,进入插入排序,当gap = 1时,就相当于直接插入排序。

它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的。

算法步骤
  1. 初始化 gap = n / 3 + 1,其中 n 是数组的长度。
  2. 按照当前的 gap 将数组分组,对每组进行插入排序。
  3. 缩小 gap,继续分组排序,直到 gap = 1
  4. gap = 1 时,进行最后一次插入排序,数组有序。

 

代码实现
void ShellSort(int* a, int n) {
    int gap = n;

    // 缩小增量,直到 gap == 1
    while (gap > 1) {
        gap = gap / 3 + 1;

        // 分组
        for (int group = 0; group < gap; group++) { // 控制每组
            // 每组独立进行插入排序
            for (int i = group + gap; i < n; i += gap) {
                int tmp = a[i];
                int j = i - gap;

                while (j >= group && a[j] > tmp) {
                    a[j + gap] = a[j];
                    j -= gap;
                }
                a[j + gap] = tmp;
            }
        }
    }
}

显式地将数组分组,每组独立排序后再继续调整增量 gap,这种更好理解分组排序的原理,但代码稍显冗长,所以我一般用这种

void ShellSort1(int* a, int n) {
    int gap = n;
    // 缩小增量,直到 gap == 1
    while (gap > 1) {
        gap = gap / 3 + 1;
        // 从 gap 开始,模拟插入排序
        for (int i = gap; i < n; i++) {
            int tmp = a[i]; // 当前待插入的元素
            int j = i - gap;
            // 插入排序逻辑,按 gap 步长比较和移动
             while (j >= 0 && a[j] > tmp) { // 在同组中向前查找
                a[j + gap] = a[j]; // 将较大的元素后移
                j -= gap; // 按 gap 步长继续比较
            }
            a[j + gap] = tmp; // 插入到合适位置
        }
    }
}

这种方法也叫“简单希尔排序”(Simple Shell Sort),或者直接叫并着走,它直接在外层控制增量 gap,然后在整个数组中按步长进行插入排序,逻辑比较直观,效率高。这种实现方法更贴近希尔排序的本质,适合直接应用于实际场景。

它的核心思想是

  • 希尔排序的分组本质上是用 步长 gap 控制哪些元素属于一个组。

    • 在并着走的实现中,假设 gap = 3
      • 对于索引为 0, 3, 6, 9... 的元素,它们属于第一组。
      • 对于索引为 1, 4, 7, 10... 的元素,它们属于第二组。
      • 对于索引为 2, 5, 8, 11... 的元素,它们属于第三组。
    • 并着走的逻辑是遍历整个数组,隐式地让这些组在同一个循环中排序。
  • gap 的控制下:

    • 每个位置 i 的元素 a[i],都会和同组的前一个元素(位置 i - gap)进行比较。
    • 如果需要交换位置,就不断向前检查,直到找到合适位置。
特性总结
算法复杂度

1.时间复杂度

                最坏情况:O(n^2)(不理想的增量序列)。

                平均情况:O(n^(3/2)) 或更优(根据增量序列)。

                最好情况:接近 O(n)

可以分成内外层来分析

外层循环(控制增量 gap):应该能直接看出来吧,无疑问的O(log(n)),就是增量序列的长度。

内层循环(分组插入排序):

假设⼀共有n个数据,合计gap组,则每组为n / gap个;在每组中,插入移动的次数最坏的情况下为 1 + 2 + 3 + .... + ( n / gap− 1)),⼀共是gap组,因此: 1 + 2 + 3 + .... + ( n / gap− 1))
总计最坏情况下移动总数为: gap ∗ (1 + 2 + 3 + .... + (n / gap − 1 ))
gap取值有(以除3为例):n / 3  n / 9  n / 27 ......  2  1
  • 当gap为n / 3时,移动总数为: n / 3 * (1 + 2) = n
  • 当gap为n / 9时,移动总数为: n / 9 * (1 + 2 + 3 + .... + 8) = (n / 9) * (8 (1 + 8) / 2)= 4n
  • 最后⼀趟,gap=1,即直接插入排序,内层循环排序消耗为n

可知,比较次数是先增加再下降的,或者画一张曲线图更好理解

因此,希尔排序在最初和最后的排序的次数都为n,即前⼀阶段排序次数是逐渐上升的状态,当到达某⼀顶点时,排序次数逐渐下降至n,而该顶点的计算暂时无法给出具体的计算过程
所以,目前其实没有明确的希尔排序的时间复杂度,普遍认为的话是在 O(n^1.3) ,这里我们引用充当教科书较多的 《数据结构(C语言版)》--- 严蔚敏书中给出的时间复杂度的解释

 

2.空间复杂度:使用原地排序,额外空间复杂度为 O(1)

3.稳定性不稳定,因为在分组时可能会打乱相同元素的相对顺序。


优缺点

优点

  1. 简单易实现。
  2. 对中等规模的数组(如 1 万以下)性能较好。
  3. 在基本有序的数组上效率较高。

缺点

  1. 不稳定,不能保证相同元素的顺序。
  2. 对非常大的数组,效率不如快速排序。

增量序列的选择
  • 希尔增量gap = gap / 3 + 1
  • Hibbard增量gap = 2^k - 1
  • Sedgewick增量gap = 9 * 4^i - 9 * 2^i + 1 等。
  • 增量序列的选择会显著影响希尔排序的性能。

适用场景
  1. 数据规模适中(几百到几万)。
  2. 数据分布无规律,但需要排序效率较高的场景。
  3. 对性能要求高,但稳定性不重要的场景。

2.2 选择排序 

每⼀次从待排序的数据元素中选出最小或最大的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

2.2.1 直接选择排序 

直接选择排序(Selection Sort)是一种简单的排序算法,其基本思想是每次从待排序的序列中选择最小(或最大)元素,将其放到已排序序列的末尾。该算法属于交换排序类,通过多次选择最小(或最大)元素并与当前序列中的元素交换来逐步完成排序。

基本思想
  1. 选择最小元素:在每一轮中,找到剩余未排序部分的最小元素。
  2. 交换位置:将找到的最小元素与当前已排序部分的末尾元素交换位置。
  3. 重复:每次排好一个元素后,缩小待排序部分的范围,继续执行选择和交换操作,直到所有元素排序完成。
算法步骤 
  1. 假设数组长度为 n,开始时将整个数组看作未排序部分。
  2. 从第一个元素开始,扫描剩余部分,找到最小的元素。
  3. 将最小元素与当前待排序部分的第一个元素交换。
  4. 重复此过程,直到排序完成。
1. 在元素集合 array[i]--array[n-1] 中选择关键码最大(小)的数据元素
2. 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素
交换
3. 在剩余的 array[i]--array[n-2](array[i+1]--array[n-1]) 集合中,重复上述步骤,直到集合剩余 1 个元素
代码实现
void SelectionSort(int* a, int n) {
    // 外层循环控制已排序部分的末尾
    for (int i = 0; i < n - 1; i++) {
        int minIndex = i;

        // 内层循环在未排序部分中寻找最小值
        for (int j = i + 1; j < n; j++) {
            if (a[j] < a[minIndex]) {
                minIndex = j;  // 记录最小元素的索引
            }
        }

        // 交换最小元素与当前已排序部分的下一个元素
        if (minIndex != i) {
            int temp = a[i];
            a[i] = a[minIndex];
            a[minIndex] = temp;
        }
    }
}
特性总结
算法复杂度

1.时间复杂度

                最坏情况(数组逆序):O(n^2)

                最好情况(数组已排序):O(n^2)(即数组已经排序,选择排序仍需执行完整的循环)

                平均情况O(n^2)

2.空间复杂度原地排序:不需要额外的辅助空间,空间复杂度为 O(1)

3.稳定性不稳定:在排序过程中可能会改变相等元素的相对顺序,因为会交换位置。


优缺点

优点

  1. 简单直观:直接选择排序算法的实现简单,易于理解,适合小规模数据。
  2. 空间效率高:只使用常数级的额外空间,内存开销小。

缺点

  1. 效率低下:由于时间复杂度为 O(n^2),对于大规模数据,性能较差。
  2. 不稳定:相同元素的顺序可能被改变,导致排序不稳定。
  3. 交换次数较多:每次找到最小元素后都会交换,可能导致不必要的交换操作。

适用场景
  1. 数据量较小(如 n <= 100)时,选择排序是一种简单有效的排序方法,适合小规模数据的排序。
  2. 数据本身接近有序时,直接选择排序的性能相对较好,尽管时间复杂度为 O(n^2),但相较于其他 O(n^2) 算法,选择排序的交换次数较少。

2.2.2 堆排序

堆排序(Heap Sort)是一种基于堆数据结构的排序算法,堆是一种完全二叉树,满足堆的性质:

  • 最大堆(Max Heap):父节点的值大于或等于其子节点的值,根节点是最大元素。
  • 最小堆(Min Heap):父节点的值小于或等于其子节点的值,根节点是最小元素。

堆排序利用堆的性质,每次从堆中提取根节点(最大或最小),然后调整堆结构,从而实现排序。

基本思想 
  1. 构建堆:将待排序数组转换成一个堆结构(可以是最大堆或最小堆),通常构建最大堆。
  2. 交换根节点与最后一个节点:将堆顶(最大元素)与堆的最后一个元素交换,这样最大元素就被放置到了正确的位置。
  3. 调整堆:交换后,堆的结构可能被破坏,需要重新调整堆,使其恢复堆的性质。
  4. 重复:将剩下的部分继续调整为堆,再次进行交换,直到所有元素都排序完成。
算法步骤
  1. 建堆:将给定的数组转换成一个最大堆。
  2. 交换根节点和最后一个节点:把堆顶元素(最大值)交换到数组的末尾。
  3. 调整堆:将剩余部分重新调整为最大堆。
  4. 重复交换和调整过程,直到堆的大小减小为1。
代码实现 
#include <stdio.h>

// 调整堆结构
void AdjustDown(int* a, int n, int parent) {
    int child = parent * 2 + 1;  // 左子节点的索引
    while (child < n) {
        // 如果有右子节点,且右子节点更大,则选择右子节点
        if (child + 1 < n && a[child + 1] > a[child]) {
            child++;
        }
        
        // 如果父节点小于最大子节点,则交换
        if (a[child] > a[parent]) {
            int temp = a[parent];
            a[parent] = a[child];
            a[child] = temp;
            parent = child;
            child = parent * 2 + 1;  // 继续向下调整
        } else {
            break;  // 如果父节点大于等于最大子节点,则结束
        }
    }
}

// 堆排序主函数
void HeapSort(int* a, int n) {
    // 建堆(从最后一个非叶子节点开始调整堆)
    for (int i = (n - 1) / 2; i >= 0; --i) {
        AdjustDown(a, n, i);
    }

    // 交换根节点(最大元素)和最后一个元素,然后调整堆
    int end = n - 1;
    while (end > 0) {
        // 交换根节点与堆的最后一个元素
        int temp = a[0];
        a[0] = a[end];
        a[end] = temp;
        
        // 重新调整堆
        AdjustDown(a, end, 0);
        --end;
    }
}

// 打印数组
void PrintArray(int* a, int n) {
    for (int i = 0; i < n; ++i) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

int main() {
    int arr[] = {4, 10, 3, 5, 1};
    int n = sizeof(arr) / sizeof(arr[0]);

    HeapSort(arr, n);
    PrintArray(arr, n);

    return 0;
}
堆排序的步骤演示

假设我们有一个数组 [4, 10, 3, 5, 1],我们来逐步演示堆排序的过程。

1.建堆:首先将数组转换为最大堆:

      AdjustDown 会从最后一个非叶子节点开始,调整堆结构。

                经过调整,最大堆应该是 [10, 5, 3, 4, 1]

2.交换根节点和最后一个元素:交换根节点 10 和数组末尾的元素 1,得到 [1, 5, 3, 4, 10]

                通过 AdjustDown 调整堆,使其重新恢复堆的性质,得到 [5, 4, 3, 1, 10]

3.再次交换根节点和最后一个元素:交换根节点 5 和倒数第二个元素 1,得到 [1, 4, 3, 5, 10]

                通过 AdjustDown 调整堆,得到 [4, 1, 3, 5, 10]

4.重复:继续交换并调整堆,直到整个数组排好序:

                交换后得到 [3, 1, 4, 5, 10]

                调整后得到 [3, 1, 4, 5, 10]

                最终得到排序结果 [1, 3, 4, 5, 10]

特性总结
算法复杂度

1.时间复杂度

                最坏情况(数组逆序):O(n log n)

                最好情况(数组已排序):O(n log n)

                平均情况O(n log n)

2.空间复杂度原地排序:堆排序不需要额外的辅助空间,空间复杂度为 O(1)

3.稳定性不稳定:堆排序在排序过程中可能改变相等元素的相对顺序,因此是一个不稳定的排序算法。


优缺点

优点

  1. 时间复杂度稳定:无论在最坏、最好还是平均情况下,堆排序的时间复杂度始终为 O(n log n),表现稳定。
  2. 原地排序:堆排序只使用常数级额外空间,空间复杂度为 O(1),内存开销小。
  3. 适用于大规模数据:由于堆排序的时间复杂度较为稳定,因此适合用于处理大规模数据的排序任务。

缺点

  1. 不稳定:堆排序不保持相等元素的相对顺序,因此不适用于需要稳定排序的场景。
  2. 常数因子较大:虽然时间复杂度为 O(n log n),但堆排序的常数因子较大,通常会比其他如快速排序的实际性能稍差。

适用场景
  1. 大规模数据的排序:堆排序在处理大数据时较为稳定,尤其是在对时间复杂度有较高要求时。
  2. 内存有限的情况:堆排序是原地排序,不需要额外的内存,适用于内存受限的情况。
  3. 需要稳定时间复杂度的场景:当不关心排序的稳定性时,堆排序是一个不错的选择,尤其是在无法预测输入数据分布的情况下。

下一章应该是介绍冒泡和快速排序(

那几种快速排序够写很多了(

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

洛谷刷题之p1631

序列合并 题目入口 题目描述 有两个长度为 N N N 的单调不降序列 A , B A,B A,B&#xff0c;在 A , B A,B A,B 中各取一个数相加可以得到 N 2 N^2 N2 个和&#xff0c;求这 N 2 N^2 N2 个和中最小的 N N N 个。 输入格式 第一行一个正整数 N N N&#xff1b; 第二…

【漏洞复现】CVE-2022-24697

漏洞信息 NVD - CVE-2022-24697 Kylin’s cube designer function has a command injection vulnerability when overwriting system parameters in the configuration overwrites menu. RCE can be implemented by closing the single quotation marks around the parameter…

非常简单实用的前后端分离项目-仓库管理系统(Springboot+Vue)part 2

七、创建前端项目 你下载了nodejs吗&#xff1f;从cn官网下载&#xff1a;http://nodejs.cn/download/&#xff0c;或者从一个国外org网站下载&#xff0c;选择自己想要的版本https://nodejs.org/download/release/&#xff0c;双击下载好的安装文件&#xff0c;选择安装路径安…

应急响应靶机——Windows近源攻击

载入虚拟机&#xff0c;开启虚拟机&#xff0c;点击“解题.exe”&#xff1a; &#xff08;账户密码&#xff1a;Administrator/zgsf2024&#xff09; 1、攻击者的外网IP地址 2、攻击者的内网跳板IP地址 3、攻击者使用的限速软件的md5大写 4、攻击者的后门md5大写 5、攻击…

用两个栈实现队列 剑指offer

题目描述 用两个栈实现一个队列。队列声明如下图&#xff0c;请实现它的两个函数appendTail和deleteHead,分别完成在队尾插入节点和队头删除节点的功能。 代码实现 测试用例 相关题目

超详细ensp配置VRRP和MSTP协议

一、简介 1、什么是VRRP&#xff1a; &#xff08;1&#xff09;VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;的概念&#xff1a; VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;指的是一种实现路由器冗余备份的协议&#xff0c;常用于…

嵌入式Linux开发4——文件类型2

目录 使用stat查明文件类型 stat 命令 stat() 系统调用 struct stat 结构体 常见字段和它们的含义 fstat 函数 示例&#xff1a; lstat 函数 区别总结 使用场景 stat、fstat 和 lstat 比较 链接 硬链接 硬链接的特性 创建硬链接 硬链接的优缺点 符号链接&#…

模电期末笔记 (包过版)

文章目录 一、直流电路公式题型一&#xff1a;电压源与电流源求电压&#xff0c;电流&#xff0c;功率题型二&#xff1a;基尔霍夫定律求电压&#xff0c;电流题型三: 理想电源的等效变换题型四&#xff1a;求复杂电路的电压&#xff0c;电流&#xff0c;电功率**题型五&#x…

C# 常量

文章目录 前言一、整数常量&#xff08;一&#xff09;合法与非法实例对比&#xff08;二&#xff09;不同进制及类型示例 二、浮点常量三、字符常量四、字符串常量五、定义常量 前言 在 C# 编程的世界里&#xff0c;常量是一类特殊的数据元素&#xff0c;它们如同程序中的 “定…

C++11新增的特性

一.列表初始化/{}初始化 回顾&#xff1a;C98中⼀般数组和结构体可以⽤{}进⾏初始化。 1.C11中&#xff0c;一切对象皆可用{}初始化&#xff0c;内置类型⽀持&#xff0c;⾃定义类型也⽀持&#xff08;⾃定义类型本质是类型转换&#xff0c;中间会产⽣临时对象&#xff0c;最…

SAP学习

1、概述 2、SD 2.1 销售中的企业结构 2.2流程概览

Linux之网络基础

网络发展 网络的发展可以从人与人之间的工作模式开始谈起, 人与人的工作模式反应了机器与机器的工作模式: 1. 独立模式: 在网络发展的早期计算机间处于独立模式, 计算机之间相互独立 最开始计算机之间是独立运行的, 数据之间的交互需要人用软盘等存储介质拷贝过去, 一般涉及…

数字图像处理(9):VGA接口及其时序

&#xff08;1&#xff09;特点&#xff1a;成本低、结构简单、应用灵活 VGA接口需要五个信号&#xff1a;R、G、B、Hsync、Vsync &#xff08;2&#xff09;VGA的工作原理&#xff1a; 设定一个高速时钟信号&#xff08;像素时钟&#xff09;来控制每个像素的传输速率&#…

111. UE5 GAS RPG 实现角色技能和场景状态保存到存档

实现角色的技能存档保存和加载 首先&#xff0c;我们在LoadScreenSaveGame.h文件里&#xff0c;增加一个结构体&#xff0c;用于存储技能相关的所有信息 //存储技能的相关信息结构体 USTRUCT(BlueprintType) struct FSavedAbility {GENERATED_BODY()//需要存储的技能UPROPERT…

【jmeter】服务器使用jmeter压力测试(从安装到简单压测示例)

一、服务器上安装jmeter 1、官方下载地址&#xff0c;https://jmeter.apache.org/download_jmeter.cgi 2、服务器上用wget下载 # 更新系统 sudo yum update -y# 安装 wget 以便下载 JMeter sudo yum install wget -y# 下载 JMeter 压缩包&#xff08;使用 JMeter 官方网站的最…

图像算法在生物医药领域的应用

摘要&#xff1a; 随着科技的飞速发展&#xff0c;图像算法在生物医药领域的应用日益广泛且深入。本文详细阐述了图像算法在生物医药多个方面的应用&#xff0c;包括医学影像诊断、病理图像分析、药物研发、细胞图像研究以及生物医学工程等。通过对这些应用的探讨&#xff0c;展…

注意力(Attention)机制详解(附代码)

Attention机制是深度学习中的一种技术&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;和计算机视觉领域中得到了广泛的应用。它的核心思想是模仿人类的注意力机制&#xff0c;即人类在处理信息时会集中注意力在某些关键部分上&#xff0c;而忽略其他不那么重要的…

Jmeter测试nginx部署的静态网页最大在线人数

一、下载Jmeter apache-jmeter-5.4.3.tar资源-CSDN文库 解压之后&#xff0c;双击ApacheJMeter.jar,即可打开 二、测试最大在线人数 1、plugins-manager下载安装 起初刚解压的jmeter里面没有插件管理这个选项 去官网下载&#xff1a;Install :: JMeter-Plugins.org 将下载j…

【深度学习|目标跟踪】StrongSort 详解(以及StrongSort++)

StrongSort详解 1、论文及源码2、DeepSort回顾3、StrongSort的EMA4、StrongSort的NSA Kalman5、StrongSort的MC6、StrongSort的BOT特征提取器7、StrongSort的AFLink8、未完待续 1、论文及源码 论文地址&#xff1a;https://arxiv.org/pdf/2202.13514 源码地址&#xff1a;https…

Scala关于成绩的常规操作

score.txt中的数据&#xff1a; 姓名&#xff0c;语文&#xff0c;数学&#xff0c;英语 张伟&#xff0c;87&#xff0c;92&#xff0c;88 李娜&#xff0c;90&#xff0c;85&#xff0c;95 王强&#xff0c;78&#xff0c;90&#xff0c;82 赵敏&#xff0c;92&#xff0c;8…