排序 | 冒泡插入希尔选择堆快排归并计数排序

排序 | 冒泡插入希尔选择堆快排归并计数排序

文章目录

  • 排序 | 冒泡插入希尔选择堆快排归并计数排序
    • 冒泡排序
    • 插入排序
    • 希尔排序
    • 选择排序
    • 堆排序
    • 快速排序--交换排序
      • 三数取中
      • 快速排序hoare版本
      • 快速排序挖坑法
      • 快速排序前后指针法
    • 快速排序--非递归实现
    • 归并排序
    • 归并排序非递归实现
    • 非比较排序【计数排序】
    • 排序算法复杂度及稳定性分析

我们需要实现的一些功能:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include<time.h>
// 打印
void Print_a(int* a, int sz);// 交换
void Swap(int* p1, int* p2);// 插入排序
void InsertSort(int* a, int n);// 冒泡排序
void BubbleSort(int* a, int n);// 希尔排序
void ShellSort(int* a, int n);// 堆排序
void AdjustDwon(int* a, int n, int root);
void HeapSort(int* a, int n);// 选择排序
void SelectSort(int* a, int n);// ------------------------------------------------------// 快速排序hoare版本 
int PartSort1(int* a, int begin, int end);// 快速排序挖坑法
int PartSort2(int* a, int begin, int end);// 快速排序前后指针法 
int PartSort3(int* a, int begin, int end);// 排序函数
void QuickSort(int* a, int begin, int end);//------------------------------------------------------// 快速排序 非递归实现 
void QuickSortNonR(int* a, int begin, int end);// 归并排序递归实现 
void MergeSort(int* a, int n);// 归并排序非递归实现 
void MergeSortNonR(int* a, int n);// 非比较排序
void CountSort(int* a, int n);

冒泡排序

  • 冒泡排序是一种基本的排序算法,其核心思想是通过多次交换相邻元素的位置,使得每一轮循环都将最大(或最小)的元素移动到序列的最后。这个过程就像气泡逐渐上升到表面一样,因而得名"冒泡排序"。

在这里插入图片描述

在这里插入图片描述
代码实现:

void bubbleSort(int* a,int n)
{for (int i = 0; i < n-1; i++){for (int j = 0; j < n - 1 - i; j++){if (a[j] > a[j + 1]){Swap(&a[j], &a[j + 1]);}}}
}

优点:

  1. 简单易懂: 冒泡排序的思想非常简单,容易理解和实现,适合初学者学习排序算法的基本概念。
  2. 原地排序: 冒泡排序是一种原地排序算法,不需要额外的空间来存储临时数据,只需要一个常数级的辅助空间。
  3. 稳定性: 冒泡排序是一种稳定的排序算法,相等元素的相对位置不会发生变化。

缺点:

  1. 效率低: 冒泡排序的平均时间复杂度为O(n^2),在处理大规模数据时性能较差,比较和交换的操作太过频繁。
  2. 不适合大规模数据: 冒泡排序的性能不如一些更高效的排序算法,如快速排序、归并排序等,特别是在数据规模较大的情况下。
  3. 对基本有序的序列效率低下: 在实际应用中,如果序列已经基本有序,冒泡排序仍然需要进行多次比较和交换,效率不高。

插入排序

  • 插入排序是一种简单直观的排序算法,其核心思想是将一个元素插入到已经排好序的数组(或子数组)中的合适位置,以达到整体有序的效果。插入排序的工作方式类似于整理扑克牌的过程:手里的牌是已经有序的部分,新摸到的牌则需要插入到适当的位置,保持有序性。

在这里插入图片描述

在这里插入图片描述
代码实现:

