C++常见十种排序方式

目录

前言

1、选择排序

介绍

参考代码

2、冒泡排序

        介绍

        参考代码

3、插入排序

        介绍

        参考代码 

4、希尔排序 

        介绍

        参考代码 

5、快速排序

        介绍

        参考代码 

6、并归排序

        介绍

        参考代码 

7、堆排序

        介绍

        参考代码

8、基数排序 

        介绍

          参考代码

9、计数排序

        介绍

        参考代码

10、桶排序 

        介绍

        参考代码 

总结


前言

        本期我们将学习C++常见的十种排序方式,它们的优缺点作者都会写在这里。

        排序(Sorting)是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个项值有序的序列。

        常见的快速排序、归并排序、堆排序以及冒泡排序等都属于比较类排序算法。比较类排序是通过比较来决定元素间的相对次序,由于其时间复杂度不能突破,因此也称为非线性时间比较类排序。在冒泡排序之类的排序中,问题规模为 O(n^2)。在归并排序、快速排序之类的排序中,问题规模通过分治法消减为 log n次,所以时间复杂度平均 O(nlogn)

        比较类排序的优势是,适用于各种规模的数据,也不在乎数据的分布,都能进行排序。可以说,比较排序适用于一切需要排序的情况。

        而计数排序、基数排序、桶排序则属于非比较类排序算法。非比较排序不通过比较来决定元素间的相对次序,而是通过确定每个元素之前,应该有多少个元素来排序。由于它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。非比较排序只要确定每个元素之前的已有的元素个数即可,所有一次遍历即可解决。算法时间复杂度O(n).

        非比较排序时间复杂度低,但由于非比较排序需要占用空间来确定唯一位置。所以对数据规模和数据分布有一定的要求。


1、选择排序

介绍

        选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。

        每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完即可。实际上,我们可以一趟选出两个值,一个最大值一个最小值,然后将其放在序列开头和末尾,这样可以使选择排序的效率快一倍。

时间复杂度:最坏情况:O(n^2)
                      最好情况:O(n^2)
空间复杂度:O(1)

参考代码

//选择排序
void swap(int* a, int* b)
{int tem = *a;*a = *b;*b = tem;
}
void SelectSort(int* arr, int n)
{//保存参与单趟排序的第一个数和最后一个数的下标int begin = 0, end = n - 1;while (begin < end){//保存最大值的下标int maxi = begin;//保存最小值的下标int mini = begin;//找出最大值和最小值的下标for (int i = begin; i <= end; ++i){if (arr[i] < arr[mini]){mini = i;}if (arr[i] > arr[maxi]){maxi = i;}}//最小值放在序列开头swap(&arr[mini], &arr[begin]);//防止最大的数在begin位置被换走if (begin == maxi){maxi = mini;}//最大值放在序列结尾swap(&arr[maxi], &arr[end]);++begin;--end;}
}

2、冒泡排序

       

        介绍

        冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

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

        左边大于右边交换一趟排下来最大的在右边。

时间复杂度:最坏情况:O(n^2)
      最好情况:O(n)
空间复杂度:
O(1)

        

        参考代码

//冒泡排序
void BubbleSort(int* arr, int n)
{int end = n;while (end){int flag = 0;for (int i = 1; i < end; ++i){if (arr[i - 1] > arr[i]){int tem = arr[i];arr[i] = arr[i - 1];arr[i - 1] = tem;flag = 1;}}if (flag == 0){break;}--end;}
}

3、插入排序

        介绍

        插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动 。

        在待排序的元素中,假设前n-1个元素已有序,现将第n个元素插入到前面已经排好的序列中,使得前n个元素有序。按照此法对所有元素进行插入,直到整个序列有序。
  但我们并不能确定待排元素中究竟哪一部分是有序的,所以我们一开始只能认为第一个元素是有序的,依次将其后面的元素插入到这个有序序列中来,直到整个序列有序为止。

时间复杂度:最坏情况下为O(N*N),此时待排序列为逆序,或者说接近逆序
      最好情况下为O(N),此时待排序列为升序,或者说接近升序。
空间复杂度:O(1)
 

        参考代码 

