考研数据结构--排序算法汇总,代码完整可实现

在考研中,经常会考到各种排序算法,所以总结一下,以便复习。

各类排序的时间复杂度和空间复杂度概览;

1. 直接插入排序

其基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表。

特性

  1. 时间复杂度
  • 最好情况就是全部有序,此时只需遍历一次,最好的时间复杂度为 O(n)
  • 最坏情况全部反序,内层每次遍历已排序部分,最坏时间复杂度为 O(n^2)
  • 综上,因此直接插入排序的平均时间复杂度为 O(n^2)

2.空间复杂度

  • 辅助空间是常量
  • 平均的空间复杂度为:O(1)

3.算法稳定性

  • 判断标准:相同元素的前后顺序是否改变
  • 插入到比它大的数前面,所以直接插入排序是稳定的

4. 完整可实现代码

c++ 复制代码
#include <bits/stdc++.h>

using namespace std;
// 直接插入排序
// 其基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表
void InsertSort(int a[], int l) {
    int temp;
    int j;
    // 先看第一个数,将数组划分为有序和无序部分,第一个数默认有序。
    for (int i = 1; i < l; i++) {
        // 取出无序部分的首个,在有序部分从后向前比较,插入到合适的位置
        if (a[i] < a[i - 1]) {
            temp = a[i];  // temp暂存需要插入的数
            for (j = i - 1; j >= 0 && temp < a[j]; j--) {
                a[j + 1] = a[j];  // 取出原序列中大于暂存的数,往后移
            }  // 循环结束后,已经找到需要插入元素的位置
            a[j + 1] = temp;  // 将该位置插入元素
        }
        cout << "第" << i << "次插入:";
        for (int k = 0; k < l; k++) {
            cout << a[k] << " ";
        }
        cout << endl;
    }
}