void InsertSort(int* a, int n)
{for (int i = 0; i < n - 1; i++){// 记录每次i的位置int end = i;// 将i+1的位置保存int tmp = a[end + 1];// 一次排序while (end >= 0){// 如果后面的数字小于前面的那一个就进行往后覆盖,// 然后end--,继续排序if (tmp < a[end]){a[end + 1] = a[end];--end;}else{// 如果大于或者等于了就跳出break;}}// 因为--end了,所以就要在end+1的位置放刚刚保存的值tmpa[end + 1] = tmp;}
}

优点:

  1. 简单易理解: 插入排序的实现非常简单,易于理解和实现,适用于小规模数据或部分有序的数据。
  2. 稳定性: 插入排序是一种稳定的排序算法,相等元素的相对位置不会发生变化。
  3. 适应性好: 如果数据已经基本有序,插入排序的性能会比较好,因为大部分元素都已经在正确的位置上,只需少量的比较和移动。
  4. 原地排序: 插入排序是一种原地排序算法,不需要额外的空间来存储临时数据。

缺点:

  1. 效率低: 插入排序的平均时间复杂度为O(n^2),在数据规模较大时,性能不如一些更高效的排序算法,如快速排序、归并排序等。
  2. 对大规模数据排序效率低下: 插入排序在处理大规模数据时性能较差,因为它需要大量的比较和移动操作。
  3. 不适合链表结构: 插入排序需要频繁地移动元素,对于链表结构来说,由于不支持随机访问,插入排序效率较低。

希尔排序

  • 希尔排序(Shell Sort)是一种插入排序的改进版本,也称为缩小增量排序。它通过比较相距一定间隔的元素,逐步减小这个间隔,直到间隔为1时完成最后一轮排序。希尔排序的核心思想是先使数组中任意间隔为h的元素有序,然后逐步减小h,最终使整个数组有序。

代码实现:

void ShellSort(int* a, int n)
{int gap = n;// gap > 1时是预排序,目的让他接近有序// gap == 1是直接插入排序,目的是让他有序while (gap > 1){// gap = gap / 2; // log 2 Ngap = gap / 3 + 1; // log 3 N//每次排gap次for (int j = 0; j < n - gap; j++){//插入排序int end = j;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

优点:

  1. 相对于插入排序的改进: 希尔排序是插入排序的改进版本,通过引入间隔(gap)的概念,减少了数据的搬移次数,提高了效率。
  2. 适用于中等规模数据: 希尔排序相对于一些简单的排序算法,对中等规模的数据表现较好,比如对于几千甚至几万个元素的排序。
  3. 不稳定性: 相比较于一些稳定排序算法(如归并排序、插入排序),希尔排序的不稳定性可能在某些情况下是一个优势,特别是在排序过程中需要对元素进行位置交换的场景。

缺点:

  1. 不适用于大规模数据: 希尔排序的性能相对较好,但在处理非常大规模数据时,效率可能不如一些更为高级的排序算法,比如快速排序、归并排序等。
  2. 不稳定性: 尽管不稳定性在某些情况下可以是优势,但在某些应用场景下,需要保持相等元素的相对位置不变,这时候希尔排序的不稳定性可能成为一个缺点。

选择排序

  • 选择排序(Selection Sort)是一种简单直观的排序算法,其基本思想是通过不断选择未排序序列中的最小(或最大)元素,将其与未排序序列的第一个元素交换,从而逐步构建有序序列。

在这里插入图片描述

代码实现:

// 选择排序
void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;while (begin < end){// 两头找int mini = begin, maxi = begin;for (int i = begin + 1; i <= end; i++){// 如果i的位置比mini小就更新一下if (a[i] < a[mini]){mini = i;}//如果i的位置比maxi大就更新一下if (a[i] > a[maxi]){maxi = i;}}// 走到这里就说明小的要和左边交换一下Swap(&a[mini], &a[begin]);// 注意:这里Eugene左边的和maxi相等了要更新一下maxiif (begin == maxi){maxi = mini;}// 然后交换maxi和endSwap(&a[end], &a[maxi]);++begin;--end;}
}

优点:

  1. 简单易理解: 选择排序的实现非常简单,易于理解和实现,适合初学者学习排序算法的基本概念。
  2. 原地排序: 选择排序是一种原地排序算法,不需要额外的空间来存储临时数据,只需要一个常数级的辅助空间。
  3. 不稳定性: 选择排序是一种不稳定的排序算法,相等元素的相对位置可能发生变化,但在某些情况下,不稳定性可能是一个优势。

缺点:

  1. 效率低: 选择排序的平均时间复杂度为O(n^2),在处理大规模数据时性能较差,由于每次只能确定一个元素的位置,比较和交换的操作过于频繁。
  2. 对基本有序的序列效率低下: 在实际应用中,如果序列已经基本有序,选择排序仍然需要进行大量的比较和交换,效率不高。
  3. 不适合大规模数据: 选择排序的性能不如一些更高效的排序算法,如快速排序、归并排序等,特别是在数据规模较大的情况下。

堆排序

  • 堆排序是一种基于二叉堆数据结构的排序算法。它利用了堆的性质来进行排序,其中堆分为最大堆和最小堆两种类型。在最大堆中,父节点的值大于或等于其子节点的值;在最小堆中,父节点的值小于或等于其子节点的值。

  • 这里在堆排序章节已经讲过了,这里就不细讲了~~

代码实现:

void AdjustDwon(int* a, int n, int root)
{int parent = root;int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] > a[child])++child;if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}void HeapSort(int* a, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDwon(a, n, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDwon(a, end, 0);--end;}
}

