【算法】八大排序算法
这篇文章是对数据结构中 八大经典排序算法 的详解,包括其原理、实现过程、时间复杂度、空间复杂度及其适用场景。最后两种排序不常见,但仍收录了进来保持文章结构的完整性。
排序(Sort)是将无序的记录序列(或称文件)调整成有序的序列。升序 或 降序 —> 一般都是对数据进行升序排列(从小到大排序)。
对文件(File)进行排序有重要的意义。如果文件按key有序,可对其折半查找,使查找效率提高;在数据库(Data Base)和知识库(Knowledge Base)等系统中,一般要建立若干索引文件,就牵涉到排序问题;在一些计算机的应用系统中,要按不同的数据段作出若干统计,也涉及到排序。排序效率的高低,直接影响到计算机的工作效率。
稳定排序和非稳定排序
设文件 f=(R1……Ri……Rj……Rn)
中记录 Ri、Rj(i≠j,i、j=1……n)
的 key
相等,即 Ki=Kj
。若在排序前 Ri
领先于Rj,排序后 Ri
仍领先于 Rj
,则称这种排序是稳定的,其含义是它没有破坏原本已有序的次序。反之,若排序后Ri与Rj的次序有可能颠倒,则这种排序是非稳定的,即它有可能破坏了原本已有序记录的次序。
说人话就是:假设有6个数据:5 2 6 2 8 1 —> 具有重复数据;经过排序后得到: 1 2 2 5 6 8,稳定排序和不稳定排序之间讲究的就是在相同的数据中,相同数据是否转换了位置。
1> 1 2 2 5 6 8
------①②--------> 两个 2(重复数据) 没有发生位置改变,称为稳定排序。
2> 1 2 2 5 6 8
------②①--------> 两个 2(重复数据) 发生了位置改变,称为不稳定排序。
排序的稳定性没办法解决,看具体的算法性能决定排序的稳定性。这二者之间只有性能差异,并不会影响到数据和操作的变化。
内排序和外排序
内排序:发生在内存中的排序方式(我们现在用的大部分排序方式都是内排序);
外排序:发生在其他硬件或(存储器)之间的排序 —> 通信排序。
若待排文件 f
在计算机的内存储器中,且排序过程也在内存中进行,称这种排序为内排序。内排序速度快,但由于内存容量一般很小,文件的长度(记录个数)n受到一定限制。若排序中的文件存入外存储器,排序过程借助于内外存数据交换(或归并)来完成,则称这种排序为外排序。我们重点讨论内排序的一些方法、算法以及时间复杂度的分析。
算法数据可视化参考该网站:https://visualgo.net/zh。
截止目前,各种内排序方法可归纳为以下五类:
(1)插入排序
(2)交换排序
(3)选择排序
(4)归并排序
(5)基数排序
也可以按照比较类排序和非比较类排序来进行分类:
- 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
- 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
算法复杂度分析
- 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
- 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
- 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
- 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
1. 冒泡排序(Bubble Sort)
冒泡排序是一种简单的交换排序算法,按顺序比较相邻的两个元素,将较大的元素逐渐“冒泡”到数组的末尾。相信冒泡排序是大家最熟知、面试中常考题、也是最经典的一种排序方式。
算法原理
- 对数组从头到尾遍历。
- 每次比较相邻的两个元素,如果前者大于后者,则交换它们。
- 每轮遍历后,最大的元素会“冒泡”到数组的末尾。
- 重复此过程,直到数组完全有序。
时间复杂度
- 最好情况:
O(n)
(数组本身有序,使用标志优化) - 最坏情况:
O(n²)
(数组逆序) - 平均情况:
O(n²)
空间复杂度
O(1)
(原地排序)
冒泡排序演示
代码实现(C语言)
void bubbleSort(int arr[], int n) {int i, j, temp;for (i = 0; i < n - 1; i++) {int swapped = 0; // 标志位,检测是否发生交换for (j = 0; j < n - i - 1; j++) {if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;swapped = 1;}}if (!swapped) break; // 如果没有发生交换,提前退出}
}
2. 选择排序(Selection Sort)
选择排序是一种简单的排序算法,通过选择最小(或最大)的元素并将其放到正确位置。
算法原理
- 在未排序部分中找到最小元素。
- 将该最小元素与未排序部分的第一个元素交换。
- 重复上述步骤,直到所有元素有序。
时间复杂度
- 最好情况:
O(n²)
- 最坏情况:
O(n²)
- 平均情况:
O(n²)
空间复杂度
O(1)
(原地排序)
选择排序演示
代码实现(C语言)
void selectionSort(int arr[], int n) {int i, j, minIndex, temp;for (i = 0; i < n - 1; i++) {minIndex = i;for (j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}if (minIndex != i) {temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}}
}
选择排序是表现最稳定的排序算法之一,因为无论什么数据进去都是 O(n2)
的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法。
3. 插入排序(Insertion Sort)
插入排序通过逐步构建有序序列,将每个元素插入到有序序列的正确位置。
算法原理
- 从第二个元素开始,视其为待插入元素。
- 从已排序部分的末尾向前遍历,找到其插入位置。
- 插入元素后,已排序部分长度加 1。
- 重复上述步骤,直到所有元素有序。
时间复杂度
- 最好情况:
O(n)
(数组本身有序) - 最坏情况:
O(n²)
(数组逆序) - 平均情况:
O(n²)
空间复杂度
O(1)
(原地排序)
插入排序演示
代码实现(C语言)
void insertionSort(int arr[], int n) {int i, j, key;for (i = 1; i < n; i++) {key = arr[i];j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}
}
插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
4. 希尔排序(Shell Sort)
希尔排序是插入排序的改进版,通过分组和缩小增量进行排序。
算法原理
- 将数组分成若干组,按间隔 gap 分组。
- 对每组元素进行插入排序。
- 缩小间隔
gap
,重复分组和排序。 - 最后,当
gap = 1
时,完成整个排序。
时间复杂度
- 最好情况:
O(n log n)
- 最坏情况:
O(n²)
- 平均情况:
O(n log n)
空间复杂度
O(1)
希尔排序演示
代码实现(C语言)
void shellSort(int arr[], int n) {int gap, i, j, temp;for (gap = n / 2; gap > 0; gap /= 2) {for (i = gap; i < n; i++) {temp = arr[i];for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {arr[j] = arr[j - gap];}arr[j] = temp;}}
}
希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。动态定义间隔序列的算法是《算法(第4版)》的合著者Robert Sedgewick提出的。
5. 快速排序(Quick Sort)
快速排序是一种基于分治的高效排序算法。
算法原理
- 选择一个基准值(通常是第一个元素)。
- 将数组分为两部分:小于基准值的放左边,大于基准值的放右边。
- 对两部分递归排序。
- 递归结束后,数组有序。
时间复杂度
- 最好情况:
O(n log n)
- 最坏情况:
O(n²)
(划分极不平衡) - 平均情况:
O(n log n)
空间复杂度
O(log n)
(递归栈空间)
快速排序演示
代码实现(C语言)
void quick_sort(int *a,int left,int right)
{if(left>=right){return;}int i=left;int j=right;int key=a[i];while(i<j){while(key<a[j] && i<j){j--;}a[i]=a[j];while(key>a[i] && i<j){i++;}a[j]=a[i];}a[i]=key;display(a);quick_sort(a,left,i-1);quick_sort(a,i+1,right);
}
6. 归并排序(Merge Sort)
归并排序是基于分治的稳定排序算法。
算法原理
- 将数组递归分成两部分,直到每部分只有一个元素。
- 合并两个有序部分,形成一个有序数组。
- 重复上述步骤,最终完成排序。
时间复杂度
- 最好/最坏/平均情况:
O(n log n)
空间复杂度
O(n)
(合并时需要额外数组)
归并排序演示
代码实现(C语言)
void merge(int arr[], int left, int mid, int right) {int n1 = mid - left + 1;int n2 = right - mid;int L[n1], R[n2];for (int i = 0; i < n1; i++) L[i] = arr[left + i];for (int i = 0; i < n2; i++) R[i] = arr[mid + 1 + i];int i = 0, j = 0, k = left;while (i < n1 && j < n2) {if (L[i] <= R[j]) arr[k++] = L[i++];else arr[k++] = R[j++];}while (i < n1) arr[k++] = L[i++];while (j < n2) arr[k++] = R[j++];
}void mergeSort(int arr[], int left, int right) {if (left >= right) return;int mid = left + (right - left) / 2;mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);merge(arr, left, mid, right);
}
归并排序是一种稳定的排序方法。和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(nlogn)的时间复杂度。代价是需要额外的内存空间。
7. 堆排序(Heap Sort)
堆排序基于堆数据结构,是一种选择排序。
算法原理
- 构建最大堆(堆顶为最大元素)。
- 将堆顶元素与堆尾元素交换,缩小堆范围。
- 调整堆,重复上述步骤,完成排序。
时间复杂度
- 最好/最坏/平均情况:
O(n log n)
空间复杂度
O(1)
堆排序演示
代码实现(C语言)
void heapify(int arr[], int n, int i) {int largest = i;int left = 2 * i + 1;int right = 2 * i + 2;if (left < n && arr[left] > arr[largest]) largest = left;if (right < n && arr[right] > arr[largest]) largest = right;if (largest != i) {int temp = arr[i];arr[i] = arr[largest];arr[largest] = temp;heapify(arr, n, largest);}
}void heapSort(int arr[], int n) {for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i);for (int i = n - 1; i > 0; i--) {int temp = arr[0];arr[0] = arr[i];arr[i] = temp;heapify(arr, i, 0);}
}
8. 基数排序(Radix Sort)
基数排序是一种非比较排序算法,适合对整数或字符串进行排序。其核心思想是按位排序,从最低位到最高位,逐位进行排序(通常使用计数排序作为子过程)。
算法原理
- 按位排序:
- 从个位开始,对每一位进行排序,直到最高位。
- 每一位的排序需要保持稳定性(如使用计数排序实现)。
- 关键步骤:
- 找到数组中的最大值,确定排序的位数 d。
- 对每一位(从最低位到最高位)依次排序。
- 使用计数排序对当前位排序,确保排序稳定。
时间复杂度
- 对每一位执行一次计数排序,时间复杂度为
O(n + k)
。 - 总共需要执行 d 次,时间复杂度为
O(d × (n + k))
。- d 是最大元素的位数。
- k 是基数(通常为 10)。
空间复杂度
- 需要额外的计数数组和输出数组,空间复杂度为
O(n + k)
。
基数排序演示
代码实现(C语言)
#include <stdio.h>
#include <stdlib.h>// 获取数组中的最大值
int getMax(int arr[], int n) {int max = arr[0];for (int i = 1; i < n; i++) {if (arr[i] > max) {max = arr[i];}}return max;
}// 对数组按当前位进行计数排序
void countingSort(int arr[], int n, int exp) {int output[n]; // 输出数组int count[10] = {0}; // 计数数组,用于存储每一位数字的出现次数// 统计当前位数字的出现次数for (int i = 0; i < n; i++) {int digit = (arr[i] / exp) % 10; // 提取当前位的数字count[digit]++;}// 计算累计计数,确保稳定排序for (int i = 1; i < 10; i++) {count[i] += count[i - 1];}// 根据当前位的数字,将元素放入输出数组for (int i = n - 1; i >= 0; i--) {int digit = (arr[i] / exp) % 10; // 提取当前位的数字output[count[digit] - 1] = arr[i];count[digit]--;}// 将排序后的结果复制回原数组for (int i = 0; i < n; i++) {arr[i] = output[i];}
}// 基数排序的主函数
void radixSort(int arr[], int n) {int max = getMax(arr, n); // 找到数组中的最大值// 从个位开始,对每一位进行计数排序for (int exp = 1; max / exp > 0; exp *= 10) {countingSort(arr, n, exp);}
}// 打印数组
void printArray(int arr[], int n) {for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");
}// 主函数
int main() {int arr[] = {170, 45, 75, 90, 802, 24, 2, 66};int n = sizeof(arr) / sizeof(arr[0]);printf("Original array:\n");printArray(arr, n);radixSort(arr, n);printf("Sorted array:\n");printArray(arr, n);return 0;
}
// (1) 获取最大值函数
// getMax 找到最大值,用于确定排序的位数(d)。
// 时间复杂度:O(n)。
// (2) 计数排序函数
// countingSort 按当前位(exp)对数组排序:
// 提取当前位的数字:(arr[i] / exp) % 10。
// 使用计数数组统计出现次数,完成稳定排序。
// (3) 基数排序主函数
// 对每一位(个位、十位、百位……)依次调用 countingSort。
// 外层循环次数为最大元素的位数 d。
// (4) 输出数组
// 使用 printArray 打印数组,方便调试和验证。
运行结果:
输入数组:
170, 45, 75, 90, 802, 24, 2, 66
排序过程(按位):
- 按个位排序:
170, 90, 802, 2, 24, 45, 66, 75
- 按十位排序:
802, 2, 24, 45, 66, 75, 170, 90
- 按百位排序:
2, 24, 45, 66, 75, 90, 170, 802
最终输出结果:
2, 24, 45, 66, 75, 90, 170, 802
基数排序基于分别排序,分别收集,所以是稳定的。基数排序是一种快速、稳定的排序算法,适合对整数或字符串进行排序。通过按位排序,避免了直接比较元素大小,在特定场景下(如大量非负整数排序),基数排序的效率优于比较排序算法(如快速排序)。
9. 计数排序(Counting Sort)
计数排序是一种非比较排序算法,适用于整数或离散范围较小的数据。通过统计每个元素出现的次数,并利用这些计数信息将数据排序。
算法原理
- 找出数组中的最大值和最小值,确定计数数组的大小。
- 创建一个计数数组 count,统计每个数字出现的次数。
- 对计数数组进行累加操作,计算每个元素的位置。
- 根据计数数组,将原数组中的元素放到正确的位置上,并生成输出数组。
时间复杂度
O(n + k)
(n 为数组长度,k 为数据范围)。
空间复杂度
O(k)
。
计数排序演示
代码实现(C语言)
#include <stdio.h>
#include <stdlib.h>// 计数排序
void countingSort(int arr[], int n) {// 找到数组中的最大值和最小值int max = arr[0], min = arr[0];for (int i = 1; i < n; i++) {if (arr[i] > max) max = arr[i];if (arr[i] < min) min = arr[i];}int range = max - min + 1; // 数据范围int* count = (int*)calloc(range, sizeof(int)); // 创建计数数组并初始化为 0int* output = (int*)malloc(n * sizeof(int)); // 创建输出数组// 统计每个元素的出现次数for (int i = 0; i < n; i++) {count[arr[i] - min]++;}// 计算计数数组的累加值for (int i = 1; i < range; i++) {count[i] += count[i - 1];}// 根据计数数组将元素放入正确位置,生成输出数组for (int i = n - 1; i >= 0; i--) {output[count[arr[i] - min] - 1] = arr[i];count[arr[i] - min]--;}// 将排序后的数组拷贝回原数组for (int i = 0; i < n; i++) {arr[i] = output[i];}// 释放动态分配的内存free(count);free(output);
}int main() {int arr[] = {4, 2, 2, 8, 3, 3, 1};int n = sizeof(arr) / sizeof(arr[0]);printf("Original array: ");for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");countingSort(arr, n);printf("Sorted array: ");for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}
运行结果
# 输入数组:
{4, 2, 2, 8, 3, 3, 1}
# 输出数组:
{1, 2, 2, 3, 3, 4, 8}
计数排序是一个稳定的排序算法。当输入的元素是 n 个 0到 k 之间的整数时,时间复杂度是O(n+k),空间复杂度也是O(n+k),其排序速度快于任何比较排序算法。当k不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。
计数排序适用于整数或范围较小的数据,具有高效的时间复杂度,但空间使用较大。
10. 桶排序(Bucket Sort)
桶排序是一种基于分布的排序算法,将输入数据分配到若干个桶(区间)中,然后对每个桶内的数据进行单独排序,最后将桶内的元素合并得到结果。
算法原理
- 确定桶的数量和每个桶的范围。
- 创建若干个桶,将元素分配到对应的桶中。
- 对每个桶内的元素进行排序(可以使用其他排序算法,如插入排序、快速排序等)。
- 将所有桶内的元素按序合并。
时间复杂度
O(n + k)
(k 为桶的数量)。
空间复杂度
O(n + k)
。
桶排序演示
代码实现(C语言)
#include <stdio.h>
#include <stdlib.h>// 桶排序中的插入排序
void insertionSort(int arr[], int n) {for (int i = 1; i < n; i++) {int key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}
}// 桶排序
void bucketSort(float arr[], int n) {// 创建 n 个桶,每个桶是一个动态数组int bucketCount = n;float** buckets = (float**)malloc(bucketCount * sizeof(float*));int* bucketSizes = (int*)calloc(bucketCount, sizeof(int)); // 存储每个桶的大小for (int i = 0; i < bucketCount; i++) {buckets[i] = (float*)malloc(n * sizeof(float)); // 每个桶最大容量为 n}// 将元素分配到对应的桶中for (int i = 0; i < n; i++) {int bucketIndex = (int)(arr[i] * bucketCount); // 根据值计算桶索引buckets[bucketIndex][bucketSizes[bucketIndex]++] = arr[i];}// 对每个桶内的数据进行排序for (int i = 0; i < bucketCount; i++) {insertionSort(buckets[i], bucketSizes[i]);}// 合并所有桶中的数据int index = 0;for (int i = 0; i < bucketCount; i++) {for (int j = 0; j < bucketSizes[i]; j++) {arr[index++] = buckets[i][j];}free(buckets[i]); // 释放桶内存}free(buckets);free(bucketSizes);
}int main() {float arr[] = {0.42, 0.32, 0.23, 0.52, 0.25, 0.47, 0.51};int n = sizeof(arr) / sizeof(arr[0]);printf("Original array: ");for (int i = 0; i < n; i++) {printf("%.2f ", arr[i]);}printf("\n");bucketSort(arr, n);printf("Sorted array: ");for (int i = 0; i < n; i++) {printf("%.2f ", arr[i]);}printf("\n");return 0;
}
运行结果:
# 输入数组:
{0.42, 0.32, 0.23, 0.52, 0.25, 0.47, 0.51}
# 输出数组:
{0.23, 0.25, 0.32, 0.42, 0.47, 0.51, 0.52}
桶排序最好情况下使用线性时间O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。
桶排序适用于浮点数或连续数据,通过分桶和排序实现高效排序,尤其在数据分布均匀时表现优异。
想要了解更多算法动画演示和代码逻辑在这个网站中可以查阅: https://visualgo.net/en
以上。仅供学习与分享交流,请勿用于商业用途!转载需提前说明。
我是一个十分热爱技术的程序员,希望这篇文章能够对您有帮助,也希望认识更多热爱程序开发的小伙伴。
感谢!
相关文章:
【算法】八大排序算法
这篇文章是对数据结构中 八大经典排序算法 的详解,包括其原理、实现过程、时间复杂度、空间复杂度及其适用场景。最后两种排序不常见,但仍收录了进来保持文章结构的完整性。 排序(Sort)是将无序的记录序列(或称文件)调整成有序的…...
pytest+allure 入门
使用allure如何生成自动化测试报告 ?一文详解allure的使用 。_allure测试报告-CSDN博客 例子: import allure import pytest import osallure.epic("闹钟") allure.feature("闹钟增删") class TestSchedule():def setu…...
算法--最大公约数,最小公倍数
1. 求两个数的最大公约数,最小公倍数 解释:这里Mymin和Mymax函数是自定义用于获取两数最大值和最小值的 求最大公约数的时候只需要得到两数之中最小的一项,向下逐个判断直到等于1 求最小公倍数的时候只需要得到两数之中最大的一项…...
【跨域问题】
跨域问题 官方概念: 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域本质来说,是前端请求给到后端时候,请求头里面,有一个 Origin ,会带上 协议域名端口号等;后端接受到请求&…...
为什么在二维卷积操作中,将宽度(W)维度放在高度(H)之前会破坏空间局部性原则,并影响缓存性能
空间局部性原则 空间局部性指的是程序倾向于访问与最近访问过的内存位置接近的内存位置。对于深度学习模型中的张量数据,这意味着当处理图像或特征图时,如果能够连续地访问相邻像素的数据,那么可以最大化利用CPU/GPU缓存,因为缓存…...
【C语言】_函数指针数组/转移表与回调函数
目录 1. 示例1:函数指针数组的简单使用 2. 示例2:多同类型函数调用 2.1 switch-case实现 2.2 switch-case函数指针 2.3 函数指针数组实现 3. 回调函数 关于函数指针,专栏文章链接如下:【C语言】_函数指针变量-CSDN博客https…...
《通过财报看企业》
“借贷关系”“净资产收益率”“财务报表”、净利润、盈利能力、现金流 第1章 净利润:决定一家公司的股价能涨多高 企业经营:存货周转率 企业市值:市值净利润市盈率 龙头企业:行业内收入规模最大、盈利能力最强,…...
年度技术突破奖|中兴微电子引领汽车芯片新变革
随着以中央计算区域控制为代表的新一代整车电子架构逐步成为行业主流,车企在电动化与智能化之后,正迎来以架构创新为核心的新一轮技术竞争。中央计算SoC,作为支撑智驾和智舱高算力需求的核心组件,已成为汽车电子市场的重要新增量。…...
力扣经典题目之912.排序数组(使用希尔排序解决)
今天继续给大家分享一道力扣的做题心得今天这道题目是 912.排序数组 题目链接:912. 排序数组 - 力扣(LeetCode) 题目:给你一个整数数组 nums,请你将该数组升序排列。 你必须在 不使用任何内置函数 的情况下解决问题…...
QT升级及下载缓慢的问题解决办法
QT升级及下载缓慢的问题解决办法 QT安装慢解决办法: 官方下载地址: https://www.qt.io/download-dev 点开后点击download 填写相关信息后即可下载完成 线上安装工具。 安装工具(qt-online-installer-windows-x64-4.8.1.exe) 如下图: 此时不…...
List详解 - 双向链表的操作
在C中,std::list是标准模板库(STL)中的一个容器,它实现了双向链表的数据结构。与数组或向量(std::vector)不同,std::list允许在常数时间内进行插入和删除操作,尤其是在链表的任意位置…...
公众号如何通过openid获取unionid
通过接口 https://api.weixin.qq.com/cgi-bin/user/info?access_tokenxxxxxxx&langzh_CN 返回的数据如下: 前提是必须绑定 微信开放平台 token如何获取呢 代码如下: String tokenUrl "https://api.weixin.qq.com/cgi-bin/token"; …...
AIP-1 AIP目的和指南
原文AIP-1: AIP Purpose and Guidelines 随着Google API数量不断增加,API治理团队不断扩张,以满足API维护工作需求。越来越有必要为API生产者、审查者和其他相关方提供一套参考文档。API风格指南和一站式介绍文档简洁扼要。AIP集合提供了一种产出一致性…...
【学习】CMMM智能制造能力成熟度评估的重要性
CMMM认证通过对企业当前生产状态的全面评估,能够精准地确定其智能化生产的程度,并将企业的智能化生产水平划分为五个等级,包括初始级、已定义级、以管理级、卓越级和顶级。这种等级划分使得不同类型的企业能够根据自身实际情况,选…...
WebGIS在应急灾害中对村庄、风景区、机场的影响范围应用-以日喀则市定日县地震为例
目录 前言 一、关于影响范围 1、震中距离5公里 2、震中20公里范围 3、20到80公里范围 二、空间查询知识 1、相关数据介绍 2、空间数据查询 三、前后端数据查询以及web可视化实现 1、后台API实现 2、WebGIS前端实现 四、Web成果展示 1、空间位置分析 2、包含风景区…...
Flink系列知识讲解之:网络监控、指标与反压
Flink系列知识之:网络监控、指标与反压 在上一篇博文中,我们介绍了 Flink 网络协议栈从高层抽象到底层细节的工作原理。本篇博文是网络协议栈系列博文中的第二篇,在此基础上,我们将讨论如何监控网络相关指标,以识别吞…...
Postman接口测试05|实战项目笔记
目录 一、项目接口概况 二、单接口测试-登录接口:POST 1、正例 2、反例 ①姓名未注册 ②密码错误 ③姓名为空 ④多参 ⑤少参 ⑥无参 三、批量运行测试用例 四、生成测试报告 1、Postman界面生成 2、Newman命令行生成 五、token鉴权(“…...
人工智能学习路线全链路解析
一、基础准备阶段(预计 2-3 个月) (一)数学知识巩固与深化 线性代数(约 1 个月): 矩阵基础:回顾矩阵的定义、表示方法、矩阵的基本运算(加法、减法、乘法)&…...
图像处理 | 图像二值化
在图像处理领域,图像二值化是一个重要的操作,它将彩色或灰度图像转换为只有两种颜色(通常是黑白)的图像。二值化广泛应用于文字识别、图像分割、边缘检测等领域,尤其在处理简洁和高对比度的图像时非常有效。本文将深入…...
ASP.NET Core 中服务生命周期详解:Scoped、Transient 和 Singleton 的业务场景分析
前言 在 ASP.NET Core 中,服务的生命周期直接影响应用的性能和行为。通过依赖注入容器 (Dependency Injection, DI),我们可以为服务定义其生命周期:Scoped、Transient 和 Singleton。本文将详细阐述这些生命周期的区别及其在实际业务中的应用…...
鼠标自动移动防止锁屏的办公神器 —— 定时执行专家
目录 ◆ 如何设置 ◇ 方法1:使用【执行Nircmd命令】任务 ◇ 方法2:使用【模拟键盘输入】任务 ◆ 定时执行专家介绍 ◆ 定时执行专家最新版下载 ◆ 如何设置 ◇ 方法1:使用【执行Nircmd命令】任务 1、点击工具栏第一个图标【新建任务】&…...
开源库:jcon-cpp
说明 jcon-cpp 是一个用于 C 的 JSON-RPC 库,它允许开发者通过 JSON-RPC 协议进行进程间通信(IPC)。JSON-RPC 是一种轻量级的远程过程调用协议,基于 JSON 格式数据进行通信。基于MIT协议,最新代码基于Qt6实现。可通过…...
Docker入门之docker基本命令
Docker入门之docker基本命令 官方网站:https://www.docker.com/ 1. 拉取官方镜像并创建容器(以redis为例) 拉取官方镜像 docker pull redis# 如果不需要添加到自定义网络使用这个命令,如需要,直接看第二步 docker r…...
C++ Qt练习项目 QChar功能测试
个人学习笔记 代码仓库 GitCode - 全球开发者的开源社区,开源代码托管平台 新建项目 设计UI 1、拖入group box去掉名字 2、拖入2个LineEdit 3、拖入两个Label 4、拖入两个PushButton 5、点栅格布局 1、拖入GroupBox 2、拖入4个PushButton 3、点栅格布局 1、拖入GroupBo…...
Taro+react 开发第一节创建 带有redux状态管理的项目
Taro 项目基于 node,请确保已具备较新的 node 环境(>16.20.0),推荐使用 node 版本管理工具 nvm 来管理 node,这样不仅可以很方便地切换 node 版本,而且全局安装时候也不用加 sudo 了。 1.安装 npm inf…...
【SOC 芯片设计 DFT 学习专栏 -- RTL 中的信号名和 Netlist 中的信号名差异】
Overview 本文将介绍 soc 设计中 RTL-to-Netlist 映射及 RTL 中的信号名和 Netlist 中的信号名差异, 在 SoC设计中,RTL-to-Netlist映射 是从RTL(Register Transfer Level)代码转换为Netlist的过程。这通常涉及将用硬件描述语言&…...
551 灌溉
常规解法: #include<bits/stdc.h> using namespace std; int n,m,k,t; const int N105; bool a[N][N],b[N][N]; int cnt; //设置滚动数组来存贮当前和下一状态的条件 //处理传播扩散问题非常有效int main() {cin>>n>>m>>t;for(int i1;i&l…...
计算机网络之---OSI七层模型
为什么会有七层模型 OSI七层模型的出现源于计算机网络技术的发展需求,主要解决以下几个问题: 标准化与互操作性 随着计算机网络的快速发展,不同厂商、不同技术之间的设备和系统需要能够无缝通信。而不同厂商在网络硬件、软件、协议等方面存在…...
spring task使用
Spring Task 简介 Spring Task 是 Spring 框架原生自带的任务调度框架,它犹如一把瑞士军刀,为开发者提供了丰富多样的功能,助力轻松创建和管理定时任务。相较于其他一些第三方任务调度框架,Spring Task 最大的优势在于其与 Sprin…...
ADB->查看进程并强杀进程
查看进程 adb shell ps | findstr com.example.myapplication// result u0_a275 26312 914 17185988 193260 do_freezer_trap 0 S com.example.myapplication用户USER: u0_a275 该字段表示运行此进程的用户。在 Android 中,应用通常以 uN_aM 的格式表…...
Qt重写webrtc的demo peerconnection
整个demo为: 可以选择多个编码方式: cmake_minimum_required(VERSION 3.5)project(untitled LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_INCLUDE_CURRENT_DIR ON)set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON)set(CMA…...
comfyui精准作图之gligen
简介 在 Stable Diffusion(SD)中,GLIGEN 是一种用于增强文本到图像生成模型可控性的技术。它通过在现有的预训练扩散模型(如 Stable Diffusion)基础上,引入额外的定位输入(如边界框、关键点或参…...
再次梳理ISP的大致流程
前言: 随着智能手机的普及,相机与我们的生活越来越紧密相关。在日常生活中,我们只需要轻轻按下手机上的拍照按钮,就能记录下美好时刻。那么问题来了:从我们指尖按下拍照按钮到一张色彩丰富的照片呈现在我们面前&#x…...
系统思考与因果智慧
“众生畏果,菩萨畏因”,这句话蕴藏着深厚的因果智慧,与系统思考不谋而合。 众生畏果,体现了大多数人的行为模式:关注的是眼前的问题与结果,比如失败、冲突、痛苦。正如在系统思考中,我们称之为…...
k8s排错集:zk集群的pod报错 Init:CrashLoopBackOff无法启动
zk三节点集群,zk-0无法启动 statefulset 进到该node节点上查看容器的报错日志,发现在初始化container的时候一个命令有问题 查看正常zk集群的pod的资源配置文件 解决办法: 修改资源配置文件 应该修改为 chown -R 1000:1000 /zkenv kubec…...
商品详情API接口数据解析,API接口系列(示例返回数据(JSON格式))
商品详情API接口是用于获取特定商品详细信息的编程接口。它通常返回JSON格式的数据,包含商品的各种属性,如名称、价格、描述、库存状态、图片URL等。以下是一个典型的商品详情API接口数据解析示例,以及如何调用和使用这些数据的基本步骤。 示…...
Qt官方下载地址
1. 最新版本 Qt官方最新版本下载地址:https://www.qt.io/download-qt-installer 当前最新版本Qt6.8.* 如下图: 2. 历史版本 如果你要下载历史版本安装工具或者源码编译方式安装,请转至此链接进行下载:https://download.qt.i…...
Python自学 - 类进阶(可调用对象)
返回目录 1 Python自学 - 类进阶(可调用对象) 可调用对象在Python中有很重要的作用,那什么是可调用对象呢? 可以简单的理解为,凡是对象可以加括号给参数的都叫可调用对象,如:obj(x)中obj就是可调用对象,因…...
键盘过滤驱动
文章目录 概述注意源码参考资料 概述 irp请求会从io管理器中传递到设备栈中依次向下发送,当到达底层真实设备处理完成后,会依次返回,这时如果在设备栈中有我们自己注册的设备,就可以起到一个过滤的功能。键盘过滤驱动就是如此&am…...
Type-C单口便携显示器-LDR6021
Type-C单口便携显示器是一种新兴的显示设备,它凭借其便携性、高性能和广泛的应用场景等优势,正在成为市场的新宠。以下是Type-C单口便携显示器的具体运用方式: 一、连接与传输 1. **设备连接**:Type-C单口便携显示器通过Type-C接…...
ClickHouse vs StarRocks 选型对比
一、面向列存的 DBMS 新的选择 Hadoop 从诞生已经十三年了,Hadoop 的供应商争先恐后的为 Hadoop 贡献各种开源插件,发明各种的解决方案技术栈,一方面确实帮助很多用户解决了问题,但另一方面因为繁杂的技术栈与高昂的维护成本&…...
服务器数据恢复—raid5故障导致上层ORACLE无法启动的数据恢复案例
服务器数据恢复环境&故障: 一台服务器上的8块硬盘组建了一组raid5磁盘阵列。上层安装windows server操作系统,部署了oracle数据库。 raid5阵列中有2块硬盘的硬盘指示灯显示异常报警。服务器操作系统无法启动,ORACLE数据库也无法启动。 服…...
鼠标过滤驱动
文章目录 概述代码参考资料 概述 其编写过程大体与键盘过滤驱动相似,只需要切换一下附加的目标设备以及创建的设备类型等。但在该操作后依然无法捕获到Vmware创建的win7操作系统的鼠标irp信息,于是通过在获取鼠标驱动,遍历其所有的设备进而附…...
SQL进阶实战技巧:LeetCode2201. 统计可以提取的工件?
目录 0 题目描述 1 数据准备 2 问题分析 第一步:生成每个工件的所有单元格 第二步:标记被挖掘的单元格...
Supermaven 加入 Cursor:AI 编码新篇章
引言 2024 年 11 月 11 日,我们迎来了一个激动人心的时刻——Supermaven 正式加入 Cursor! 这一合作标志着 AI 编程工具进入了一个新的发展阶段,为开发者提供更智能、更高效的编码体验。本文将带您了解此次合并的背景、意义以及未来的发展方…...
金融项目实战 01|功能测试分析与设计
前置内容:金融项目准备的内容笔记可直接看如下笔记 只看:一、投资专业术语 和 二、项目简介 两部分文章浏览阅读2.3k次,点赞70次,收藏67次。安享智慧理财金融系统测试项目,测试用例,接口测试,金…...
阿里云直播互动Web
官方文档:互动消息Web端集成方法_视频直播(LIVE)-阿里云帮助中心 以下是代码实现: <!-- 引入阿里云互动文件 --> <script src"https://g.alicdn.com/code/lib/jquery/3.7.1/jquery.min.js"></script> <script src&quo…...
python【输入和输出】
Python 有三种输出值的方式: 表达式语句print() 函数使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout 引用。 ① 将输出的值转成字符串,可以使用 repr() 或 str() 函数来实现: str(): 函数返回一个用户易…...
网络安全建设方案,信息安全风险评估报告,信息安全检测文档(Word原件完整版)
一、概述 1.1工作方法 1.2评估依据 1.3评估范围 1.4评估方法 1.5基本信息 二、资产分析 2.1 信息资产识别概述 2.2 信息资产识别 三、评估说明 3.1无线网络安全检查项目评估 3.2无线网络与系统安全评估 3.3 ip管理与补丁管理 3.4防火墙 四、威胁细…...
nexus搭建maven私服
说到maven私服每个公司都有,比如我上一篇文章介绍的自定义日志starter,就可以上传到maven私服供大家使用,每次更新只需deploy一下就行,以下就是本人搭建私服的步骤 使用docker安装nexus #拉取镜像 docker pull sonatype/nexus3:…...