解码数据有序之道——常见排序算法总结
本文整理了常见的排序算法,采用c++编码,并对其时间复杂度作以了分析。
1. 冒泡排序(Bubble Sort)
实现思路:
- 从数组的第一个元素开始,依次比较相邻的两个元素。
- 如果当前元素大于下一个元素,则交换它们的位置。
- 经过一轮比较,最大的元素会“浮”到数组的末尾。
- 重复这个过程,每一轮都把未排序部分的最大元素移到正确位置,总共需要进行
n - 1
轮(n
为数组元素个数)。
代码实现:
#include <iostream>
#include <vector>
using namespace std;void bubbleSort(vector<int>& arr) {int n = arr.size();for (int i = 0; i < n - 1; ++i) {for (int j = 0; j < n - i - 1; ++j) {if (arr[j] > arr[j + 1]) {swap(arr[j], arr[j + 1]);}}}
}
时间复杂度:
- 最好情况:数组已经有序,只需进行一轮比较,没有元素交换,时间复杂度为 O ( n ) O(n) O(n)。
- 最坏情况:数组完全逆序,需要进行
n - 1
轮比较,每轮比较n - i - 1
次(i
为当前轮数),时间复杂度为 O ( n 2 ) O(n^2) O(n2)。 - 平均情况:时间复杂度也是 O ( n 2 ) O(n^2) O(n2)。
2. 选择排序(Selection Sort)
实现思路:
- 首先在未排序的序列中找到最小(大)元素,存放到排序序列的起始位置。
- 然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。
- 重复这个过程,直到所有元素均排序完毕,一共需要进行
n - 1
次选择操作(n
为数组元素个数)。
代码实现:
#include <iostream>
#include <vector>
using namespace std;void selectionSort(vector<int>& arr) {int n = arr.size();for (int i = 0; i < n - 1; ++i) {int minIndex = i;for (int j = i + 1; j < n; ++j) {if (arr[j] < arr[minIndex]) {minIndex = j;}}swap(arr[i], arr[minIndex]);}
}
时间复杂度:
- 无论数组初始状态如何,都需要进行
n - 1
轮选择操作,每轮都要遍历剩余未排序元素,所以最好、最坏、平均情况的时间复杂度都是 O ( n 2 ) O(n^2) O(n2)。
3. 插入排序(Insertion Sort)
实现思路:
- 将数组分为已排序和未排序两部分,初始时已排序部分只有第一个元素。
- 取未排序部分的第一个元素,将其插入到已排序部分的合适位置,使得已排序部分依然有序。
- 重复这个过程,直到未排序部分为空。
代码实现:
#include <iostream>
#include <vector>
using namespace std;void insertionSort(vector<int>& arr) {int n = arr.size();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;}
}
时间复杂度:
- 最好情况:数组已经有序,每次插入操作只需比较一次,时间复杂度为 O ( n ) O(n) O(n)。
- 最坏情况:数组完全逆序,每次插入都要和已排序部分的所有元素比较并移动,时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
- 平均情况:时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
4.希尔排序(Shell Sort)
实现思路
- 希尔排序是对插入排序的改进,它的基本思想是先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序。
- 首先选择一个合适的间隔(称为“步长”或“增量”,通常初始化为数组长度的一半,然后每次缩小一半,直到步长为1)。
- 按照选定的步长,对相隔该步长的元素组成的子序列进行插入排序,例如步长为
gap
时,会把数组分成多个子序列,分别是arr[0], arr[gap], arr[2 * gap],...
、arr[1], arr[1 + gap], arr[1 + 2 * gap],...
等这些子序列,对每个子序列进行插入排序操作。 - 随着步长逐渐减小,子序列的元素个数逐渐增多,当步长最终减为1时,整个数组就相当于进行了一次普通的插入排序,但此时由于前面以较大步长进行了预排序,元素已经相对更接近最终位置,所以最后一次插入排序会比直接对原始数组进行插入排序效率更高。
代码实现
#include <iostream>
#include <vector>
using namespace std;void shellSort(vector<int>& arr) {int n = arr.size();for (int gap = n / 2; gap > 0; gap /= 2) {for (int i = gap; i < n; i++) {int temp = arr[i];int j;for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {arr[j] = arr[j - gap];}arr[j] = temp;}}
}
时间复杂度
- 希尔排序的时间复杂度与所选取的步长序列有关,它的时间复杂度分析比较复杂。
- 最好情况:当数组已经有序时,时间复杂度接近 O ( n ) O(n) O(n),因为每个子序列在插入排序时几乎不需要移动元素。
- 最坏情况:时间复杂度依赖于步长序列,不同的步长序列会导致不同的最坏情况时间复杂度,不过通常认为其最坏情况时间复杂度在 O ( n 2 ) O(n^2) O(n2) 左右,例如使用
Hibbard
序列作为步长时最坏情况为 O ( n 3 / 2 ) O(n^{3/2}) O(n3/2) 等。 - 平均情况:平均时间复杂度介于 O ( n ) O(n) O(n) 和 O ( n 2 ) O(n^2) O(n2) 之间,常见的分析结果大约是 O ( n 1.3 ) O(n^{1.3}) O(n1.3) 左右。
5. 快速排序(Quick Sort)
实现思路:
- 选择一个基准元素(通常是数组的最后一个元素)。
- 通过一趟排序将数组分为两部分,左边部分的元素都小于等于基准元素,右边部分的元素都大于基准元素。
- 对左右两部分分别递归地进行快速排序,直到子数组的长度为1或者0。
代码实现:
#include <iostream>
#include <vector>
using namespace std;int partition(vector<int>& arr, int low, int high) {int pivot = arr[high];int i = low - 1;for (int j = low; j < high; ++j) {if (arr[j] <= pivot) {++i;swap(arr[i], arr[j]);}}swap(arr[i + 1], arr[high]);return i + 1;
}void quickSort(vector<int>& arr, int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}
}
时间复杂度:
- 最好情况:每次划分都能把数组均匀地分成两部分,时间复杂度为 O ( n log n ) O(n \log n) O(nlogn)。
- 最坏情况:数组已经有序或者逆序,每次划分只得到一个元素和剩余元素的子数组,时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
- 平均情况:时间复杂度为 O ( n log n ) O(n \log n) O(nlogn)。
6. 归并排序(Merge Sort)
实现思路:
- 采用分治思想,先将数组不断地分成两半,直到每个子数组只有一个元素(这是递归分解的过程)。
- 然后将相邻的子数组合并成有序的数组,合并时比较两个子数组的元素,依次放入新的临时数组中,再将临时数组的元素复制回原数组对应位置(这是合并的过程)。
- 重复合并过程,直到整个数组有序。
代码实现:
#include <iostream>
#include <vector>
using namespace std;void merge(vector<int>& arr, int l, int m, int r) {int n1 = m - l + 1;int n2 = r - m;vector<int> L(n1), R(n2);for (int i = 0; i < n1; ++i) {L[i] = arr[l + i];}for (int j = 0; j < n2; ++j) {R[j] = arr[m + 1 + j];}int i = 0, j = 0, k = l;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(vector<int>& arr, int l, int r) {if (l < r) {int m = l + (r - l) / 2;mergeSort(arr, l, m);mergeSort(arr, m + 1, r);merge(arr, l, m, r);}
}
时间复杂度:
- 无论数组初始状态如何,每次划分都是 O ( 1 ) O(1) O(1) 的时间复杂度,合并操作总的时间复杂度为 O ( n ) O(n) O(n),一共要进行 log n \log n logn 层划分与合并,所以时间复杂度始终为 O ( n log n ) O(n \log n) O(nlogn)。
7. 堆排序(Heap Sort)
实现思路:
- 首先将数组构建成一个最大堆(从最后一个非叶子节点开始,对每个节点进行堆化操作,保证父节点大于等于子节点)。
- 然后把堆顶元素(最大值)与堆的最后一个元素交换,此时最大值就在正确的排序位置了,接着对剩下的元素重新进行堆化,使其再次成为最大堆。
- 重复这个过程,直到整个数组有序。
代码实现:
#include <iostream>
#include <vector>
using namespace std;void heapify(vector<int>& arr, int n, int i) {int largest = i;int l = 2 * i + 1;int r = 2 * i + 2;if (l < n && arr[l] > arr[largest]) {largest = l;}if (r < n && arr[r] > arr[largest]) {largest = r;}if (largest!= i) {swap(arr[i], arr[largest]);heapify(arr, n, largest);}
}void heapSort(vector<int>& arr) {int n = arr.size();for (int i = n / 2 - 1; i >= 0; --i) {heapify(arr, n, i);}for (int i = n - 1; i > 0; --i) {swap(arr[0], arr[i]);heapify(arr, i, 0);}
}
时间复杂度:
- 建堆过程时间复杂度为 O ( n ) O(n) O(n),每次调整堆的时间复杂度为 O ( log n ) O(\log n) O(logn),总共需要进行
n - 1
次调整堆操作,所以时间复杂度为 O ( n log n ) O(n \log n) O(nlogn)。
8.基数排序
实现思路
- 基数计数与分配
- 基数排序的核心思想是根据数字的每一位来进行排序。对于一个整数数组,首先确定数字的最大位数(d)(例如对于十进制数,最大位数可能是数组中最大数的位数)。
- 从最低位(个位)开始,依次对每一位进行排序。对于每一位,创建(r)个桶(对于十进制数(r = 10),即0 - 9号桶)。
- 遍历数组中的每个元素,根据当前位的数字值将元素放入相应的桶中。例如,如果当前位是个位,数字(123)的个位是(3),则将(123)放入(3)号桶中。
- 收集与重复
- 按照桶的顺序(从(0)号桶到(r - 1)号桶)依次收集元素,将桶中的元素放回原数组,此时原数组就按照当前位进行了排序。
- 然后处理下一位,重复上述分配和收集的过程,直到处理完最高位。这样,经过(d)轮处理后,数组就完成了排序。
时间复杂度
- 平均情况
- 时间复杂度为(O(d(r + n))),其中(d)是数字的最大位数,(r)是基数(例如十进制数(r = 10)),(n)是待排序元素的个数。
- 分析如下:对于每一位(共(d)位),需要遍历(n)个元素来分配到®个桶中,这一步的时间复杂度是(O(n))。然后需要遍历®个桶来收集元素,时间复杂度是(O®)。所以每一位的处理时间复杂度是(O(n + r)),总共(d)位,所以平均时间复杂度是(O(d(n + r)))。
- 最好情况
- 当所有元素的位数都相同时,时间复杂度为(O(d(n + r))),这与平均情况相同。因为即使元素已经有序,基数排序仍然需要按照每一位进行处理。
- 最坏情况
- 时间复杂度为(O(d(n + rd)))。这种情况可能发生在所有元素的最高位都不同,并且每一位的取值范围很大(接近(r))。在这种情况下,对于每一位,都需要处理所有的桶,而桶的数量最多可以达到(rd)(例如,当所有元素的每一位都不同时)。
代码实现(对十进制整数数组进行排序)
#include <iostream>
#include <vector>
#include <algorithm>// 基数排序函数
void radixSort(std::vector<int>& arr) {// 找到数组中的最大值,确定最大位数int maxVal = *std::max_element(arr.begin(), arr.end());for (int exp = 1; maxVal / exp > 0; exp *= 10) {// 创建计数数组,用于统计每个桶中的元素个数std::vector<int> count(10, 0);// 计算每个元素在当前位上的数字,统计每个桶中的元素个数for (int i = 0; i < arr.size(); i++) {count[(arr[i] / exp) % 10]++;}// 计算计数数组的前缀和,确定每个桶中元素在输出数组中的位置for (int i = 1; i < 10; i++) {count[i] += count[i - 1];}// 创建输出数组,用于存储排序后的结果std::vector<int> output(arr.size());// 将元素放入相应的桶中,并按照顺序放入输出数组for (int i = arr.size() - 1; i >= 0; i--) {output[count[(arr[i] / exp) % 10] - 1] = arr[i];count[(arr[i] / exp) % 10]--;}// 将排序后的结果复制回原数组for (int i = 0; i < arr.size(); i++) {arr[i] = output[i];}}
}
测试程序
可用以下代码测试这些排序算法(将所要测试的代码取消注释即可,此时为测试堆排序):
int main() {vector<int> arr = { 5, 4, 3, 2, 1 };// bubbleSort(arr);// selectionSort(arr);//shellSort(arr);// insertionSort(arr);// quickSort(arr, 0, arr.size() - 1);// mergeSort(arr, 0, arr.size() - 1);// radixSort(arr);heapSort(arr);for (int num : arr) {cout << num << " ";}cout << endl;return 0;
}
各排序算法总结与比较:
类别 | 排序方法 | 时间复杂度 | 空间复杂度 | 稳定性 | 备注 | ||
---|---|---|---|---|---|---|---|
平均情况 | 最好情况 | 最坏情况 | 辅助存储 | ||||
插入排序 | 直接插入 | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 稳定 | 数据量小时较好 |
Shell排序 | O ( n 1.3 ) O(n^{1.3}) O(n1.3) | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 不稳定 | ||
选择排序 | 直接选择 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 不稳定 | 数据量小时较好 |
堆排序 | O ( n log 2 n ) O(n\log_2 n) O(nlog2n) | O ( n log 2 n ) O(n\log_2 n) O(nlog2n) | O ( n log 2 n ) O(n\log_2 n) O(nlog2n) | O ( 1 ) O(1) O(1) | 不稳定 | 数据量大时较好 | |
交换排序 | 冒泡排序 | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 稳定 | 数据量小时较好 |
快速排序 | O ( n log 2 n ) O(n\log_2 n) O(nlog2n) | O ( n log 2 n ) O(n\log_2 n) O(nlog2n) | O ( n 2 ) O(n^2) O(n2) | O ( log 2 n ) O(\log_2 n) O(log2n) | 不稳定 | 数据量大时较好 | |
归并排序 | O ( n log 2 n ) O(n\log_2 n) O(nlog2n) | O ( n log 2 n ) O(n\log_2 n) O(nlog2n) | O ( n log 2 n ) O(n\log_2 n) O(nlog2n) | O ( n ) O(n) O(n) | 稳定 | 数据量大时较好 | |
基数排序 | O ( d ( r + n ) ) O(d(r + n)) O(d(r+n)) | O ( d ( n + r d ) ) O(d(n + r^d)) O(d(n+rd)) | O ( d ( r + n ) ) O(d(r + n)) O(d(r+n)) | O ( r d + n ) O(r^d + n) O(rd+n) | 稳定 |
注:基数排序的复杂度中, r r r代表关键字的基数, d d d代表长度, n n n代表关键字的个数
总结
不同的排序算法在不同场景下有不同的性能表现。插入排序在数据量小且基本有序时效率较高;选择排序简单但效率相对较低;交换排序中的冒泡排序适用于数据量小的情况,快速排序在平均情况下性能很好但最坏情况较差;堆排序适用于数据量大且不需要稳定排序的情况;归并排序性能稳定但需要额外空间;基数排序适用于对整数等有特定结构数据的排序,且在数据范围有限时效率较高。在实际使用时,根据数据特点和需求选择合适的排序算法。
相关文章:
解码数据有序之道——常见排序算法总结
本文整理了常见的排序算法,采用c编码,并对其时间复杂度作以了分析。 1. 冒泡排序(Bubble Sort) 实现思路: 从数组的第一个元素开始,依次比较相邻的两个元素。如果当前元素大于下一个元素,则交…...
C语言实现图片文件的复制
在C语言中,直接处理图片文件(如JPEG、PNG等)的复制,通常涉及到文件I/O操作。这些图片文件是二进制文件,因此需要使用二进制模式读取和写入文件。 图片文件复制代码: #include <stdio.h> #include&l…...

一、windows上配置ninja环境
Ninja是Google的一名程序员推出的注重速度的构建工具,一般在Unix/Linux上的程序通过make/makefile来构建编译,而Ninja通过将编译任务并行组织,大大提高了构建速度。下面介绍了windows上配置Ninja环境。 1.下载Ninja ninja官网地址࿱…...

我们来编程 -- win11多jdk版本切换
题记 售前的酒喝到位了调研需求及文档整理出来了开发要入场了,真惨啊!年底了,手里活干的好好的,因为flyback在项目地,硬是被安排进来了拥抱变化,我呸…不得不切换系统,构建代码,一股…...
JAVA 图形界面编程 AWT篇(1)
前言 为了应对JAVA课设,小编走上了java的图形界面编程的道路,通过博客分享自己的学习历程,并进行笔记的记录。 AWT(Abstract Window Toolkit)介绍 AWT(抽象窗口工具包)是 Java 最早的图形用户界…...

C语言 字符串输入输出函数、scanf(“%[^\n]“,)可输入空格 、fgets删除换行符
字符串输入函数: scanf("%s",数组名) gets(数组名) fgets() --- 文件流输入函数 函数原型: int scanf( const char *format, ...…...

【蓝桥杯每日一题】推导部分和——带权并查集
推导部分和 2024-12-11 蓝桥杯每日一题 推导部分和 带权并查集 题目大意 对于一个长度为 ( N ) 的整数数列 A 1 , A 2 , ⋯ , A N A_1, A_2, \cdots, A_N A1,A2,⋯,AN ,小蓝想知道下标 ( l ) 到 ( r ) 的部分和 ∑ i l r A i A l A l 1 ⋯ A r \sum_{…...

Linux 磁盘满了怎么办?快速排查和清理方法
当 Linux 磁盘满了,会导致系统无法正常运行,比如无法写入文件、服务停止、甚至系统崩溃。因此,快速排查并清理磁盘空间是非常重要的。以下是详细的排查和解决步骤: 一、快速定位磁盘占用原因 1. 检查磁盘使用情况 使用 df 命令查…...

【专题】2024年中国新能源汽车用车研究报告汇总PDF洞察(附原数据表)
原文链接: https://tecdat.cn/?p38564 本年度,国家及地方政府持续发力,推出诸多政策组合拳,全力推动汽车产业向更高质量转型升级,积极鼓励消费升级,并大力推行以旧换新等惠民生、促发展举措。尤为引人注目…...

数据结构之链表笔试题详解
一:移除链表元素 我们很容易就可以想到一个解决方案:再创建一个链表,把不是val的结点拿过来尾插。 这样确实可以但是,我们每次尾插都需要遍历一遍整个链表,这样时间复杂度就变成了O(n^2), 因此我们不妨设…...

结构化的Prompt
资源库: AI 提示词-WayToAGI精选高效的AI提示词库,助力创作者和开发者解锁人工智能的潜力。通过我们的提示词和策略,优化您的AI工具使用效率,激发创意思维,提升产出质量。https://www.waytoagi.com/prompts?tag6 结构…...

【数字化】华为数字化转型架构蓝图
导读:华为的数字化转型规划团队在2016年年底基于对愿景的系统诠释,整合出了数字化转型架构蓝图。该蓝图共分为5层,旨在通过数字化转型实现客户交互方式的转变、作战方式的转变、公司各平台业务能力的数字化、服务化以及运营模式的转变。 目录…...

最新全开源IM即时通讯系统源码(PC+WEB+IOS+Android)部署指南
全开源IM(即时通讯)系统源码部署是一个复杂但系统的过程,涉及多个组件和步骤。以下是一个详细的部署指南,旨在帮助开发者或系统管理员成功部署一个全开源的IM系统,如OpenIM。 IM即时通讯系统源码准备工作 …...
go 跨平台打包
GOARCH是Go语言中的一个环境变量,用于指定目标平台的底层架构。在Go的交叉编译过程中,GOARCH决定了编译出的二进制文件将在哪种硬件架构上运行。 GOARCH的常见值 amd64:64位 x86 架构386:32位 x86 架构arm&am…...
C++ 给定字符串,然后给出开始要取的位置,返回取到的信息
3 happy new year 7 year 1 new 4 new year year error input #include <stdio.h> #include <string.h> void strmcpy(char* s, char* t, int m); int main() {int repeat, m;char t[1000], s[1000];scanf("%d", &repeat);getchar(); //吸收换行符in…...

【树莓派4B】MindSpore lite 部署demo
一个demo,mindspore lite 部署在树莓派4B ubuntu22.04中,为后续操作开个门! 环境 开发环境:wsl-ubuntu22.04分发版部署环境:树莓派4B,操作系统为ubuntu22.04mindspore lite版本:mindspore-li…...

Idea汉化插件Datagrip汉化插件
汉化插件 Chinese (Simplified) Language Pack / 中文语言包 插件地址 安装完了之后,如果还不是中文的怎么办 需要手动设置 Seetings -> Appearance & Behavior -> System Settings -> Language and Region -> Language 修改为 [ Chi…...

精彩回顾|Cocos开发者沙龙长沙站
长沙-不一样 Cocos 开发者沙龙长沙站,完全超出了我们的预期,一开始还担心没有太多人报名。最后发现,全场爆满,座无虚席。 <<< 左右滑动见更多 >>> 许多小伙伴曾反馈过,在以往的开发者沙龙回顾文章中…...

算法日记 49 day 图论(A*算法)
这算是算法的最后一篇了,原本A*之前还有一些相关的最短路径算法的,比如dijkstra的堆优化,SPFA等等,但是有些我没看懂,就不写了,用A*做个结尾。 题目:骑士的攻击 127. 骑士的攻击 (kamacoder.co…...
服务器批量清理redis keys,无法适用客户端必须直连的情况
在 Redis 中,批量清理指定模式的键(例如 memberCardData:*)可以通过多种方法来实现。需要注意的是,Redis 的命令执行是单线程的,因此对大量键进行操作时可能会阻塞服务器。以下是几种常见的方法: shell K…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...