优点:

  1. 稳定性: 堆排序是一种不稳定的排序算法,因为在构建初始堆和进行堆调整的过程中可能破坏相同元素的相对顺序。然而,如果对于相同的元素,可以使用索引来保持其相对顺序,就可以避免这个问题。
  2. 原地排序: 堆排序是一种原地排序算法,不需要额外的存储空间来存储待排序的数据,只需要常数级别的辅助空间。
  3. 时间复杂度: 堆排序的平均、最好和最坏情况下的时间复杂度都是 O(n log n),其中 n 是待排序元素的数量。这使得堆排序在大数据集上表现良好。

缺点:

  1. 非自适应性: 堆排序的时间复杂度在各种情况下都是 O(n log n),无论输入数据的初始顺序如何。因此,它对于部分有序的数据或者小规模数据集的排序效率可能不如一些自适应性较强的算法。
  2. 不稳定: 在排序过程中,堆排序可能破坏相同元素的相对顺序,因此是一种不稳定的排序算法。如果对稳定性有要求,可能需要考虑其他算法。
  3. 不适用于链式存储结构: 堆排序通常需要对数组进行直接访问,而不适用于链式存储结构。因此,如果数据结构采用链表形式存储,需要将其转换为数组再进行排序,这可能引入额外的开销。

快速排序–交换排序

三数取中

int GetMidi(int* a, int left, int right)
{//int midi = (begin + end) / 2;int mid = (left + right) >> 1;if (a[left] < a[mid]){if (a[mid] < a[right])return mid;else if (a[left] > a[right])return left;elsereturn right;}else // a[left] > a[mid]{if (a[mid] > a[right])return mid;else if (a[left] < a[right])return left;elsereturn right;}
}

快速排序hoare版本

  • 快速排序是一种常用的排序算法,Hoare版本是其中一种实现方式,由Tony Hoare提出。

在这里插入图片描述

代码实现:

int PartSort1(int* a, int begin, int end)
{// 三数取中int midi = GetMidi(a, begin, end);Swap(&a[midi], &a[begin]);// 要在最左边开始int left = begin, right = end;int keyi = begin;while (left < right){// 右边找小while (left < right && a[right] >= a[keyi]){--right;}// 左边找大while (left < right && a[left] <= a[keyi]){++left;}// 找到了,就交换Swap(&a[left], &a[right]);}// 交换的左边的和keyi,然后更新一下keyiSwap(&a[left], &a[keyi]);return left;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;// 小区间if (end - begin + 1 < 10){InsertSort(a + begin, end - begin + 1);}else{int keyi = PartSort1(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);}
}

优点:

  1. 原地排序: 快速排序是一种原地排序算法,不需要额外的空间来存储临时数据,只需要一个常数级的辅助空间。
  2. 平均情况下具有较好的性能: 在平均情况下,快速排序的时间复杂度为O(n log n),这使得它在实践中具有较好的性能。
  3. 适用于大规模数据: 快速排序在处理大规模数据时通常表现良好,尤其是相对于一些平均时间复杂度较高的排序算法而言。
  4. 对基本有序的数据排序效果好: 在一些情况下,快速排序对基本有序的数据排序效果较好。

缺点:

  1. 不稳定性: 快速排序是一种不稳定的排序算法,相等元素的相对位置可能发生变化,如果需要稳定性,可能需要额外的处理。
  2. 对于极端情况的性能: 在最坏情况下,即已经有序的序列,快速排序的时间复杂度为O(n^2),这时性能可能较差。为了避免这种情况,通常会使用一些优化策略,比如随机化选择枢轴。
  3. 对于小规模数据性能较差: 在小规模数据的排序中,快速排序的递归调用会增加额外的开销,性能可能不如一些简单的排序算法,如插入排序。

