各种排序算法
前置知识
排序: 按照递增或者递减的顺序把数据排列好
稳定性: 值相等的元素在排序之后前后顺序是否发生了改变
内部排序: 数据放在内存上
外部排序: 数据放在磁盘上
内部排序
基于比较的排序
几大排序算法
1. 堆排序
特点:
思想:
1. 创建大根堆,把所有元素放在大根堆里面
2. 定义变量end,作为最后一个有效元素的下标
3. 交换0下标和end下标的值
4. 进行0下标到end下标的向下调整
5. end--;
这样就可以把大的元素放在后面,从小到大一次按照层序遍历排好
具体代码:
//堆排序private static void creatHeap(int[] array) {for (int parent = (array.length - 1 - 1) / 2; parent >= 0 ; parent--) {siftDown(array,parent,array.length);}}//TODO alt+enterprivate static void siftDown(int[] array,int parent,int length) {int child = 2 * parent + 1;while (child < length) {if(child + 1 < length && array[child] < array[child + 1]) {child++;}if(array[child] > array[parent]) {swap(array,child,parent);parent = child;child = 2*parent+1;}else {break;}}}public static void heapSort(int[] array) {//创建大根堆creatHeap(array);int end = array.length - 1;while (end > 0) {swap(array,0,end);siftDown(array,0,end);end--;}}
2. 直接插入排序
特点:
时间复杂度:
最坏情况:O(n^2)
最好情况:O(n) 当数据越有序,排序越快
适用情况: 待排序序列 已经基本上基于有序了
空间复杂度:O(1)
稳定性: 稳定(如果一个排序是稳定的就可以变成不稳定的,但是不稳定的不能变成稳定的)
主要思想:
1. 假设从第一个元素是有序的
2. 从第二个元素开始就一次和前面的元素进行比较,找到合适的位置就插进去.
具体代码:
public static void insertSort(int[] array) {//从第一个元素开始for (int i = 1; i < array.length ; i++) {int j = i - 1;//保存当前下标的值int tem = array[i];//加不加=会对稳定性产生影响,如果一个排序是稳定的就可以变成不稳定的,但是不稳定的不能变成稳定的)for (; j >= 0 ; j--) {//如果前面的元素大于tem,就往前移动if(array[j] > tem) {array[j+1] = array[j];//不用i的原因是j会一直改变,不一定就是j的前一个}else {break;}//最后把元素放在前面//因为循环出来的条件表示必须j要小于0,所以直接传j会下标越界}array[j + 1] = tem;}}
3. 希尔排序
特点:
时间复杂度: O(n^0.25)~O(1.6n^0.25)
空间复杂度: O(1)
稳定性: 不稳定
主要思想:
1. 分组,组内进行排序(直接插入排序)
2. 然后逐渐缩小组数
注意:
组数大于1排序都是预排序
缩小增量到最后.然后进行直接插入排序
具体代码:
public static void shellsort(int[] array) {//分组int gap = array.length;while (gap > 0){gap /= 2;//每次分组进行一次直接插入排序shell(array,gap);}}public static void shell(int[] array,int gap) {//我们默认第一个元素是有序的for (int i = gap; i < array.length; i++) {int temp = array[i];//j下标等于i前面一个gap的下标值int j = i - gap;//然后逐渐和该组前面的数进行比较for(; j >= 0 ; j -= gap) {if(array[j] > temp) {//往前移动一个gap的array[j + gap] = array[j];}else {break;}}array[j + gap] = temp;}}
4. 选择排序
特点:
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:不稳定
主要思想:
1. 俩层循环, 外层循环相当于每一次提供一个比较数,内层循环就把比较数后面的数和比较数进行比较,如果比比较数还小,就记录下来下标的值
2. 内层循环完之后,说明我们找到了这一趟最小值的下标,让其和外层循环所指的元素进行交换.
另一种写法: 双向选择排序
1. 找最大最小值下标,然后放在l和r里面.
2. 交换 l和minIndex下标所指向的值,交换r和maxIndex下标所指向的值
3. l++,r--
不过有个特殊情况:当maxIndex就是i下标的值,会出现问题,如图
具体代码:
法1:
public static void selectSort(int[] array) {for (int i = 0; i < array.length; i++) {int min = i;//让j为i+1for (int j = i + 1; j < array.length; j++) {if(array[min] > array[j]) {min = j;//min保存的是每一趟最小值的下标}}int tmp = array[i];array[i] = array[min];array[min] = tmp;}}
法2:
public static void selectSort2(int[] array) {//定义左右下标分别指向第一个和最后一个元素int left = 0;int right = array.length - 1;while (left < right){//定义max和min来记录最大最小值的下标int maxIndex = left;int minIndex = left;for (int i = left; i <= right; i++) {//记录最大最小值的下标if (array[minIndex] > array[i]) {minIndex = i;}if (array[maxIndex] < array[i]) {maxIndex = i;}}//交换值swap(array,left,minIndex);//如果最大值的下标就是left的下标,那么在进行最小值下标交换的的时候,最大值的下标就会改变if(maxIndex == left) {maxIndex = minIndex;}swap(array,right,maxIndex);//改变下标left++;right--;}}
5. 冒泡排序
特点:
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性: 稳定的排序
主要思想:
内层循环每次每次从0开始,把小的交换到前面,大的换到后面,每一轮回,把该轮的最大值换到最后.
优化后:
特点:
时间复杂度:
最好的情况:O(n)
具体思想:
优化:
1. 减少j的遍历次数
2. 考虑极端情况,如果有序的话,我们就直接可以结束循环
具体代码:
未优化版本:
public static void bubbleSort(int[] array) {//i表示趟数for (int i = 0; i < array.length - 1; i++) {//j来比较每个数据的大小for (int j = 0; j < array.length - 1 ; j++) {if(array[j] > array[j + 1]) {swap(array,j,j+1);}}}}
优化版本:
public static void bubbleSort1(int[] array) {//i表示趟数for (int i = 0; i < array.length - 1; i++) {boolean flag = false;//j来比较每个数据的大小
// for (int j = 0; j < array.length - 1 - i; j++) {for (int j = 0; j < array.length - 1 - i ; j++) {//优化1if(array[j] > array[j + 1]) {swap(array,j,j+1);flag = true;}}if (flag == false) {break;}}}
6. 快速排序(分治思想)
递归:
这几种方法不同主要是在找基准的时候方法不一样
法1 Hoare法
特点:
时间复杂度:
最好情况下:O(nlog2^n)
最坏情况下:O(n^2) 逆序/有序(递归开辟的栈帧太多了,会溢出)
空间复杂度:
最好情况下: O(log2^n)
最坏情况下: O(n) 逆序/有序
稳定性:不稳定
主要思想:
1. 用递归(二叉树前序遍历的思想),不同区间的第一个元素作为基准值
2. 小于基准值的放左边,大于基准值的放右边
法2(挖坑法)
主要思想:
法3 前后指针法
主要思想:
prev指向比基准小的最后一个位置
cur一直去找比基准小的
注意的点:
1. array[right] >= tmp 等于号(不等于可能会死循环,比如首位都是值一样的元素的时候)
2. 为什么从右边开始不从左边开始? 从左边开始一定是遇到比它大的停下来,所以再交换的话,比基准大的数字就换到前面去了
具体代码:(3会1即可),但是思想要明白
Hoare法
public static void quickSort(int[] array) {quick(array,0,array.length - 1);}private static void quick(int[] array, int start, int end) {//走到头了if (start >= end) {return;}//找到基准值//相当于二叉树的前序遍历int pivot = partitionHoare(array,start,end);//调整左区间quick(array,start,pivot - 1);//调整右区间quick(array,pivot + 1,end);}
法2(挖坑法)
public static void quickSort1(int[] array) {quick1(array,0,array.length - 1);}private static void quick1(int[] array, int start, int end) {//走到头了if (start >= end) {return;}//找到基准值int pivot = partitionHole(array,start,end);//调整左区间quick(array,start,pivot - 1);//调整右区间quick(array,pivot + 1,end);}//TODO 第二种方法,挖坑法private static int partitionHole(int[] array,int left,int right) {//记录第一个元素的值,把它作为基准int tmp = array[left];int i = left;while (left < right) {while (left < right && array[right] >= tmp) {right--;}//直接把比它小的值填坑即可array[left] = array[right];while (left < right && array[left] <= tmp) {left++;}//直接把比它大的值填坑即可array[right] = array[left];}//相遇的位置就把tmp也填坑array[left] = tmp;//返回基准值的下标return left;}
法3 前后指针法
public static void quickSort2(int[] array) {quick2(array,0,array.length - 1);}private static void quick2(int[] array, int start, int end) {//走到头了if (start >= end) {return;}//找到基准值int pivot = partitionIndex(array,start,end);//调整左区间quick(array,start,pivot - 1);//调整右区间quick(array,pivot + 1,end);}//TODO 第三种方法找基准 前后指针法//prev记录比基准小的最后一个位置//cur来找比基准小的数据//三种会一个就可以,建议选前俩种private static int partitionIndex(int[] array, int left, int right) {int prev = left;int cur = left + 1;while (cur <= right) {if (array[cur] < array[left] && array[++prev] != array[cur]) {swap(array, cur, prev);}cur++;}swap(array, prev, left);return prev;}
总结:(代码会一种就行,但是三种思想要会)
写选择题,先试2后1再3
1. Hoare
2. 挖坑法
3. 前后指针法
这三种方式 每次划分之后的前后顺序 有可能是不一样的
优化:
1. 主要就是减少递归的次数(均匀的分割,降低树的高度)
法1. 三数取中法(三个数找中位数,分俩个大类,每个类又包含三个子类)
法2. 递归到小的子区间时,可以考虑使用插入排序(我们越递归到后面,区间越小,越有序,那么此时就使用直接插入排序)
具体代码:
public static void quickSort3(int[] array) {quick3(array,0,array.length - 1);}//规定array[mid]<array[left]<array[right],排好序
//求中位数的下标private static int middleNum(int[] array,int left,int right) {int mid = (left + right) / 2;//每次分三种情况来讨论if(array[left] < array[right]) {//mid>rightif(array[mid] > right) {return right;}else if(array[mid] < left) {return left;}else {return mid;}}else {//array[left] > array[right]if(array[mid] < array[right]) {return right;}else if(array[mid] > array[left]) {return left;}else {return mid;}}}private static void quick3(int[] array, int start, int end) {//走到头了if (start >= end) {return;}//TODO 优化2我们越递归到后面,区间越小,越有序,那么此时就使用直接插入排序if(end - start + 1 <= 15) {insertSort(array,start,end);return;}
// System.out.println("start: " + start + "end" + end);//TODO 优化1三数取中法//1 2 3 4 5 6 7//得到中间大的位置int index = middleNum(array,start,end);//把中间大的放在基准位置swap(array,start,index);//4 2 3 1 5 6 7//找到基准值//相当于二叉树的前序遍历int pivot = partitionHoare1(array,start,end);//调整左区间quick(array,start,pivot - 1);//调整右区间quick(array,pivot + 1,end);}private static void insertSort(int[] array, int left, int right) {//从第一个元素开始for (int i = left + 1; i <= right ; i++) {int j = i - 1;//保存当前下标的值int tem = array[i];//加不加=会对稳定性产生影响,如果一个排序是稳定的就可以变成不稳定的,但是不稳定的不能变成稳定的)for (; j >= left ; j--) {//如果前面的元素大于tem,就往前移动if(array[j] > tem) {array[j+1] = array[j];//不用i的原因是j会一直改变,不一定就是j的前一个}else {break;}//最后把元素放在前面//因为循环出来的条件表示必须j要小于0,所以直接传j会下标越界}array[j + 1] = tem;}}
非递归:
思路:
使用栈,
通过分割区间调用pivot来进行区间的排序
1. 调用partition方法找到pivot
2. 分别判断左右区间有没有俩个元素(pivot+1和end进行比较,pivot-1和start进行比较)
3. 判断栈空不空,不空就取出俩个元素,建立新的区间->1
具体代码:
public static void quickSortNor(int[] array,int start, int end){Stack<Integer> stack = new Stack<>();//指定start和end的指向start = 0;end = array.length - 1;//找到基准值int pivot = partitonHoare(array,start,end);////判断左右是否有至少俩个元素if(pivot + 1 < end) {//把区间入栈stack.push(array[pivot + 1]);stack.push(end);}if(pivot - 1 > start) {//把区间入栈stack.push(array[start]);stack.push(array[pivot - 1]);}//栈不空就取出俩个元素while (!stack.isEmpty()) {int right = stack.pop();int left = start;pivot = partitonHoare(array,start,end);//判断左右是否有至少俩个元素if(pivot + 1 < end) {//把区间入栈stack.push(array[pivot + 1]);stack.push(end);}if(pivot - 1 > start) {//把区间入栈stack.push(array[start]);stack.push(array[pivot - 1]);}}}
//hoare找基准private static int partitonHoare(int[] array, int left, int right) {int tmp = array[left];int index = left;while (left < right) {//如果左边的值小于基准值while (left < right && array[left] < tmp ) {left++;}//如果右边的值大于基准值while (left < right && array[right] > tmp) {right--;}//此时我们的找到了左边大于基准值的位置,右边小于基准值的位置,我们进行交换swap(array,left,right);}//把基准值放在l = r的位置swap(array,left,index);return left;}
7. 归并排序(分治思想)
递归
特点:
时间复杂度: O(N*log2^N)
空间复杂度: O(n)
稳定性:稳定
主要思想:
先分解再合并(二路归并)
1. 分成一个个子序列,让子序列有序.
2. 然后再合并成,合并后任然保证有序.
具体代码:
public static void mergeSort(int[] array) {mergeFunc(array,0,array.length - 1);}//用来进行分割private static void mergeFunc(int[] array, int start, int end) {//越界就返回if(start >= end) {//不加=会数组越界return;}//找到中间元素int mid = (end + start) / 2;//分割左边mergeFunc(array,start,mid);//分割右边mergeFunc(array,mid + 1,end);//分割到头了,就进行合并merge(array,start,mid,end);}private static void merge(int[] array, int left,int mid, int right) {int s1 = left;int e1 = mid;int s2 = mid+1;int e2 = right;int i = 0;//新数组的下标//创建一个新的数组int[] arryTemp = new int[right - left + 1];//俩端都有元素的时候while (s1 <= e1 && s2 <= e2) {//进行比较if(array[s1] <= array[s2]) {arryTemp[i++] = array[s1++];}else {arryTemp[i++] = array[s2++];}}//此时只有一端有元素,就直接放进数组即可while (s1 <= e1) {arryTemp[i++] = array[s1++];}while (s2 <= e2) {arryTemp[i++] = array[s2++];}//我们要把元素放进原来的数组里面for (int j = 0; j < arryTemp.length; j++) {array[j + left] = arryTemp[j];}}
非递归:
思想:
用gap来确定每个组多少个元素,先一个一个有序,然后俩个俩个有序....
1. gap表示每组有多少个元素
2. 根据gap确定左右半区的边界和中间位置
3. 合并左右半区的元素
具体代码:
private static void merge(int[] array, int left,int mid, int right) {int s1 = left;int e1 = mid;int s2 = mid+1;int e2 = right;int i = 0;//新数组的下标//创建一个新的数组int[] arryTemp = new int[right - left + 1];//俩端都有元素的时候while (s1 <= e1 && s2 <= e2) {//进行比较if(array[s1] <= array[s2]) {arryTemp[i++] = array[s1++];}else {arryTemp[i++] = array[s2++];}}//此时只有一端有元素,就直接放进数组即可while (s1 <= e1) {arryTemp[i++] = array[s1++];}while (s2 <= e2) {arryTemp[i++] = array[s2++];}//我们要把元素放进原来的数组里面for (int j = 0; j < arryTemp.length; j++) {array[j + left] = arryTemp[j];}}//非递归private static void mergeSortNor(int[] array) {//每组多少个数据int gap = 1;while (gap <= array.length) {for (int i = 0; i < array.length; i = i + 2 * gap) {//i每一次循环都在gap个元素的分组下进行排序//确定左右分组的边界值int left = i;int mid = left + gap - 1;int right = mid + gap;//防止越界操作,比如left是数组的最后一个元素,我们Mid和right就越界了if(mid >= array.length) {mid = array.length - 1;}if(right >= array.length) {right = array.length - 1;}//合并左右半区的元素merge(array,left,mid,right);}//增大每组的元素gap *=2;}}
外部排序:
当数据量很大的时候我们需要在磁盘上进行操作.
比如: 内存只有 1 G,需要排序的数据有100G
在内存中放不下这些数据,因此需要外部排序,我们常常用归并排序来进行外部排序
1. 先把文件切分成 200 份,每个 512 M(切割到每份可以被内存放下)
2. 分别对 512 M 排序,因为内存已经可以放的下,所以任意排序方式都可以
3. 进行 2路归并,同时对 200 份有序文件做归并过程,最终结果就有序了
各种基于比较的排序算法的使用场景:
时间和空间复杂度总结:
排序方法 | 最好 | 平均 | 最坏 | 空间复杂度 | 稳定性 |
冒泡排序 | O(n) | O(n^2) | O(n^2) | O(1) | 稳定 |
插入排序 | O(n) | O(n^2) | O(n^2) | O(1) | 稳定 |
选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 不稳定 |
希尔排序 | O(n) | O(n^0.13) | O(n^0.15) | O(1) | 不稳定 |
堆排序 | O(n*log(n)) | O(n*log(n)) | O(n*log(n)) | O(1) | 不稳定 |
快速排序 | O(n*log(n)) | O(n*log(n)) | O(n^2) | O(logn) ~O(n) | 不稳定 |
归并排序 | O(n*log(n)) | O(n*log(n)) | O(n*log(n)) | O(n) | 稳定 |
非基于比较的排序:(量力而行)
1. 计数排序
特点:
时间复杂度:O(max(N,范围))
空间复杂度:O(范围)
稳定性:稳定的
基本思想:
当数据是0-9之间的时候,我们申请一个数组,然后遍历数据,假设我们第一个元素是1,我们就在数组1下标把值+1;
1. 申请一个数组 当前是10
2. 遍历原来的数组,把数字对象的count数组的下标内容进行++
3. 遍历计数数组count 写回原来数组array,此时需要注意写的次数要和元素值一样,最后数组array当中就会存储有序的序列
当数据是90-99之间的时候
len = maxVal - minVal + 1
count[array[i]-minVal]++
具体代码:
https://zhuanlan.zhihu.com/p/26595385?group_id=842495057868226560
public static void countSort(int[] array) {//求最大最小值O(n)int minVal = array[0];int maxVal = array[0];for (int i = 1; i < array.length; i++) {if (array[i] < minVal) {minVal = array[i];}if(array[i] > maxVal) {maxVal = array[i];}}//确定计数数组的长度int len = maxVal - minVal + 1;int[] count = new int[len];//遍历array数组 把数据出现的次数存储到计数数组当中0(n)for (int i = 0; i < array.length; i++) {count[array[i]-minVal]++;}//计数数组已经存放了每个数据出现的次数//遍历计数数组 把实际的数据写回array数组int index = 0;for (int i = 0; i < count.length; i++) {//O(范围)while (count[i] > 0) {array[index] = i + minVal;index++;//写回一次count[i]--;}}}
2. 基数排序
主要思想:
1.以个十百位一次依次放入count数组(0-9]
2. 然后依次从0-9对count数组进行底层元素的取出(队列,或者链表(尾插头删))
具体代码
1.10 基数排序 | 菜鸟教程
3. 桶排序
主要思想:
1. 每个桶放不同区间的数
2. 把数据放在桶里面,对桶进行排序
具体代码:
https://blog.csdn.net/qq_27124771/article/details/87651495
相关文章:
各种排序算法
前置知识 排序: 按照递增或者递减的顺序把数据排列好 稳定性: 值相等的元素在排序之后前后顺序是否发生了改变 内部排序: 数据放在内存上 外部排序: 数据放在磁盘上 内部排序 基于比较的排序 几大排序算法 1. 堆排序 特点: 思想: 1. 创建大根堆,把所有元素放在大根堆里…...
前端-Git
一.基本概念 Git版本控制系统时一个分布式系统,是用来保存工程源代码历史状态的命令行工具 简单来说Git的作用就是版本管理工具。 Git的应用场景:多人开发管理代码;异地开发,版本管理,版本回滚。 Git 的三个区域&a…...
用nextjs开发时遇到的问题
这几天已经基本把node后端的接口全部写完了,在前端开发时考虑时博客视频类型,考虑了ssr,于是选用了nextJs,用的是nextUi,tailwincss,目前碰到两个比较难受的事情。 1.nextUI个别组件无法在服务器段渲染 目前简单的解决方法&…...
Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64
yum install 报错: Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64 CentOS7的SCL源在2024年6月30日停止维护了。 当scl源里面默认使用了centos官方的地址,无法连接,需要替换为阿里云。 cd /etc/yum.repos.d/ 找到 CentOS-SCLo-scl.repo 和…...
HCIA笔记3--TCP-UDP-交换机工作原理
1. tcp协议 可靠的连接 1.1 报文格式 1.2 三次握手 1.3 四次挥手 为什么TIME_WAIT需要2MSL的等待时间? (a) 为了实现可靠的关闭 (b)为了让过期的报文在网络上消失 对于(a), 假设host发给server的last ack丢了。 ser…...
RabbitMQ原理架构解析:消息传递的核心机制
文章目录 一、RabbitMQ简介1.1、概述1.2、特性 二、RabbitMQ原理架构三、RabbitMQ应用场景3.1、简单模式3.2、工作模式3.3、发布订阅3.4、路由模式3.5 主题订阅模式 四、同类中间件对比五、RabbitMQ部署5.1、单机部署5.2、集群部署(镜像模式)5.3、K8s部署…...
C语言指针作业
//8-29 第八章作业 //3.输入10个整数,将其中最小的数第一个数对换,把最大的数与最后一个数对换 //写3个函数:①输人10个数;②进行处理;③输出10个数。 //①输人10个数, //方法一:数组索引 void main() {int arr[10];int *p arr;//printf("请输入…...
区块链:比特币-Binance
写在前面:相对于Tran和BNB而言,Binance不支持智能合约;大约每 10分钟 生成一个新区块 一、认识Binance 官方网站:Blockchain Explorer - Bitcoin Tracker & More | Blockchain.com 官方文档:Authentication – I…...
数据工程流程
** 数据工程流程图** #mermaid-svg-ArT55xCISSfZImy3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ArT55xCISSfZImy3 .error-icon{fill:#552222;}#mermaid-svg-ArT55xCISSfZImy3 .error-text{fill:#552222;stroke…...
使用Python和Pybind11调用C++程序(CMake编译)
目录 一、前言二、安装 pybind11三、编写C示例代码四、结合Pybind11和CMake编译C工程五、Python调用动态库六、参考 一、前言 跨语言调用能对不同计算机语言进行互补,本博客主要介绍如何实现Python调用C语言编写的函数。 实验环境: Linux gnuPython3.10…...
基于springboot的县市级土地使用监控系统的设计与实现
文末获取本系统(程序源码数据库调试部署开发环境)文末可获取,系统界面在最后面。 摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的…...
Hot100 - 最大子数组和
Hot100 - 最大子数组和 最佳思路:动态规划 时间复杂度:O(n) 代码: class Solution {public int maxSubArray(int[] nums) {int sum 0;int ans Integer.MIN_VALUE;for (int i 0; i < nums.length; i) {// 如果 sum > 0,…...
Matlab 深度学习 PINN测试与学习
PINN 与传统神经网络的区别 与传统神经网络的不同之处在于,PINN 能够以微分方程形式纳入有关问题的先验专业知识。这些附加信息使 PINN 能够在给定的测量数据之外作出更准确的预测。此外,额外的物理知识还能在存在含噪测量数据的情况下对预测解进行正则…...
[STM32]从零开始的STM32 FreeRTOS移植教程
一、前言 如果能看到这个教程的话,说明大家已经学习嵌入式有一段时间了。还记得嵌入式在大多数时候指的是什么吗?是的,我们所说的学习嵌入式大部分时候都是在学习嵌入式操作系统。从简单的一些任务状态机再到复杂一些的RTOS,再到最…...
软件团队的共担责任
问责制被认为是个人与其社会系统之间的纽带,它创造了一种将个人与其行为和绩效联系起来的身份关系。在入门系列的第一篇文章《超越工具和流程:成功软件开发团队的策略》中,我们介绍了问责制的概念,并提出了以下定义: …...
代码美学:MATLAB制作渐变色
输入颜色个数n,颜色类型: n 2; % 输入颜色个数 colors {[1, 0, 0], [0, 0, 1]}; createGradientHeatmap(n, colors); 调用函数: function createGradientHeatmap(n, colors)% 输入检查if length(colors) ~ nerror(输入的颜色数量与n不一…...
Perforce SAST专家详解:自动驾驶汽车的安全与技术挑战,Klocwork、Helix QAC等静态代码分析成必备合规性工具
自动驾驶汽车安全吗?现代汽车的软件包含1亿多行代码,支持许多不同的功能,如巡航控制、速度辅助和泊车摄像头。而且,这些嵌入式系统中的代码只会越来越复杂。 随着未来汽车的互联程度越来越高,这一趋势还将继续。汽车越…...
大模型中常见的微调方法有哪些?
我整理了1000道算法面试题: 获取 这里说的微调主要是指参数微调,参数微调的方法主要有以下几种: - Adapter 在预训练模型每一层(或某些层)中添加Adapter模块(如上图左侧结构所示),微调时冻结预训练模型主体,由Ada…...
MATLAB支持的距离度量
距离度量是用于量化两个点或样本之间差异的一种方法。在不同的领域和应用场景中,距离度量的选择可能会有所不同。 欧几里得距离(Euclidean Distance):这是最直观的距离定义,适用于n维空间中的两点。对于二维空间中的点…...
c++编程玩转物联网:使用芯片控制8个LED实现流水灯技术分享
在嵌入式系统中,有限的GPIO引脚往往限制了硬件扩展能力。74HC595N芯片是一种常用的移位寄存器,通过串行输入和并行输出扩展GPIO数量。本项目利用树莓派Pico开发板与74HC595N芯片,驱动8个LED实现流水灯效果。本文详细解析项目硬件连接、代码实…...
LSA详情与特殊区域
LSA是构成LSDB的重要原材料,在OSPF中发挥很大作用。 报文 通用头部 LS age:LSA寿命,0-3600s Options:可选项 LS type:LSA类型,三要素之一 Link State ID:LSAID 三要素之一 Advertising Ro…...
Leecode刷题C语言之交替组①
执行结果:通过 执行用时和内存消耗如下: 代码如下: int numberOfAlternatingGroups(int* colors, int colorsSize) {int res 0;for (size_t i 0; i < colorsSize; i) {if (colors[i] ! colors[(i - 1 colorsSize) % colorsSize] && col…...
深入解析 Django 中数据删除的最佳实践:以动态管理镜像版本为例
文章目录 引言场景与模型设计场景描述 删除操作详解1. 删除单个 Tag2. 批量删除 Tags3. 删除前确认4. 日志记录 高阶优化与问题分析1. 外键约束与误删保护2. 并发删除的冲突处理3. 使用软删除 结合 Django Admin 的实现总结与实践思考 引言 在现代应用开发中,服务和…...
4457数字示波器 2Gpts的深度存储
4457数字示波器 2Gpts的深度存储 256级灰度等级及四种波形色彩显示 4457M系列数字示波器,带宽从1GHz到4GHz,采样率10GSa/s、20GSa/s,垂直分辨率12bit,存储深度1Gpts,最快波形捕获率70万个波形/秒,独创的…...
【笔记】轻型民用无人驾驶航空器安全操控
《轻型民用无人驾驶航空器安全操控》 理论考试培训材料 法规部分 【民用无人驾驶航空器的分类】 1、如何定义微型、轻型无人驾驶航空器? 微型无人驾驶航空器,是指空机重量小于0.25千克,最大平飞速度不超过40千米/小时,无线电发…...
【leetcode】动态规划
31. 873. 最长的斐波那契子序列的长度 题目: 如果序列 X_1, X_2, ..., X_n 满足下列条件,就说它是 斐波那契式 的: n > 3对于所有 i 2 < n,都有 X_i X_{i1} X_{i2} 给定一个严格递增的正整数数组形成序列 arr ࿰…...
嵌入式linux系统中图像处理基本方法
目录 2.1 BMP图像处理 2.1.1 BMP文件格式解析 2.1.2 代码实现:将BMP文件解析为RGB格式,在LCD上显示 2.2 JPEG图像处理 2.2.1 JPEG文件格式和libjpeg编译 2.2.2 libjpeg接口函数的解析和使用 2.2.3 使用libjpeg把JPEG文件解析为RGB格式,在LCD上显示 …...
Qt SQL模块概述
Qt SQL支持的数据库 要在项目中使用 Qt SQL 模块,需要在项目配置文件中添加下面一条设置语句: Qt sql在头文件或源文件中使用 Qt SQL 模块中的类,可以使用包含语句: #include <QtSql>这样会将某个 Qt SQL 模块中的所有类…...
PVE相关名词通俗表述方式———多处细节实验(方便理解)
PVE设置初期,对CIDR、 网关、 LinuxBridge、VLAN等很有困惑的朋友一定很需要一篇能够全面通俗易懂的方式去理解PVE 中Linux网桥的工作方式,就像操作一个英雄,多个技能,还是需要一点点去学习理解的,如果你上来就对着别人…...
C语言实现冒泡排序:从基础到优化全解析
一、什么是冒泡排序? 冒泡排序(Bubble Sort)是一种经典的排序算法,其工作原理非常直观:通过多次比较和交换相邻元素,将较大的元素“冒泡”到数组的末尾。经过多轮迭代,整个数组会变得有序。 二…...
ReentrantLock(可重入锁) Semaphore(信号量) CountDownLatch
目录 ReentrantLock(可重入锁) &Semaphore(信号量)&CountDownLatchReentrantLock(可重入锁)既然有了synchronized,为啥还要有ReentrantLock?Semaphore(信号量)如何确保线程安全呢?CountDownLatch ReentrantLock(可重入锁) &Semaphore(信号量…...
Zookeeper选举算法与提案处理概览
共识算法(Consensus Algorithm) 共识算法即在分布式系统中节点达成共识的算法,提高系统在分布式环境下的容错性。 依据系统对故障组件的容错能力可分为: 崩溃容错协议(Crash Fault Tolerant, CFT) : 无恶意行为,如进程崩溃,只要…...
Jmeter中的断言
7)断言 1--响应断言 功能特点 数据验证:验证响应数据是否包含或不包含特定的字符串、模式或值。多种匹配类型:支持多种匹配类型,如文本、正则表达式、文档等。灵活配置:可以设置多个断言条件,满足复杂的测…...
【通俗理解】隐变量的变分分布探索——从公式到应用
【通俗理解】隐变量的变分分布探索——从公式到应用 关键词提炼 #隐变量 #变分分布 #概率模型 #公式推导 #期望最大化 #机器学习 #变分贝叶斯 #隐马尔可夫模型 第一节:隐变量的变分分布的类比与核心概念【尽可能通俗】 隐变量的变分分布就像是一场“捉迷藏”游戏…...
Vivado程序固化到Flash
在上板调试FPGA时,通常使用JTAG接口下载程序到FPGA芯片中,FPGA本身是基于RAM工艺的器件,因此掉电后会丢失芯片内的程序,需要重新烧写程序。但是当程序需要投入使用时不能每一次都使用JTAG接口下载程序,一般FPGA的外围会…...
铲屎官进,2024年宠物空气净化器十大排行,看看哪款吸毛最佳?
不知道最近换毛季,铲屎官们还承受的住吗?我家猫咪每天都在表演“天女散花”,家里没有一块干净的地方,空气中也都是堆积的浮毛,幸好有宠物空气净化器这种清理好物。宠物空气净化器针对宠物浮毛设计,可以有效…...
SpringBoot 项目中使用 spring-boot-starter-amqp 依赖实现 RabbitMQ
文章目录 前言1、application.yml2、RabbitMqConfig3、MqMessage4、MqMessageItem5、DirectMode6、StateConsumer:消费者7、InfoConsumer:消费者 前言 本文是工作之余的随手记,记录在工作期间使用 RabbitMQ 的笔记。 1、application.yml 使…...
嵌入式硬件实战提升篇(二)PCB高速板设计 FPGA核心板带DDR3 PCB设计DDR全面解析
引言:设计一款高速板,供读者学习,FPGA核心板,带一颗DDR3内存,FPGA型号:XC6SLX16-2FTG256C。 随着嵌入式硬件技术的快速发展,高速板设计逐渐成为嵌入式系统设计中的核心技术之一。高速板的设计要…...
2044:【例5.12】回文字串
【题目描述】 输入一串字符,字符个数不超过100,且以“.”结束。 判断它们是否构成回文。 【输入】 一行字符串。 【输出】 是否为回文串。是输出“Yes”,否输出“No。” 【输入样例】 abccb 【输出样例】 No 代码实现 #include <stdio.h> /*2044&#x…...
Sui 链游戏开发实战:用 Move 写一个链上剪刀石头布游戏!
系列文章目录 Task1:hello move🚪 Task2:move coin🚪 Task3:move nft🚪 Task4:move game🚪 更多精彩内容,敬请期待!✌️ 文章目录 系列文章目录前言什么是 …...
Prometheus告警带图完美解决方案
需求背景 告警分析处理流程 通常我们收到 Prometheus 告警事件通知后,往往都需要登录 Alertmanager 页面查看当前激活的告警,如果需要分析告警历史数据信息,还需要登录 Prometheus 页面的在 Alerts 中查询告警 promQL 表达式,然…...
深度学习模型:循环神经网络(RNN)
一、引言 在深度学习的浩瀚海洋里,循环神经网络(RNN)宛如一颗独特的明珠,专门用于剖析序列数据,如文本、语音、时间序列等。无论是预测股票走势,还是理解自然语言,RNN 都发挥着举足轻重的作用。…...
分布式在线评测系统
OnlineJudge 前言所用技术开发环境 1. 需求分析2. 项目宏观结构3. compile_server服务设计3.1 compiler服务设计3.2 runner服务设计3.3 compile_run3.4 compile_server.cpp 4. oj_server服务设计4.1 model设计4.2 view设计4.3 control设计4.3.1 获取题目列表功能4.3.2 获取单个…...
Unity中动态生成贴图并保存成png图片实现
实现原理: 要生成长x宽y的贴图,就是生成x*y个像素填充到贴图中,如下图: 如果要改变局部颜色,就是从x1到x2(x1<x2),y1到y2(y1<y2)这个范围做处理, 或者要想做圆形就是计算距某个点(x1,y1&…...
鸿蒙多线程开发——sendable共享容器
1、异步锁机制 在介绍共享容器之前,先介绍异步锁机制。 为了解决多线程并发任务间的数据竞争问题,ArkTS引入了异步锁能力。异步锁可能会被类对象持有,因此为了更方便地在并发实例间获取同一个异步锁对象,AsyncLock对象支持跨线程…...
五天SpringCloud计划——DAY1之mybatis-plus的使用
一、引言 咱也不知道为啥SpringCloud课程会先教mybatis-plus的使用,但是教都教了,就学了吧,学完之后觉得mybatis-plus中的一些方法还是很好用了,本文作为我学习mybatis-plus的总结提升,希望大家看完之后也可以熟悉myba…...
Vue.js基础——贼简单易懂!!(响应式 ref 和 reactive、v-on、v-show 和 v-if、v-for、v-bind)
Vue.js是一个渐进式JavaScript框架,用于构建用户界面。它专门设计用于Web应用程序,并专注于视图层。Vue允许开发人员创建可重用的组件,并轻松管理状态和数据绑定。它还提供了一个虚拟DOM系统,用于高效地渲染和重新渲染组件。Vue以…...
警钟长鸣,防微杜渐,遨游防爆手机如何护航安全生产?
近年来,携非防爆手机进入危险作业区引发爆炸的新闻屡见报端。2019年山西某化工公司火灾,2018年延安某煤业瓦斯爆炸,均因工人未用防爆手机产生静电打火引发。涉爆行业领域企业量大面广,相当一部分企业作业场所人员密集,…...
中国科学院大学研究生学术英语读写教程 Unit7 Materials Science TextA 原文和翻译
中国科学院大学研究生学术英语读写教程 Unit7 Materials Science TextA 原文和翻译 Why Is the Story of Materials Really the Story of Civilisation? 为什么材料的故事实际上就是文明的故事? Mark Miodownik 1 Everything is made of something. Take away co…...
win10中使用ffmpeg和MediaMTX 推流rtsp视频
在win10上测试下ffmpeg推流rtsp视频,需要同时用到流媒体服务器MediaMTX 。ffmpeg推流到流媒体服务器MediaMTX ,其他客户端从流媒体服务器拉流。 步骤如下: 1 下载MediaMTX github: Release v1.9.3 bluenviron/mediamtx GitHub…...