int main() {
    int a[10] = {2, 5, 8, 3, 6, 9, 1, 4, 7};
    int b[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int len = 9;
    InsertSort(a, len);
    return 0;
}

2. 折半插入排序

  1. 特性
  • 时间复杂度:

折半查找只是减少了比较次数,但是元素的移动次数不变,所以时间复杂度为O(n^2)

  • 空间复杂度

平均的空间复杂度也是:O(1)

  1. 稳定性: 稳定的排序算法
c++ 复制代码
#include <bits/stdc++.h>

using namespace std;

void BInsertSort(int a[], int l) {
    int temp;
    int low, high;
    int m;
    for (int i = 1; i < l; i++) {
        // 取出无序部分的首个,在有序部分二分查找到位置
        if (a[i] < a[i - 1]) {
            low = 0;
            high = i - 1;
            // 在前面有序的部分进行二分查找
            while (low <= high) {
                m = low + (high - low) / 2;
                if (a[m] > a[i])  // 有序部分的中间数,大于无序部分的首个元素
                    high = m - 1;
                else
                    low = m + 1;  // low的位置最终为小于等于a[i]的数
            }
            temp = a[i];  // 暂存需要插入的元素
            // 遍历,将元素向右移,找到插入的位置
            for (int j = i; j > low; j--) {
                a[j] = a[j - 1];
            }
            a[low] = temp;  // 在找到的位置进行赋值
        }
        cout << "第" << i << "次插入:";
        for (int k = 0; k < l; k++) {
            cout << a[k] << " ";
        }
        cout << endl;
    }
}

int main() {
    int a[10] = {2, 5, 8, 3, 6, 9, 1, 4, 7};
    int b[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int len = 9;
    BInsertSort(a, len);
    return 0;
}

3. 折半查找

也称二分查找,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
// 也称二分查找,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列
int BinarySearch(int a[], int low, int high, int target) {
    // 最终low与high会合并(注意合并时也要比较),按照规律,此时high会到low前面,这时才可以确定没有,所以这个循环的条件就是low<=high
    while (low <= high) {
        int mid = low + (high - low) / 2;  // 溢出问题
        cout << "low:" << low << " high:" << high << " mid:" << mid << endl;
        if (a[mid] >
            target) {  // 将两个数进行比较,然后缩小查找范围,。当中间数大于查找数时,往左边找
            high = mid - 1;
        } else if (a[mid] < target) {  // 中间数小于查找数时,往右边找
            low = mid + 1;
        } else {  // 相等时,直接返回
            return mid;
        }
    }
    return -1;
}

int main() {
    int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int len = 9;
    cout << BinarySearch(a, 0, len - 1, 3) << endl;
    return 0;
}

4. 希尔排序

是插入排序的一种又称"缩小增量排序"(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。

特性 1.时间复杂度 对于这个算法有两个常见结果 O ( n^2 ) O(n^1.5)

2.空间复杂度 和直接插入一样 平均的空间复杂度为:O(1)

3.算法稳定性 相同元素的前后顺序改变

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;

void ShellSort(int a[], int len) {
    int temp;
    int j;
    int gap = len / 2;
    int index = 0;  // 增加增量
    while (gap)     // 多组
    {
        for (int i = gap; i < len; i++)  // 直接从组内第二个判起
        {
            //  是否需要变,比如第一步的2和9位置不需要改变
            if (a[i] < a[i - gap]) {
                index++;
                cout << "第" << index << "次交换" << a[i] << "和" << a[i - gap]
                     << "后:";
                temp = a[i];  // 取出改变值,就是需要交换位置,更大的那个数
                // 需要交换位置的数,小于大的数,还要保证下标大于等于0,
                for (j = i - gap; j >= 0 && temp < a[j]; j = j - gap)  // 找位置
                {
                    a[j + gap] = a[j];  // 右移
                }
                a[j + gap] = temp;  // 插入
                for (int k = 0; k < len; k++)
                    cout << a[k] << " ";
                cout << endl;
            }
        }
        gap /= 2;
    }
}

int main() {
    int a[10] = {2, 5, 8, 3, 6, 9, 1, 4, 7, 0};
    int b[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int len = 10;
    ShellSort(a, len);
    return 0;
}

5. 冒泡排序

是一种简单的排序算法

由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名"冒泡排序"。

特性

  1. 时间复杂度
  • 最好情况就是全部有序,此时只需遍历一次,因此冒泡排序最好的时间复杂度为O(n)
  • 最坏情况全部反序,两重for循环全部执行,因此冒泡排序的最坏时间复杂度为 O(n^2)

综上,因此冒泡排序总的平均时间复杂度为O(n^2)

  1. 空间复杂度
  • 最优的空间复杂度就是不需要借用第三方内存空间,则复杂度为0
  • 最差的空间复杂度就是开始元素逆序排序,每次都要借用一次内存,按照实际的循环次数,为O(n)

平均的空间复杂度为:O(1)

  1. 算法稳定性
  • 相同元素的前后顺序是否改变, 因为只交换不同大小的,所以冒泡排序是稳定的
c++ 复制代码
#include <iostream>
using namespace std;
void BubbleSort(int a[], int l) {
    int ans;
    int temp;
    int index;
    for (int i = l - 1; i >= 1; i--)  // 一重循环,n-1次
    {
        ans = 1;
        for (int j = 1; j <= i; j++)  // 第二个数到未排序数
        {
        //大的往后提
            if (a[j - 1] > a[j]) {
                ans = 0;  // 有未排序的
                //                temp = arr[j];
                //                arr[j] = arr[j + 1];
                //                arr[j + 1] = temp;
                swap(a[j], a[j - 1]);  // 交换

                cout << "第" << ++index << "次排序:";
                for (int k = 0; k < l; k++)  // 打印数组
                {
                    cout << a[k] << " ";
                }
                cout << endl;
            }
        }
        if (ans)  // 额外标记
            break;
    }
}
int main() {
    int a[20] = {2, 5, 8, 3, 6, 9, 1, 4, 7};
    int b[20] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
    int len = 9, temp;
    BubbleSort(a, len);
    return 0;
}

6. 快速排序

快速排序的基本思想是:通过一次排序将要排序的数据分成两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后,再按此方法对这两部分数据分别进行快速排序,直到有序。

  1. 算法设计

(1)分解: 先从数列中取出一个元素作为基准元素。以基准元素为标准,将问题分解为两个子序列,使小于或者等于基准元素的子序列在左侧,使大于基准元素的子序列在右侧。

(2)治理 : 对两个子序列进行快速排序(递归快速排序)。

(3)合并: 将排好的两个子序列合并在一起,得到原问题的解。

(4)基准元素的选取:

①:取第一个元素。(通常选取第一个元素)

②:取最后一个元素

③:取中间位置的元素

④:取第一个、最后一个、中间位置元素三者之中位数

⑤:取第一个和最后一个之间位置的随机数 k (low<=k<=hight)

  1. 快速排序的情况比较棘手,在最糟情况下,其运行时间为O(n2)。在平均情况下,快速排序的运行时间为O(nlogn)。
c++ 复制代码
#include <bits/stdc++.h>
using namespace std;

// 快速排序(从小到大)
void quickSort(int left, int right, int arr[]) {
    if (left >= right)
        return;
    int i, j, base, temp;
    i = left,
    j = right;  // 把待排序数组元素的第一个和最后一个下标分别赋值给i,j,使用i,j进行排序;
                // 将待排序数组的第一个元素作为哨兵,将数组划分为大于哨兵以及小于哨兵的两部分
    base = arr[left];  // 取最左边的数为基准数
    while (i < j) {
        while (arr[j] >= base && i < j)
            j--;
        while (arr[i] <= base && i < j)
            i++;
        if (i < j) {
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    // 基准数归位
    arr[left] = arr[i];
    arr[i] = base;
    quickSort(left, i - 1, arr);   // 递归左边
    quickSort(i + 1, right, arr);  // 递归右边
}
void print(int a[], int n) {
    for (int j = 0; j < n; j++) {
        cout << a[j] << "  ";
    }
    cout << endl;
}
int main() {
    int a[10] = {8, 1, 9, 7, 2, 4, 5, 6, 10, 3};
    cout << "初始序列:";
    print(a, 10);
    quickSort(0, 9, a);
    cout << "排序结果:";
    print(a, 10);
    return 0;
}

7. 简单选择排序

特性

1.时间复杂度:O(n^2)

2.空间复杂度:平均的空间复杂度为:O(1)

3.算法稳定性: 不稳定

可实现代码

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;

void SelectSort(int a[], int len) {
    int k;
    for (int i = 0; i < len - 1; i++)  // 未排序第一个数
    {
        k = i;                             // 取第一个数
        for (int j = i + 1; j < len; j++)  // 遍历未排序部分
        {
            if (a[j] < a[k]) {
                k = j;  // 取更小
            }
        }
        if (i != k)  // 不在未排序第一的位置
        {
            swap(a[k], a[i]);
        }
        cout << "第" << i + 1 << "次排序后";
        for (int t = 0; t < len; t++)
            cout << a[t] << " ";
        cout << endl;
    }
};
int main() {
    int a[9] = {2, 7, 8, 3, 7, 9, 1, 3, 7};
    int len = 9;
    SelectSort(a, len);

    return 0;
}

8. 堆排序

  1. 什么是堆 首先堆heap是一种数据结构,是一棵完全二叉树且满足性质:所有非叶子结点的值均不大于或均不小于其左、右孩子结点的值.
  2. 下面通过一组数据说明堆排序的方法: 9, 79, 46, 30, 58, 49

基本过程:

  1. 先将待排序的数视作完全二叉树(按层次遍历顺序进行编号, 从0开始),如下图:
  1. 完全二叉树的最后一个非叶子节点,也就是最后一个节点的父节点。
  • 最后一个节点的索引为数组长度len-1,那么最后一个非叶子节点的索引应该是为(len-1)/2.也就是从索引为2的节点开始
  • 如果其子节点的值大于其本身的值。则把他和较大子节点进行交换,即将索引2处节点和索引5处元素交换。交换后的结果如图:

建堆从最后一个非叶子节点开始即可

3:向前处理前一个节点,也就是处理索引为1的节点,此时79>30,79>58,因此无需交换。

  1. 向前处理前一个节点,也就是处理索引为0的节点,此时9 < 79,9 < 49, 因此需交换。应该拿索引为0的节点与索引为1的节点交换,因为79>49. 如图:
  1. 如果某个节点和它的某个子节点交换后,该子节点又有子节点,系统还需要再次对该子节点进行判断。如上图因为1处,3处,4处中,1处的值大于3,4处的值,所以还需交换。

牢记: 将每次堆排序得到的最大元素与当前规模的数组最后一个元素交换。

6. 完整可实现代码

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
/*
           8
      1         14
   3    21    5    7
10
*/
void adjust(int arr[], int len, int index) {
    int left = 2 * index + 1;
    int right = 2 * index + 2;
    int maxIdx = index;
    if (left < len &&
        arr[left] >
            arr[maxIdx])  // 左边的小标小于总的数组长度,和左边的值小于传入索引的值
        maxIdx = left;    // 记录大值的索引
    if (right < len && arr[right] > arr[maxIdx])
        maxIdx = right;   // maxIdx是3个数中最大数的下标
    if (maxIdx != index)  // 如果maxIdx的值有更新
    {
        swap(arr[maxIdx], arr[index]);
        adjust(arr, len, maxIdx);  // 递归调整其他不满足堆性质的部分
    }
}
void heapSort(int arr[], int size) {
    for (int i = size / 2 - 1; i >= 0;
         i--) {  // 对每一个非叶结点进行堆调整(从最后一个非叶结点开始)
        adjust(arr, size, i);  // i为调整元素的下标
    }
    for (int i = size - 1; i >= 1; i--) {
        swap(arr[0], arr[i]);  // 将当前最大的放置到数组末尾
        adjust(arr, i, 0);  // 将未完成排序的部分继续进行堆排序
    }
}

int main() {
    int array[8] = {8, 1, 14, 3, 21, 5, 7, 10};
    heapSort(array, 8);
    for (auto it : array) {
        cout << it << " ";
    }
    return 0;
}

其实整个堆排序过程中, 我们只需重复做两件事:

  • 建堆(初始化+调整堆, 时间复杂度为O(n);
  • 拿堆的根节点和最后一个节点交换(siftdown, 时间复杂度为O(n*log n);

因而堆排序整体的时间复杂度为O(n*log n).

9. 归并排序

  1. 归并排序是比较稳定的排序方法。
  • 它的基本思想是把待排序的元素分解成两个规模大致相等的子序列。
  • 如果不易分解,将得到的子序列继续分解,直到子序列中包含的元素个数为1。
  • 因为单个元素的序列本身就是有序的,此时便可以进行合并,从而得到一个完整的有序序列。
  1. 流程图示例
  • 首先我们先给定一个无序的数列(42,15,20,6,8,38,50,12),我们进行合并排序数列,如下图流程图所示:

思路:

  • 步骤一:首先将待排序的元素分成大小大致相同的两个序列。

  • 步骤二:再把子序列分成大小大致相同的两个子序列。

  • 步骤三:如此下去,直到分解成一个元素停止,这时含有一个元素的子序列都是有序的。

  • 步骤四:进行合并操作,将两个有序的子序列合并为一个有序序列,如此下去,直到所有的元素都合并为一个有序序列。

解释一下int *

在C++中,"int * a"通常表示一个整型指针。这是一个指针变量,它存储的是整型变量的地址。

举个例子,假设我们有一个整数变量 int num = 5;,如果我们声明一个指针变量 int * a; 并使其指向 num,那么 a = &num;a = num;(此处是取地址运算符的应用)之后,a 就存储了 num 的地址。

之后,我们可以通过解引用操作符 * 来访问 num 的值,如 cout << *a; 就会输出 5。因为我们把 a 理解为存储了 num 的地址,解引用操作符 * 就是取出该地址处存储的值。

此外,如果我们声明了一个指针数组,例如 int * a[5];,那么 a 就存储了五个整型指针的地址,每个整型指针都可以存储一个整型变量的地址。

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
void merge(int* a, int low, int mid, int hight)  // 合并函数
{
    cout << "a: " << *a << endl;
    cout << "low: " << low << endl;
    cout << "mid: " << mid << endl;
    cout << "hight: " << hight << endl;

    // 用 new 申请一个辅助函数,创建一个新的动态数组,用于存放合并后的有序数组。
    int* b = new int[hight - low + 1];
    int i = low, j = mid + 1, k = 0;  // k为 b 数组的小标
    cout << "a[i]: " << a[i] << endl;
    cout << "a[j]: " << a[j] << endl;
    while (i <= mid && j <= hight) {
        if (a[i] <= a[j]) {
            b[k++] = a[i++];  // 按从小到大存放在 b 数组里面
        } else {
            b[k++] = a[j++];
        }
    }
    while (i <= mid)  // j 序列结束,将剩余的 i 序列补充在 b 数组中
    {
        b[k++] = a[i++];
    }
    while (j <= hight)  // i 序列结束,将剩余的 j 序列补充在 b 数组中
    {
        b[k++] = a[j++];
    }
    k = 0;                              // 从小标为 0 开始传送
    for (int i = low; i <= hight; i++)  // 将 b 数组的值传递给数组 a
    {
        a[i] = b[k++];
    }
    delete[] b;  // 辅助数组用完后,将其的空间进行释放(销毁)
}
void mergesort(int* a, int low, int hight)  // 归并排序
{
    if (low < hight) {
        int mid = (low + hight) / 2;
        mergesort(a, low, mid);        // 对 a[low,mid]进行排序
        mergesort(a, mid + 1, hight);  // 对 a[mid+1,hight]进行排序

        merge(a, low, mid, hight);  // 进行合并操作
    }
}
int main() {
    int a[9] = {2, 4, 8, 3, 565, 9, 1, 56, 7};
    int n = 9;
    mergesort(a, 0, n - 1);
    cout << "归并排序结果:" << endl;
    for (int i = 0; i < n; i++) {
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}

10. 基数排序

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。基数排序基于计数排序。

图像过程:

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;

int maxBit(vector<int> vec) {
    int max = vec[0];
    for (int i = 1; i < vec.size(); i++) {
        if (vec[i] > max)
            max = vec[i];
    }
    int p = 1;
    while (max / 10 != 0) {
        max = max / 10;
        p++;
    }
    return p;
}
vector<int> countSort(vector<int> vec,
                      int place) {  // 按指定位置的值进行计数排序
    vector<int> temp(vec);          // 临时数组,存储place位置的值
    vector<int> ordered(vec);       // 排好序的数组放进ordered
    int count[10] = {0};
    for (int i = 0; i < vec.size(); i++) {
        // 找到每个元素place位置上的数字存在temp中
        temp[i] = (int)(vec[i] / pow(10, place - 1)) % 10;
    }
    for (int i = 0; i < vec.size(); i++) {
        count[temp[i]]++;  // 统计数字出现的频率
    }
    for (int i = 1; i < 10; i++) {
        // 此时count中存放着temp中每个数字的索引
        count[i] = count[i] + count[i - 1];
    }
    for (int i = vec.size() - 1; i >= 0; i--) {
        int index = count[temp[i]] - 1;
        count[temp[i]]--;
        ordered[index] = vec[i];
    }
    // cout << "next:" << endl;

    return ordered;
}
void radixSort(vector<int>& vec) {
    // 最长位数是多少,代表要进行几次排序
    int maxbit = maxBit(vec);
    // i为多少,代表按第几位数字比较(从右向左)
    for (int i = 1; i <= maxbit; i++) {
        vec = countSort(vec, i);
    }
    for (int i = 0; i < vec.size(); i++) {
        cout << vec[i] << "  ";
    }
}
int main() {
    // vector<int> 是 C++
    // 标准模板库(STL)中的一个模板类,它表示一个动态数组,可以存储整数类型(int)的数据。
    // 具体来说,vector<int>
    // 是一个可以动态改变大小的数组,它提供了方便的接口来管理数组中的元素。你可以通过
    // push_back() 方法添加元素,通过 erase()
    // 方法删除元素,也可以通过下标访问或者迭代器访问元素。
    vector<int> vec{3, 5, 34, 10, 8, 6,  16, 5, 8, 6, 2, 4, 900, 4, 7,
                    0, 1, 8,  9,  7, 38, 1,  2, 5, 9, 7, 4, 0,   2, 6};
    radixSort(vec);
    return 0;
}

11. 计数排序

当待排序数组中的元素是某个区间的整数时,可以使用计数排序。

  • 其基本思想就是对每一个输入元素,确定出小于x的元素个数。有了这一信息,就可以把x直接放到它在最终输出数组中的位置上。
  • 例如,如果有17个元素小于x,则x就属于第18个输出位置。
c++ 复制代码
/*算法:计数排序*/

#include <cstring>
#include <iostream>
using namespace std;

/***************************************************************************
    1.计数排序法,仅可用于正整数排序。
    2.计数排序的基本思想就是对每一个输入元素x,确定出小于x的元素个数。
    有了这一信息,就可以把x直接放到它在最终输出数组中的位置上。
    3.例如,如果有17个元素小于x,则x就属于第18个输出位置。
    4.当排序的数较为稠密时,所需的辅助空间较小。
****************************************************************************/
bool ctsort(int A[], int size) {
    if (NULL == A || size < 0)
        return false;
    /*寻找数组A中的最大整数k*/
    int k = A[0];
    for (int i = 1; i < size; i++)
        if (A[i] > k)
            k = A[i];
    k++;  // 最大整数+1

    // 申请数组,使counts数组最大下标对应A中的最大整数
    int* counts = new int[k];
    int* tmp = new int[size];  // 存放排序的结果

    // 初始化counts数组
    for (int i = 0; i < k; i++)
        counts[i] = 0;

    // counts[i]表示数字i在data中的个数
    for (int i = 0; i < size; i++)
        counts[A[i]] = counts[A[i]] + 1;

    // 将counts累计起来,这样counts[i]表示小于等于i的元素个数
    for (int i = 1; i < k; i++)
        counts[i] = counts[i] + counts[i - 1];

    // 从后往前开始数A中元素排序
    for (int i = size - 1; i >= 0; i--) {
        // counts[data[j]]表示当前小于等于数据data[j]的元素个数,counts[data[j]]
        // -1则将其转换为temp中的位置
        tmp[counts[A[i]] - 1] = A[i];
        counts[A[i]] = counts[A[i]] - 1;
    }
    memcpy(A, tmp, size * sizeof(int));
    delete[] counts;
    delete[] tmp;
    return true;
}

int main() {
    int A[] = {9, 3, 7, 4, 5, 2, 1};  // 测试用例1
    // int A[] = {9,3,7,4,5,2,7};//测试用例2
    ctsort(A, 7);
    for (int i = 0; i < 7; i++)
        cout << A[i] << " ";
}
相关推荐
睡不着还睡不醒44 分钟前
【数据结构强化】应用题打卡
算法
sp_fyf_20241 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-05
人工智能·深度学习·神经网络·算法·机器学习·语言模型·自然语言处理
C++忠实粉丝2 小时前
前缀和(6)_和可被k整除的子数组_蓝桥杯
算法
木向2 小时前
leetcode42:接雨水
开发语言·c++·算法·leetcode
TU^2 小时前
C语言习题~day16
c语言·前端·算法
吃什么芹菜卷2 小时前
深度学习:词嵌入embedding和Word2Vec
人工智能·算法·机器学习
wclass-zhengge2 小时前
数据结构与算法篇(树 - 常见术语)
数据结构·算法
labuladuo5202 小时前
AtCoder Beginner Contest 372 F题(dp)
c++·算法·动态规划
夜雨翦春韭2 小时前
【代码随想录Day31】贪心算法Part05
java·数据结构·算法·leetcode·贪心算法
hsling松子7 小时前
使用PaddleHub智能生成,献上浓情国庆福
人工智能·算法·机器学习·语言模型·paddlepaddle