快速排序挖坑法

  • 快速排序的挖坑法(也称为Lomuto分区方案)是快速排序的一种实现方式。在挖坑法中,选择一个基准元素,通过不断交换元素将数组分成两个部分,左边的部分都小于基准元素,右边的部分都大于基准元素。接着,对左右两个部分分别递归进行同样的操作。

在这里插入图片描述

代码实现:

int PartSort2(int* a, int begin, int end)
{int midi = GetMidi(a, begin, end);Swap(&a[midi], &a[begin]);int key = a[begin];int holei = begin;while (begin < end){// 右边找小while (begin < end && a[end] >= key){--end;}a[holei] = a[end];holei = end;// 左边找大while (begin < end && a[begin] <= key){++begin;}a[holei] = a[begin];holei = begin;}a[holei] = key;return holei;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;// 小区间if (end - begin + 1 < 10){InsertSort(a + begin, end - begin + 1);}else{int keyi = PartSort2(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);}
}

优点:

  1. 原地排序: 挖坑法是一种原地排序算法,不需要额外的空间来存储临时数据,只需要一个常数级的辅助空间。
  2. 简单直观: 挖坑法实现相对较简单,容易理解和实现,适用于教学和学习排序算法。

缺点:

  1. 不稳定性: 挖坑法是一种不稳定的排序算法,相等元素的相对位置可能发生变化,如果需要稳定性,可能需要额外的处理。
  2. 最坏情况下的性能: 在最坏情况下,即已经有序的序列,挖坑法的性能可能较差。这时的时间复杂度为O(n^2),因为每次分区只能使序列中的一个元素有序。
  3. 对于小规模数据性能较差: 在小规模数据的排序中,挖坑法的递归调用会增加额外的开销,性能可能不如一些简单的排序算法,如插入排序。

快速排序前后指针法

  • 快速排序的前后指针法(也称为Hoare分区方案)是另一种实现方式。在这个方法中,通过两个指针从数组的两端分别向中间移动,交换不符合排序条件的元素,最终将数组分为两个部分,左边部分小于基准元素,右边部分大于基准元素。

在这里插入图片描述

代码实现:

int PartSort3(int* a, int begin, int end)
{int midi = GetMidi(a, begin, end);Swap(&a[begin], &a[midi]);int prev = begin;int cur = prev + 1;int keyi = begin;while (cur <= end){if (a[cur] < a[keyi] && ++prev != cur)Swap(&a[prev], &a[cur]);++cur;}Swap(&a[keyi], &a[prev]);keyi = prev;return prev;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;// 小区间if (end - begin + 1 < 10){InsertSort(a + begin, end - begin + 1);}else{int keyi = PartSort3(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);}
}

优点:

  1. 原地排序: 前后指针法是一种原地排序算法,不需要额外的空间来存储临时数据,只需要一个常数级的辅助空间。
  2. 相对较好的性能: 在平均情况下,快速排序的前后指针法具有较好的性能,时间复杂度为O(n log n)。
  3. 不需要额外的空间: 与挖坑法相比,前后指针法在实际的操作中,不需要额外的元素用于填坑,从而减少了一些操作。

缺点:

  1. 不稳定性: 前后指针法是一种不稳定的排序算法,相等元素的相对位置可能发生变化,如果需要稳定性,可能需要额外的处理。
  2. 最坏情况下的性能: 在最坏情况下,即已经有序的序列,前后指针法的性能可能较差。这时的时间复杂度为O(n^2),因为每次分区只能使序列中的一个元素有序。
  3. 对于小规模数据性能较差: 在小规模数据的排序中,前后指针法的递归调用会增加额外的开销,性能可能不如一些简单的排序算法,如插入排序。

快速排序–非递归实现

  • 我们这里使用栈来解决这个问题~~
  • 先入栈,然后再进行分割
  • 注意: 如果是先入右后入左,那么出的时候就要先出左后出右
  • 栈不为空就继续,然后分割排左边和右边

代码实现:

#include"Stack.h"
// 快速排序 非递归实现 
void QuickSortNonR(int* a, int begin, int end)
{ST s;StackInit(&s);// 先入右后入左StackPush(&s, end);StackPush(&s, begin);while (!StackEmpty(&s)){// 先出左后出右int left = StackTop(&s);StackPop(&s);int right = StackTop(&s);StackPop(&s);// 排序int keyi = PartSort3(a, left, right);// [left keyi-1] keyi [keyi+1 right]if (left < keyi - 1){StackPush(&s, keyi - 1);StackPush(&s, left);}if (keyi + 1 < right){StackPush(&s, right);StackPush(&s, keyi + 1);}}StackDestroy(&s);
}

归并排序

  • 归并排序(Merge Sort)是一种分治算法,它的基本思想是将待排序的数组分成两个相等大小的子数组,然后分别对这两个子数组进行排序,最后将排序好的子数组合并成一个有序的数组。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码实现:

void _MergeSort(int* a, int begin, int end, int* tmp)
{if (begin >= end)return;// 分割  // 这里右移一位相当于 /2 int mid = (begin + end) >> 1; // 递归_MergeSort(a, begin, mid, tmp);_MergeSort(a, mid + 1, end, tmp);// [begin mid][mid+1 end]  归并int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int i = begin;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}while (begin1 <= end1){tmp[i++] = a[begin1++];}while (begin2 <= end2){tmp[i++] = a[begin2++];}// 拷贝回原数组for (int i = begin; i <= end; ++i){a[i] = tmp[i];}//memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin) + 1);
}// 归并排序递归实现 
void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail!\n");return;}_MergeSort(a, 0, n - 1, tmp);free(tmp);
}