void InsertSort(int* arr, int n)
{for (int i = 0; i < n - 1; ++i){//记录有序序列最后一个元素的下标int end = i;//待插入的元素int tem = arr[end + 1];//单趟排while (end >= 0){//比插入的数大就向后移if (tem < arr[end]){arr[end + 1] = arr[end];end--;}//比插入的数小,跳出循环else{break;}}//tem放到比插入的数小的数的后面arr[end  + 1] = tem;//代码执行到此位置有两种情况://1.待插入元素找到应插入位置(break跳出循环到此)//2.待插入元素比当前有序序列中的所有元素都小(while循环结束后到此)}
}


4、希尔排序 

        介绍

     

        希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。

        希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。 

        希尔排序,先将待排序列进行预排序,使待排序列接近有序,然后再对该序列进行一次插入排序,此时插入排序的时间复杂度为O(N)。

时间复杂度平均:O(n^{1.3})
空间复杂度:O(1)

        

        参考代码 

        

//希尔排序
void ShellSort(int* arr, int n)
{int gap = n;while (gap>1){//每次对gap折半操作gap = gap / 2;//单趟排序for (int i = 0; i < n - gap; ++i){int end = i;int tem = arr[end + gap];while (end >= 0){if (tem < arr[end]){arr[end + gap] = arr[end];end -= gap;}else{break;}}arr[end + gap] = tem;}}
}


5、快速排序

        介绍

        快速排序(Quicksort),计算机科学词汇,适用领域Pascal,C++等语言,是对冒泡排序算法的一种改进。

        1、选出一个key,一般是最左边或是最右边的。
        2、定义一个begin和一个end,begin从左向右走,end从右向左走。(需要注意的是:若选择最左边的数据作为key,则需要end先走;若选择最右边的数据作为key,则需要bengin先走)。
        3、在走的过程中,若end遇到小于key的数,则停下,begin开始走,直到begin遇到一个大于key的数时,将begin和right的内容交换,end再次开始走,如此进行下去,直到begin和end最终相遇,此时将相遇点的内容与key交换即可。(选取最左边的值作为key)
        4.此时key的左边都是小于key的数,key的右边都是大于key的数
        5.将key的左序列和右序列再次进行这种单趟排序,如此反复操作下去,直到左右序列只有一个数据,或是左右序列不存在时,便停止操作,此时此部分已有序。

时间复杂度:O(N*log_{2}^{N})

快速排序的过程类似于二叉树其高度为logN,每层约有N个数,如下图所示:

        

        参考代码 

//快速排序   hoare版本(左右指针法)
void QuickSort(int* arr, int begin, int end)
{//只有一个数或区间不存在if (begin >= end)return;int left = begin;int right = end;//选左边为keyint keyi = begin;while (begin < end){//右边选小   等号防止和key值相等    防止顺序begin和end越界while (arr[end] >= arr[keyi] && begin < end){--end;}//左边选大while (arr[begin] <= arr[keyi] && begin < end){++begin;}//小的换到右边,大的换到左边swap(&arr[begin], &arr[end]);}swap(&arr[keyi], &arr[end]);keyi = end;//[left,keyi-1]keyi[keyi+1,right]QuickSort(arr, left, keyi - 1);QuickSort(arr,keyi + 1,right);
}//快速排序法  挖坑法
void QuickSort1(int* arr, int begin, int end)
{if (begin >= end)return;int left = begin,right = end;int key = arr[begin];while (begin < end){//找小while (arr[end] >= key && begin < end){--end;}//小的放到左边的坑里arr[begin] = arr[end];//找大while (arr[begin] <= key && begin < end){++begin;}//大的放到右边的坑里arr[end] = arr[begin];}arr[begin] = key;int keyi = begin;//[left,keyi-1]keyi[keyi+1,right]QuickSort1(arr, left, keyi - 1);QuickSort1(arr, keyi + 1, right);
}//单趟排
int PartSort(int* arr, int begin, int end)
{int key = arr[begin];while (begin < end){while (key <= arr[end] && begin < end){--end;}arr[begin] = arr[end];while (key >= arr[begin] && begin < end){++begin;}arr[end] = arr[begin];}arr[begin] = key;int meeti = begin;return meeti;
}void QuickSortNoR(int* arr, int begin, int end)
{stack<int> st;//先入右边st.push(end);//再入左边st.push(begin);while (!st.empty()){//左区间int left = st.top();st.pop();//右区间int right = st.top();st.pop();//中间数int mid = PartSort(arr, left, right);//当左区间>=mid-1则证明左区间已经排好序了if (left < mid - 1){st.push(mid - 1);st.push(left);}//当mid+1>=右区间则证明右区间已经排好序if (right > mid + 1){st.push(right);st.push(mid + 1);}}
}//快速排序法  前后指针版本
void QuickSort2(int* arr, int begin, int end)
{if (begin >= end)return;int cur = begin, prev = begin - 1;int keyi = end;while (cur != keyi){if (arr[cur] < arr[keyi] && ++prev != cur){swap(&arr[cur], &arr[prev]);}++cur;}swap(&arr[++prev],&arr[keyi]);keyi = prev;//[begin,keyi -1]keyi[keyi+1,end]QuickSort2(arr, begin, keyi - 1);QuickSort2(arr, keyi + 1, end);}


6、并归排序

        介绍

        归并排序(Merge Sort)是一种经典的排序算法,它采用了分治法的策略。

        将初始序列的n个元素看成n个有序的子序列,每个子序列中只有一个元素,将其两两归并,得到n/2个长度为2(或1、子序列不为偶数则有落单)的有序子序列,再两两归并…以此类推直到得到n长的有序序列。

时间复杂度O(n log n)
空间复杂度O(n)

 

        参考代码 

/*题目:归并排序划分成很小的组,然后两两归并
*/
#include<iostream>
using namespace std;void Merge(int[], int, int[], int, int, int)  //归并函数的声明【把归并函数提到该函数前面,则不用声明】
//归并排序
//参数:
//		numbers[]:原数组
//		length:数组元素的个数(数组长度)
//		temp[]:辅助数组
//		begin:数组开头的下标
//		end:数组结尾的下标
void MergeSort(int numbers[], int length, int temp[], int begin, int end)
{//1. 同样判断传入的参数是否有效if (numbers == nullptr || length <= 0 || begin < 0 || end >= length)throw new exception("Invalid input.");//2. 作为递归的结束条件,开始下标和结束下标相等时,说明子序列中只有一个元素,看作有序的if (end - begin == 0)return;//3. 定义中间变量,将数组分半【如果有7个元素,下标0-6,则middle=3,数组分为长度为4和3的两段】int middle = ((end - begin) / 2 ) + begin;//4. 递归,先递归左半边,再递归右半边,将左右子序列不断分为长度为1的子序列才停止递归MergeSort(numbers, length, temp, begin, middle);MergeSort(numbers, length, temp, middle + 1, end);//5. 再慢慢归并Merge(numbers, length, temp, begin, end, middle);
}
//归并函数
//参数:
//		numbers[]:原数组
//		length:数组元素的个数(数组长度)
//		temp[]:辅助数组
//		begin:数组开头的下标
//		end:数组结尾的下标
//		middle:数组中间的下标
void Merge(int numbers[], int length, int temp[], int begin, int end, int middle)
{//1. 判断是否有不符合要求的参数传入,有则抛出错误if (numbers == nullptr || length <= 0 || begin < 0 || end >= length)throw new exception("Invalid input.");//2. 将原序列从中分开int leftIndex = begin;		//左边序列的开始(左边序列的结尾是middle)int rightIndex = middle + 1;//右边序列的开始(右边序列的结尾是end)int tempIndex = begin;		//辅助数组的下标//3. 当左右子序列尚未到头时,循环while (leftIndex <= middle && rightIndex <= end){//4. 两两对比判断,谁大谁就放入辅助数组,同时指针后移if (numbers[leftIndex] < numbers[rightIndex])temp[tempIndex] = numbers[leftIndex++];elsetemp[tempIndex] = numbers[rightIndex++];//5. 辅助数组下标++++tempIndex;}//6. 当左边或右边子序列尚未到头时,直接放入辅助数组while (leftIndex <= middle)temp[tempIndex++] = numbers[leftIndex++];while (rightIndex <= end)temp[tempIndex++] = numbers[rightIndex++];//7. 再将辅助数组中已经有序的元素覆盖掉原数组中无序的元素,使原数组变成部分有序for (int i = begin; i <= end; ++i)numbers[i] = temp[i];
}
//简单测试
int main(int arvc, char* argv[])
{const int length = 9;int nums[length] = { 18, 7, 23, 3, 9, 32, 10 , 99, 0};int *temp = new int[length];MergeSort(nums, length, temp, 0, 8);for (int i = 0; i < length; i++)cout << nums[i] << "  ";delete[] temp;temp = nullptr;cout << endl;return 0;
}


7、堆排序

        介绍

        堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

        参考代码

#include<iostream>using namespace std;
void sw(int &a,int &b) {int temp = a;a = b;b = temp;
}
// arr[]为完全二叉树层序遍历得到的数组
// n为完全二叉树的节点,即数组长度
// i为待维护的节点
void heapify(int arr[], int n, int i) {    //把这个二叉树先堆化//递归出口if (i >= n) return;int largest = i;int lson = i * 2 + 1;int rson = i * 2 + 2;if (lson < n && arr[largest] < arr[lson]) {  //和左孩子数值比较,找到最大节点,赋值下标largest = lson;}if (rson < n && arr[largest] < arr[rson]) {  //和右孩子数值比较,找到最大节点,赋值下标largest = rson;}if (largest != i) {   //如果现在的最大值下标和之前的不一样,那么交换二者的数值//sw(arr[largest], arr[i]);swap(arr[largest], arr[i]);heapify(arr, n, largest); //进行一个递归,因为在上一层的节点交换完之后,无法保证下边父节点大于孩子节点}}
void heap_sort(int arr[], int n) {//建堆int lastNode = n - 1;    //从后往前建堆int parent = (lastNode - 1) / 2;for (int i = parent; i >= 0; i--) {heapify(arr, n, i);}//堆排序for (int i = n - 1; i >= 0; i--) {sw(arr[i], arr[0]);heapify(arr, i, 0);}
}
int main() {int arr[5] = { 5,4,3,2,1 };heap_sort(arr, sizeof(arr) / sizeof(arr[0]));for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {cout << arr[i] << endl;}return 0;
}


8、基数排序 

        介绍

        基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。

        1.计算出得到的序列中的位数最大的数字的位数,以便确定需要进行几次排序
        2.创建取出任意数字任意位数的函数,用于对数字的排序
        3.接下来便可以开始排序

时间复杂度:O(n*d)

空间复杂度:O(n)

 

          参考代码

        

#include <iostream>
#include <vector>
using namespace std;int MaxBit(vector<int> input)    //求出数组中最大数的位数
{int max_num = input[0];      //默认最大数为第一个数字for (int i = 0; i < input.size(); i++)  //找出数组中的最大数{if (input[i] > max_num){max_num = input[i];}}int p = 0;while (max_num > 0){p++;max_num /= 10;   //每次除以10取整,即可去掉最低位}return p;
}int GetNum(int num, int d)   //取出所给数字的第d位数字
{int p = 1;while (d - 1 > 0){p *= 10;d--;}return num / p % 10;
}vector<int> RadixSort(vector<int> input, int length)   //基数排序
{vector<int> bucket(length);   //创建临时存放排序过程中的数据vector<int> count(10);   //创建按位计数的技术容器,即记录排序中按个位、十位...各个数的位置的个数for (int d = 1; d <= MaxBit(input); d++) {// 计数器清0for (int i = 0; i < 10; i++) {count[i] = 0;}// 统计各个桶中的个数for (int i = 0; i < length; i++) {count[GetNum(input[i], d)]++;}for (int i = 1; i < 10; i++) {     //得到每个数应该放入bucket中的位置count[i] += count[i - 1];}for (int i = length - 1; i >= 0; i--) {  //采用倒序进行排序是为了不打乱已经排好的顺序int k = GetNum(input[i], d);bucket[count[k] - 1] = input[i];count[k]--;}for (int j = 0; j < length; j++)    // 临时数组复制到 input 中{input[j] = bucket[j];}}return input;
}int main()
{int arr[] = { 50, 123, 543, 187, 49, 30, 0, 2, 11, 100 };vector<int> test(arr, arr + sizeof(arr) / sizeof(arr[0]));cout << "排序前:";for (int i = 0; i < test.size(); i++) {cout << test[i] << " ";}cout << endl;vector<int> result = test;result = RadixSort(result, result.size());cout << "排序后:";for (int i = 0; i < result.size(); i++) {cout << result[i] << " ";}cout << endl;system("pause");
}


9、计数排序

        介绍

        计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 [1] 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序)

  1. 找出待排序的数组中最大和最小的元素
  2. 统计数组中每个值为i的元素出现的次数,存入数组C的第i
  3. 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
  4. 反向填充目标数组:将每个元素i放在新数组的第C[i]项,每放一个元素就将C[i]减去1

时间复杂度:O(n+k)

 

        

        参考代码

        

#include <stdlib.h>void countingSort(int *ini_arr, int *sorted_arr, int n, int maxValue)
{int *count_arr = (int *)malloc(sizeof(int) * maxValue);int i, j, k;for (k = 0; k <= maxValue; k++)count_arr[k] = 0;for (i = 0; i < n; i++)count_arr[ini_arr[i]]++;for (k = 1; k <= maxValue; k++)count_arr[k] += count_arr[k - 1];for (j = n; j > 0; j--)sorted_arr[--count_arr[ini_arr[j - 1]]] = ini_arr[j - 1];free(count_arr);
}


10、桶排序 

        介绍

        桶排序(Bucket Sort)是一种排序算法,其工作原理是将数组分配到有限数量的桶中,然后对每个桶中的元素进行排序,最后再将各个桶中的数据有序的合并起来。

    原理:将数值作为桶号,遍历整个数组,将相应的桶进行计数
        1、 遍历原数组,找到最大值max,然后申请max+1个空间(桶),初始化为0(下标为0-max),即    vector<int>bucket(max+1,0)
        2、 再次遍历原数组,找到每个数值对应的桶号,并对桶计数++,即bucket[vec[i]]++
        3、 遍历桶数组,看对应的桶内计数为几就取出几下下标值(桶号),放到原数组中。

时间复杂度: O(n)

空间复杂度:O(n+k)

        参考代码 

#include<iostream>
#include<vector>
using namespace std;
void bucketSort(vector<int>&vec, int n)
{int max = vec[0];for (int i = 0; i < n; i++){if (vec[i] > max){max = vec[i];}}//申请max+1个桶//int *bucket = new int[max + 1];//给每个桶赋初值为0;//memset(bucket, 0, (max + 1) * sizeof(int));vector<int>bucket(max + 1, 0);//遍历原数组,把相应的数放到相应的桶里for (int i = 0; i < n; i++){bucket[vec[i]]++;}int index = 0;//从桶里把数取出来, i代表的数值对应桶下标, bucket[i]代表的是个数for (int i = 0; i < bucket.size(); i++){while (bucket[i] > 0){vec[index++] = i;bucket[i]--;}}
}
int main()
{vector<int>vec = { 2,3,5,8,9,7,4,6,1 };bucketSort(vec, vec.size());for (auto it : vec){cout << it << " ";}return 0;
}


总结

        

        在编写合理的情况下,简单排序算法是稳定的;快速排序、堆排序是不稳定的。在CSP中,往往排序是没有附带其他项目的,也就不要求排序稳定。快速排序、堆排序仍然是最佳选择。可是有没有时间复杂度为O(nlogn)的稳定的排序算法呢?有的。归并排序基于分治思想:把要排序的数组平分两半,对两部分分别排序(递归地)后再合并起来。合并时,将一个数组按顺序插入另一个数组中,需要开辟一个暂存数组。利用空间优化,可只用开辟一个与原数组等大的数组。归并排序的优缺点都很明显。无论情形如何,它的比较次数、赋值次数都稳定在nlogn,没有最差情况,运行时间与快速排序、堆排序相当。而且,它是稳定的排序算法。但是,它的内存占用会达到快速排序、堆排序的两倍,合理选用排序算法。

        下面是一些主排序算法的优缺点比较:竞赛时使用容易造成内存超出限制。

        

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

半个小时搞懂STM32面经知识——DMA

1.DMA 1.1 什么是DMA&#xff1f; DMA传输将数据从一个地址空间复制到另一个地址空间&#xff0c;提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 CPU无时不刻的在处理着大量的事务&#xff0c;但有些事情却没有那么重要&#xff0c;比方说数据的复制和存储数…

5.13号模拟前端面试10问

1.介绍箭头函数和普通函数的区别 箭头函数和普通函数在JavaScript中有一些重要的区别。以下是关于这些区别的详细解释&#xff1a; 语法结构上的差异&#xff1a; 箭头函数使用更简洁的语法&#xff0c;它不需要使用function关键字&#xff0c;而是使用一个箭头&#xff08;…

AI大模型系列之七:Transformer架构讲解

目录 Transformer是什么&#xff1f; 输入模块结构&#xff1a; 编码器模块结构&#xff1a; 解码器模块: 输出模块结构&#xff1a; Transformer核心思想是什么&#xff1f; Transformer的代码架构 自注意力机制是什么&#xff1f; 多头注意力有什么用&#xff1f; 前…

人工智能中的概率魔法:解锁不确定性的智慧之钥

在人工智能&#xff08;AI&#xff09;的广阔天地中&#xff0c;概率论以其独特的魅力&#xff0c;成为了连接现实世界与智能决策的桥梁。从语音识别到图像识别&#xff0c;从自然语言处理到机器翻译&#xff0c;从智能推荐到自动驾驶&#xff0c;概率论知识在这些领域中发挥着…

C++ 派生类的引入与特性

一 继承与派生 从上面的例子可以看出&#xff1a; 继承&#xff1a;一旦指定了某种事物父代的本质特征&#xff0c;那么它的子代将会自动具有哪些性质。这就是一种朴素的可重用的概念。 派生&#xff1a;而且子代可以拥有父代没有的特性&#xff0c;这是可扩充的概念。 1 C 的…

重大升级 | OpenSCA SaaS全面接入供应链安全情报!

结合社区用户反馈及研发小伙伴的积极探索&#xff0c; OpenSCA 项目组再次发力&#xff0c;SaaS版本重大升级啦&#xff01; 用户的需求是OpenSCA前进的动力&#xff0c;欢迎更多感兴趣的朋友们积极试用和反馈~ 更 新 内 容 1.全面接入云脉XSBOM供应链安全情报 2.强大的资产…

【kubernetes】容器编排平台的介绍

目录 前言 一、云原生知识 1、云原生要素 2、SRE&#xff08;Site Reliability Engineering&#xff09; 二、kubernetes 概述 1、kubernetes 概念 2、传统后端部署与k8s 的对比 2.1 传统部署 2.2 k8s的部署 3、为什么要用K8S 4、K8S解决的问题 5、K8S功能与特性 5…

CEETRON SDK 可为您的CAE应用程序提供5大优势!

开发CAE应用程序是一项资源密集型、复杂且耗时的工作。成功的开发人员会尽其所能&#xff0c;确保他们专注于让他们的产品、他们的新想法独一无二的东西。凭借CEETRON系列产品及其集成的工具&#xff0c;Tech Soft 3D提供了唯一支持预处理、求解和后处理工作流程的完整CAE组件技…

【挑战30天首通《谷粒商城》】-【第一天】【10 番外篇】 解决docker 仓库无法访问 + MobaXterm连接VirtualBox虚拟机

文章目录 课程介绍 1、解决docker 仓库无法访问 2、 MobaXterm连接VirtualBox虚拟机 Stage 1&#xff1a;下载MobaXterm选择适合你的版本 Stage 2&#xff1a;vagrant ssh 连接&#xff0c;开启ssh访问 Stage 2-1&#xff1a;su获取root账号权限,输入密码&#xff08;默认vagra…

材料物理 笔记-8

原内容请参考哈尔滨工业大学何飞教授&#xff1a;https://www.bilibili.com/video/BV18b4y1Y7wd/?p12&spm_id_frompageDriver&vd_source61654d4a6e8d7941436149dd99026962 或《材料物理性能及其在材料研究中的应用》&#xff08;哈尔滨工业大学出版社&#xff09; ——…

网页如何集成各社区征文活动

Helllo , 我是小恒 由于我需要腾讯云社区&#xff0c;稀土掘金以及CSDN的征文活动RSS&#xff0c;找了一下没发现&#xff0c;所以使用GET 请求接口对网页定时进行拉取清洗&#xff0c;甚至无意间做了一个简单的json格式API 最终网址:hub.liheng.work API:http://hub.liheng.wo…

海洋环境保护论文阅读记录

海洋环境保护 论文1&#xff1a;Critical role of wave–seabed interactions in the extensive erosion of Yellow River estuarine sediments 波浪-海床相互作用在黄河河口广泛侵中的关键作用 estuatine 河口的&#xff0c;港湾的 erodibility侵蚀度 sediment erodibility …