优点:

  1. 稳定性: 归并排序是一种稳定的排序算法,即对于相等的元素,它们在排序后的相对位置保持不变。
  2. 适用于链表: 归并排序对于链表等非随机访问结构的数据也非常有效,因为它不涉及随机访问,只涉及指针操作。
  3. 适用于外部排序: 归并排序在外部排序(需要对外部存储进行排序的情况)中表现良好,因为它可以很容易地通过合并有序的外部文件来实现。
  4. 稳定的时间复杂度: 归并排序的时间复杂度是稳定的,不受输入数据的影响,总是O(n log n)。

缺点:

  1. 额外空间需求: 归并排序需要额外的内存空间来存储临时数组,这使得它的空间复杂度相对较高,是O(n)。
  2. 非原地排序: 归并排序是一种非原地排序算法,即它需要额外的空间来存储临时数组,而不是在原始数组上进行排序。这对于内存受限的情况可能不太理想。
  3. 常数因子较大: 归并排序的常数因子较大,因此在实际应用中可能被一些其他排序算法(如快速排序)超越。

归并排序非递归实现

  • 思想和上面的归并排序差不多~~

代码实现:

void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);int gap = 1; // 每组数据个数while (gap < n){for (int i = 0; i < n; i += 2 * gap){// [i, i+gap-1] [i+gap,i+2*gap-1]int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;// 归并过程中右半区间可能就不存在if (begin2 >= n)break;// 归并过程中右半区间算多了, 修正一下if (end2 >= n){end2 = n - 1;}int index = i;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}// 拷贝回去for (int j = i; j <= end2; ++j){a[j] = tmp[j];}}gap *= 2;}free(tmp);
}

非比较排序【计数排序】

  • 计数排序(Counting Sort)是一种非比较性的整数排序算法,它通过确定每个元素在输出序列中的位置来实现排序。

在这里插入图片描述

代码实现:

void CountSort(int* a, int n)
{int max = a[0], min = a[0];for (int i = 0; i < n; i++){if (a[i] > max)max = a[i];if (a[i] < min)min = a[i];}int range = max - min + 1;int* count = (int*)malloc(sizeof(int) * range);if (count == NULL){perror("malloc fail!\n");return;}memset(count, 0, sizeof(int) * range);//统计次数for (int i = 0; i < n; i++){count[a[i] - min]++;}int i = 0;for (int j = 0; j < range; j++){while (count[j]--){a[i++] = j + min;}}free(count);
}

优点:

  1. 线性时间复杂度: 计数排序是一种具有线性时间复杂度的排序算法,其时间复杂度为O(n + k),其中n是输入元素的数量,k是输入范围的大小。在输入范围较小的情况下,计数排序通常比其他O(n log n)的排序算法更快。
  2. 稳定性: 计数排序是一种稳定的排序算法,即相等元素的相对顺序在排序后仍然保持不变。
  3. 适用于整数排序: 计数排序适用于整数排序,尤其是在知道输入范围不太大的情况下。它不依赖于比较操作,因此在某些情况下可能比基于比较的排序算法更高效。

缺点:

  1. 空间复杂度: 计数排序的主要缺点是它需要额外的空间来存储计数数组。如果输入范围很大,可能需要较大的额外空间,这可能导致空间复杂度较高。
  2. 仅适用于整数: 计数排序仅适用于整数排序,因为它依赖于将元素映射到计数数组的索引。对于浮点数或其他数据类型,需要进行额外的转换。
  3. 对输入范围的限制: 计数排序要求输入的元素必须在已知范围内,否则需要进行范围的确定和调整,增加了实现的复杂性。

排序算法复杂度及稳定性分析

在这里插入图片描述

在这里插入图片描述

本期内容就到这里了,感谢大家的收看,欢迎三连~~

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

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

相关文章

【AutoDL】使用云服务器跑深度学习代码

一、AutoDL租用服务器 1.选用服务器 1.算力市场 租用服务器&#xff0c;选择自己心仪的服务器 2.镜像 可以选择一些基础的镜像&#xff0c;社区镜像里是git上有的环境。 3.上传文件 在文件存储中&#xff0c;选择上传的区&#xff0c;在右边点击上传&#xff0c;选择自己的文…

Dockerfile创建镜像LNMP+WordPress

目录 实验部署 nginx 配置mysql 配置php 实验部署 INMPwordpress nginx 172.111.0.10 docker-nginx mysql 172.111.0.20 docker-mysql php 172.111.0.30 docker-php nginx 关闭防火墙和安全机制在opt目录创建nginx MySQL php目录 cd nginx mysql php vim Dockerfile#声…

Arduino中读取SD卡文本文件数据

1、硬件 2、代码 #include <SD.h> #include <SPI.h> // needed for Arduino versions later than 0018const long _1000msTime 1000; // 1000 milli seconds unsigned long _1000msLastTime;File myFile; int date; int Lastdate; String strDate;//…

YOLOv5独家原创改进:SPPF自研创新 | SPPF与感知大内核卷积UniRepLK结合,大kernel+非膨胀卷积提升感受野

💡💡💡本文自研创新改进:SPPF与感知大内核卷积UniRepLK结合,大kernel+非膨胀卷积,使SPPF增加大kernel,提升感受野,最终提升检测精度 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/category_12511931.html 💡💡💡全网独家首发创新(原创),…

垃圾回收 (GC) 在 .NET Core 中是如何工作的?(二)

接上一篇文章垃圾回收 (GC) 在 .NET Core 中是如何工作的&#xff1f;-CSDN博客 GC 会分配堆段&#xff0c;其中每个段都是一系列连续的内存。 置于堆中的对象归类为 3 个代系之一&#xff1a;0、1 或 2。 代系可确定 GC 尝试在应用不再引用的托管对象上释放内存的频率。 编号…

【亚马逊云科技】使用Vscode Amazon-Q完成GUI界面粉笔脚本开发

本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 亚马逊云科技开发者社区, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 前言 亚马逊云科技-Q&#xff0c;可以快速获得紧迫问题的相关答案&#xff0c;解决问题…

生物信息学分析领域领先的特制语言环境NGLess(Next Generation Less)介绍、安装配置和详细使用方法

介绍 NGLess&#xff08;Next Generation Less&#xff09;是一种用于生物信息学分析的领先的领域特定语言&#xff08;DSL&#xff09;。它旨在简化和加速NGS&#xff08;Next Generation Sequencing&#xff09;数据的分析过程。NGLess具有清晰的语法和功能&#xff0c;使用户…

机器翻译:跨越语言边界的智能大使

导言 机器翻译作为人工智能领域的瑰宝&#xff0c;正在以前所未有的速度和精度&#xff0c;为全球沟通拓展新的可能性。本文将深入研究机器翻译的技术原理、应用场景以及对语言交流未来的影响。 1. 简介 机器翻译是一项致力于通过计算机自动将一种语言的文本翻译成另一种语言的…

[Unity]关于Unity接入Appsflyer并且打点支付

首先需要去官方下载Appsflyer的UnityPackage 链接在这afPackage 然后导入 导入完成 引入此段代码 using AppsFlyerSDK; using System.Collections; using System.Collections.Generic; using UnityEngine;public class AppflysManager : MonoBehaviour {public static App…

测试总监给我分享的《接口自动化测试》总结,让我成功的入门接口自动化门槛......

前两天在测试技术交流群里&#xff0c;听了一位字节跳动的测试总监分享的接口自动化测试的内容&#xff0c;对接口自动化更加了解了&#xff0c;也为自己接下来在公司实施接口自动化项目提供了思路。 前言 自动化测试&#xff0c;算是近几年比较火热的一个话题&#xff0c;当…

现代C++ 实现单例模式

传统写法有什么问题 如果你了解过单例模式&#xff0c;双重检查锁定模式&#xff08;Double-Checked Locking Pattern&#xff0c;后文简称DCLP&#xff09;的写法你一定不会陌生&#xff0c;甚至你或许认为它是最正确的代码。 class Singleton { public://获取单例Singleton…

解决:Component name “index“ should always be multi-word

原因 要求组件名称以驼峰格式命名&#xff0c;自定义组件名称应该由多单纯组成&#xff0c;防止和html标签冲突&#xff0c;所以index.vue 会报错 解决 1、按照规则驼峰格式&#xff0c;如&#xff1a;appIndex.vue 2、若有.eslintrc.js文件&#xff0c;并在规则中(rules)关…

数据挖掘-08-基于Python实现时间序列分析建模(ARIMA 模型)(包括数据和代码)

文章目录 0. 数据代码下载1. 背景描述2. 预测目的3. 数据总览4. 数据预处理4.1数据描述性统计与清洗a. 导入程序库b. 读取数据c. 查看统计信息和空值d. 查看是否有重复数据以及清理重复数据e. 空值清理f. 针对清洗后的数据进行统计分析 5. 探索性数据分析5.1 数据分析 6. 构建 …

猫粮哪个牌子质量好性价比高?盘点十款主食冻干猫粮品牌排行榜!

在过去的100多年里&#xff0c;猫咪主食市场一直被膨化猫粮主导。然而&#xff0c;随着猫咪频频出现猝死、失明、发育不良以及营养不良等问题&#xff0c;猫主人们开始质疑膨化粮是否最适合猫咪。于是&#xff0c;从上世纪90年代开始&#xff0c;出现了生骨肉喂养。生骨肉确实是…

网络安全——基于Snort的入侵检测实验

一、实验目的要求&#xff1a; 二、实验设备与环境&#xff1a; 三、实验原理&#xff1a; 四、实验步骤&#xff1a; 五、实验现象、结果记录及整理&#xff1a; 六、分析讨论与思考题解答&#xff1a; 七、实验截图&#xff1a; 一、实验目的要求&#xff1a; 1、掌握…

一、win10+yolov8+anaconda环境部署

1、安装anaconda &#xff08;1&#xff09;打开aonconda下载地址&#xff1a;https://www.anaconda.com/download&#xff0c;点击download下载。 2、下载完成后&#xff0c;双击打开&#xff0c;点击Next&#xff0c;I Agree&#xff0c;选择just me&#xff1b; 3、勾选…

Spring上下文之注解模块ConfigurationMethod

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

飞天使-docker知识点8-docker的资源限制

文章目录 容器资源限制示例 容器资源限制 Docker提供了多种资源限制的方式&#xff0c;可以根据应用程序的需求和系统资源的可用性进行选择。以下是一些常见的Docker资源限制及其使用情况&#xff1a;CPU限制&#xff1a;通过设置CPU的配额&#xff08;quota&#xff09;和周期…

网络(九)CanSM及达芬奇配置

【小猫爪】AUTOSAR学习笔记05-Communication Stack之CanSM模块-CSDN博客 上链接讲的非常好。 CanSM提供的函数。 C CanSM使用的函数&#xff1a;

spring mail 邮件发送demo

首先配置号邮件服务器&#xff08;我用的是126邮箱&#xff09;&#xff0c;获取密钥&#xff1a; 进入下图的【邮箱中心】->点击右侧的齿轮按钮 接着&#xff0c;开启 下图位置 的 POP3/SMTP&#xff08;我当时点击开启时&#xff0c;需要手机扫码认证下&#xff09; 最后…