数据结构-排序
目录
一、冒泡排序
二、选择排序
三、插入排序
四、希尔排序
五、堆排
六、快速排序
1、hoare:
2、挖坑法:
3、前后指针法:
4、快排非递归
七、归并排序
1、递归写法:
2、非递归写法:
八、计数排序
九、排序的时间复杂度和空间复杂度以及稳定性
1、稳定性:
一、冒泡排序
###思想:
有几个数据就进行几次排序,每一次比较两个挨着的数据大小,把大的往后放;每一次排序走完,下一次就不需要再排这个数据,也就是说已经放在后面的数据不需要排,并且每次排序比较的次数是一个等差数列;
###图像:
###代码:
//冒泡排序
void BubbleSort(int* arr, int size)
{for (int i = 0; i < size; i++){int flag = 0;for (int j = 0; j < size - i - 1; j++){if (arr[j] > arr[j + 1]){swap(arr[j], arr[j + 1]);flag = 1;}}if (flag == 0){break;}}
}
###时间复杂度:O(N^2);flag优化,当进行一趟没有交换时,说明已经有序,无需再排,此时直接退出优化效率
二、选择排序
###思想:遍历数据,选出最大最小的数分别放在首位;
###代码:
//选择排序
void SelectSort(int* arr, int left,int right)
{int begin = 0, end = right - 1;while (begin < end){int maxi = begin;int mini = begin;for (int i = begin+1; i <= end; i++){if (arr[maxi] < arr[i]){maxi = i;}if (arr[mini] > arr[i]){mini = i;}}swap(arr[mini], arr[begin]);if (maxi == begin){maxi = mini;}swap(arr[maxi], arr[end]);begin++;end--;}
}
###时间复杂度为O(N^2),是所有排序中最差的,冒泡排序至少还有优化。
三、插入排序
###思想:
每次默认前面一段有序,从紧挨着这一段有序数据的下一个数据开始往前比较,若是比前面的小,就让前面的移到后面一个的位置,直至找到比这个数据小的数就不再移动,将这个数据插入到这里
###图像:
###代码:
//插入排序
void InsertSort(int* arr, int size)
{for (int i = 0; i < size - 1; i++){int end = i;int tmp = arr[end + 1];while (end >= 0){if (arr[end] > tmp){arr[end + 1] = arr[end];}else{break;}end--;}arr[end + 1] = tmp;}
}
跳出循环的条件有两个:一是找到比tmp小的数了,此时break,让tmp插到end+1的位置,因为end的位置的数据恰好是比tmp小的;二是end小于0了,此时说明tmp前面没有比它小的值,0位置的数据也被移到后面一位的位置上了,那么就要把tmp放在0的位置,也就是end+1。那么这两种情况这种写法都兼容;
若是在循环里面插入tmp,那么当end小于零时,还要跳出循环之后再判断end是不是大于零再插入;
###时间复杂度:O(N^2);但是比冒泡和选择都好一点。插入排序每次的end都在增加,也就是每次循环的次数在减少,内层循环是一个等差数列;虽然冒泡也是,但是插入排序一旦找到比tmp小的就会跳出,此轮循环结束;冒泡排序虽然有优化,但是在大量数据面前做到提前有序的几率很小,至少小于插入排序每轮提前找到比tmp小的数据的几率(因为只有当数据是逆序时,插入排序才会每趟循环都走完,而此种情况出现的几率极小)
总之就是:插入排序和冒泡排序虽然都是相同量级的时间复杂度,但是极大几率插入排序优于冒泡排序。
四、希尔排序
###思路:
希尔排序可以说是插入排序的优化;从第一个数据开始,和它每间隔gap个位置的数据进行插入排序;这样的排序被称为一次预排序,gap是几那么就要进行几次预排序,因为gap之间的数据并有被分在同一次预排序里面,这就说明要分多次预排序,这个多次就是gap次;
进行完一次预排序,大的数据会渐渐跑到后面,小的数据渐渐跑到前面,那么数据就是更接近有序的;gap是要慢慢减小的,最后为1,进行插入排序,因为进行了预排序,那么最后进行插入排序时就会很快;这样就达到了优化的效果;
###代码:
//希尔排序
void ShellSort(int* arr, int size)
{int gap = size;while (gap > 1){gap = gap / 3 + 1;//保证最后一次是1for (int i = 0; i < size - gap; i++){int end = i;int tmp = arr[end + gap];while (end >= 0){if (arr[end] > tmp){arr[end + gap] = arr[end];}else{break;}end-=gap;}arr[end + gap] = tmp;}}
}
按照每次/3减小是最合理的;for循环i每次加一,代表一次for循环包含当前gap下的所有的预排序;
###时间复杂度:O(N^1.3)
五、堆排
//向下调整
void AdjustDown(int* arr, int parent, int size)
{int child = parent * 2 + 1;while (child < size){if (child + 1 < size && arr[child] < arr[child + 1]){child++;}if (arr[parent] < arr[child]){swap(arr[child], arr[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
//堆排
void HeapSort(int* arr, int size)
{//建堆for (int i = (size - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr, i, size);}//O(N)//开始排序for (int i = size - 1 ; i >= 0; i--){swap(arr[0], arr[i]);AdjustDown(arr, 0, i - 1);}//O(N*logN)
}
###时间复杂度是O(N*lonN)
六、快速排序
1、hoare:
###思路:
选取一个基准值,这里选取最左边的值;从前后分别遍历数据;先从后面走起,碰见比基准值小的就停止;前面的begin碰到比基准值大的就停止;两者都停了就交换,把大的换到后面,小的换到前面;最后end和begin相遇,相遇的位置一定是比基准值小的值,跳出循环,交换基准值和begin位置的值;那么keyi之前的值就都是比它小的,后面就都是比它大的;利用keyi的位置将数据分割成两部分,利用递归,这两部分再次进行相同的操作;(似于二叉树结构)
为什么begin和end相遇的位置的值一定小于等于基准值的?因为是让end先走的,end是要找小于基准值的位置,这里分析begin和end相遇的几种情况:情况一,end找不到比基准值小的,那么最后相遇的位置就是基准值的位置,跳出循环,自己和自己交换,递归右边的部分;情况二:begin和end已经交换过了但还没相遇,end走,找不到小于基准值的值,最后和begin相遇,而begin的值是上一次和end交换的,一定是小于基准值的值;情况三:end找到了比基准值小的,停止,begin开始找比基准值大的,找不到,最后和end相遇,而end处的值就是小于基准值的,跳出交换;所以让end先走,先找小就能保证相遇的位置一定是比基准值小的。
###代码:
void QuickSort1(int* arr, int left, int right)
{int keyi = left;int begin = left;int end = right;while (begin < end){while (begin < end && arr[end] >= arr[keyi]){end--;}//先走右边保证最后交换的位置比arr[keyi]小while (begin < end && arr[begin] <= arr[keyi]){begin++;}swap(arr[begin], arr[end]);}swap(arr[keyi], arr[begin]);keyi = begin;QuickSort1(arr, left, keyi - 1);QuickSort1(arr, keyi + 1, right);
}
###时间复杂度:O(N*logN);分析:每一次遍历完就是N,begin和end相遇,那么两者共同走完了整段数据;而这个递归是类似于二叉结构的,就是logN;
但是还有优化的空间:
1、当某一段数据很少时,使用递归反而不好,此时用插入排序处理(杀鸡焉用牛刀,很少的数据不需要用堆排、希尔,但是要从一般效率的排序中选一个最好的就是插入排序),这样就有优化效果;
2、当数据是接近有序时,每一次分割之后,前面的没有数据,后面数据量是开始的数据-1;也就是keyi最后每次都是在开始的位置,那么就达不到 logN的效果,此时高度是N,因为每一次都是减少一个,而不是像一般情况小类似于每次折半;所以最后的时间复杂度是O(N^2);此时效率太低了;为了解决,这里使用三数取中,就是每次进行单趟排序时,先取一个值放在left的位置 ,这个数是left处、right处、以及两者中间处数据中中间大小的那个值;这样一来keyi处的值就不会是最小的,那么排序一次之后keyi也不会是在最开头,那么又变成了类似二叉结构的情况;达到了优化的效果。
###代码:
//快排三数取中
int GetMid(int* arr, int left, int right)
{int midi = (right + left) / 2;if (arr[left] > arr[midi]){if (arr[midi] > arr[right]){return midi;}else if (arr[left] > arr[right]){return right;}else{return left;}}else//arr[left]<=arr[midi]{if (arr[right] > arr[midi]){return midi;}else if (arr[left] > arr[right]){return left;}else{return right;}}
}
//快排
//hoare
void QuickSort1(int* arr, int left, int right)
{if (right - left + 1 <= 10)//小区间优化{InsertSort(arr, right - left + 1);return;}//三数取中if (left >= right){return;}int midi = GetMid(arr, left, right);swap(arr[midi], arr[left]);int keyi = left;int begin = left;int end = right;while (begin < end){while (begin < end && arr[end] >= arr[keyi]){end--;}//先走右边保证最后交换的位置比arr[keyi]小while (begin < end && arr[begin] <= arr[keyi]){begin++;}swap(arr[begin], arr[end]);}swap(arr[keyi], arr[begin]);keyi = begin;QuickSort1(arr, left, keyi - 1);QuickSort1(arr, keyi + 1, right);
}
2、挖坑法:
###思路:
相同地,取一个基准值,这个基准值处就是挖了一个坑;这里取最左边地的数据,那么从后面开始找,找到比基准值小的就把这个值放在坑的位置,那么这个比基准值小的数据的位置又形成了一个坑,从前面开始找找到比基准值大的值就把这个值放在上次的坑处,最后end和begin相遇,相遇得到位置也是一个坑,最后把基准值放在这个坑处;这样,也能达到排序效果;这个方法的优点在于它很自然,在前面挖了坑,就从后面找,后面挖了坑就从前面找;
3、前后指针法:
###思路:
利用两个指针,第一个指针prev指向开始的位置,第二个指针cur指向prev的下一个位置;基准值还是取最左边的,cur找到比基准值小的就让prev加加,然后cur和prev处的值进行交换,最后cur走到空,跳出循环,交换keyi处的值和prev处的值,prev处的一定是小于基准值的;这样也能把大的值放到后面,小的放在前面;最后进行分割递归;
###代码:
//前后指针法
void QuickSort2(int* arr, int left, int right)
{if (right - left + 1 <= 10){InsertSort(arr, right - left + 1);return;}if(left >= right){return;}int midi = GetMid(arr, left, right);swap(arr[midi], arr[left]);int prev = left;int cur = prev + 1;int keyi = left;while (cur <= right){if (arr[cur] < arr[keyi] ){prev++;swap(arr[cur], arr[prev]);}cur++;}swap(arr[keyi], arr[prev]);keyi = prev;QuickSort2(arr, left, keyi - 1);QuickSort2(arr, keyi + 1, right);
}
4、快排非递归
###原因:
递归深度太深不好,函数栈帧在栈区,而给非递归使用数据结构的栈在堆,堆区远大于栈区;
###思路:
将递归转到非递归使用数据结构栈;将每次一单趟排序的区间前后界限值放进栈,先放后面的界限;每一次排序之后进行分割,再放分割之后的界限值;当界限之间的数据小于两个时不需要进栈;最后达到有序;
//非递归快排实现
int quick(int* arr, int left, int right)//单趟
{int prev = left;int cur = prev + 1;int keyi = left;while (cur <= right){if (arr[cur] < arr[keyi]){prev++;swap(arr[prev], arr[cur]);}cur++;}swap(arr[prev], arr[keyi]);return prev;
}
void QuickSort3(int* arr, int size)
{stack<int> st;st.push(size-1);st.push(0);while (!st.empty()){int left = st.top();st.pop();int right = st.top();st.pop();int keyi = quick(arr, left, right);//分割if (keyi + 1 < right)//进入单趟排序的至少得有两个数才有意义{st.push(right);st.push(keyi + 1);}if (keyi - 1 > left){st.push(keyi - 1);st.push(left);}}
}
七、归并排序
###思路:
将数据分为两部分,这两部分是有序的,再遍历这两部分,创建一个新的数据,将小的放在新的数组里面,直到遍历完;
问题是如何保证分割的两部分是有序的:将数据继续划分直到只有一个数据,一个数据没有比较的对象那么它就是有序的,这一个数据和另一个数据进行归并,形成有序的两个数据;这样依次让1归并的每组数据量增多,最后就是整组数据被分为有序的两部分进行归并那么最后就排好序了。
1、递归写法:
这里类似于后序思想,先划分数据,直到划分到一个数据时回退开始归并;
###代码:
void _MergeSort(int* arr, int* tmp, int left, int right)
{if (left >= right){return;}int midi = (left + right) / 2;_MergeSort(arr, tmp, left, midi);_MergeSort(arr, tmp, midi + 1, right);int begin1 = left, end1 = midi;int begin2 = midi + 1, end2 = right;int i = left;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] <= arr[begin2]){tmp[i++] = arr[begin1++];}else{tmp[i++] = arr[begin2++];}}while (begin1 <= end1){tmp[i++] = arr[begin1++];}while (begin2 <= end2){tmp[i++] = arr[begin2++];}memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
}
void MergeSort(int* arr, int size)
{int* tmp = new int[size];int left = 0, right = size - 1;_MergeSort(arr, tmp,left, right);delete[] tmp;tmp = nullptr;
}
2、非递归写法:
这里不能使用栈了,因为这里有回退时使用区间的过程,若是使用栈,归并时找不到区间,除非使用两个栈,一个用于记录区间方便最后进行归并,另一个进行区间划分;
这里使用循环,利用一个gap值,gap最开始是1,代表一个数据,一个gap组有两个数据,这两个数据进行归并;gap每次都乘二,第二次每个gap组有四个数据,两两归并;依次增加gap,直到gap和数组大小相同时停止;
注意的问题:当数据个数不是2的次方个时,进行归并时可能数组会越界;此时要加判断,若是begin2越界了,那么说明此次归并的后面一半数据不需要归并了,前面的已经是有序的,后面的越界了;当end2越界时,将end2置为size-1,因为后面一半数据begin2没有越界只是end2越界了,说明后面一半数据中有的需要和前面一半数据进行归并,j将end2置为size-1,使得归并的区间合法;将begin2的判断放在end2的前面,因为当begin2越界了时,end2一定越界,此时直接break就行了。
###代码:
void MergeSortNonR(int* arr, int size)
{int gap = 1;int* tmp = new int[size];while (gap < size){for (int i = 0; i < size; i += 2 * gap){int begin1 = i, end1 = begin1 + gap - 1;int begin2 = i +gap, end2 = begin2 + gap - 1;int j = i;if (begin2 >= size){break;}if (end2 >= size){end2 = size - 1;}while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] <= arr[begin2]){tmp[j++] = arr[begin1++];}else{tmp[j++] = arr[begin2++];}}while (begin1 <= end1){tmp[j++] = arr[begin1++];}while (begin2 <= end2){tmp[j++] = arr[begin2++];}memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap *= 2;}
}
八、计数排序
###思路:
通过创建一个数组,这个数组是原数据的映射;统计相同元素出现次数,根据统计结果依次将数据放回原数组中;
###代码:
//计数排序
void CountSort(int* arr,int size)
{int max = arr[0], min = arr[0];for (int i = 1; i < size; i++){if (arr[i] <= min){min = arr[i];}if (arr[i] >= max){max = arr[i];}}int range = max - min + 1;int* count = (int*)calloc(range, sizeof(int));for (int i = 0; i < size; i++){count[arr[i] - min]++;}int j = 0;for (int i = 0; i < range; i++){while (count[i]--){arr[j++] = i + min;}}
}
九、排序的时间复杂度和空间复杂度以及稳定性
时间复杂度 | 空间复杂度 | 稳定性 | |
冒泡排序 | O(N^2) | O(1) | 稳定 |
选择排序 | O(N^2) | O(1) | 不稳定 |
插入排序 | O(N^2) | O(1) | 稳定 |
希尔排序 | O(N^1.3) | O(1) | 不稳定 |
推排序 | O(NlogN) | O(1) | 不稳定 |
快速排序 | O(NlogN) | O(logN) | 不稳定 |
归并排序 | O(NlogN) | O(N) | 稳定 |
计数排序 | O(N+range) | O(range) | 无 |
1、稳定性:
两个相同元素在排序前后的相对顺序不变:比方说两个相同的数,其中一个在另一个前面,排序完之后,这个在前面的数依旧是在前面的;符合这种情况就是稳定了,否则就不稳定;
使用场景:对于单调的整形没有意义,因为数都一样;对于包含多个属性的对象进行排序,假定一个属性已经排好了,排其他属性时这个排号的属性不受影响;
分析这八个排序:
- 对于冒泡排序,若前一个比后一个大就交换,当两个数相同时,不交换,也就是说排序前后的相同元素的相对顺序不变;
- 对于选择排序,假设开始的位置的数据和中间有的数据相同,当找到最小和开始的交换时,可能会改变相同数据的相对顺序;比如6 ,2,6,6,1,9;循环一次,开始的6成了最后的6;
- 插入排序,假定前面的有序,当一个元素和前面的比较,遇到相同元素时插入到这个相同元素的后面,未改变相对位置;
- 希尔排序预排序可能会改变相同元素的相对位置;
- 堆排序,举个极端例子:假设数据全部相同,那么排序一次,开始位置的数据就放到最后了;
- 快排,swap keyi位置和后面的begin位置时可能会改变顺序;时间复杂度是因为开辟栈帧,每层开辟一个;
- 归并:两个相同数据,前面的小于或者等于先放入新数组;
- 计数排序:时间复杂度看最后放数据的循环,外层是range,遍历完range,内层是每个range上不为0的,内层总共走size次,那么就是range+size;计数排序只针对单调的数据,所以不涉及到稳定性。
相关文章:
数据结构-排序
目录 一、冒泡排序 二、选择排序 三、插入排序 四、希尔排序 五、堆排 六、快速排序 1、hoare: 2、挖坑法: 3、前后指针法: 4、快排非递归 七、归并排序 1、递归写法: 2、非递归写法: 八、计数排序 九、排…...
神经网络中常见的激活函数Sigmoid、Tanh和ReLU
激活函数在神经网络中起着至关重要的作用,它们决定了神经元的输出是否应该被激活以及如何非线性地转换输入信号。不同的激活函数适用于不同的场景,选择合适的激活函数可以显著影响模型的性能和训练效率。以下是三种常见的激活函数:Sigmoid、T…...
[报错] Error: PostCSS plugin autoprefixer requires PostCSS 8 问题解决办法
报错:Error: PostCSS plugin autoprefixer requires PostCSS 8 原因:autoprefixer版本过高 解决方案: 降低autoprefixer版本 执行:npm i postcss-loader autoprefixer8.0.0 参考: Error: PostCSS plugin autoprefix…...
多线程---创建及方法
*线程创建的方式: 1.继承Thread类,重写run方法。 2.实现Runnable接口,重写run方法。 实际这两个run方法都重写的是Runnable中的run方法 简化方法: 1.匿名内部类创建Thread 子类对象 Thread thread new Thread(){Overridepub…...
C++设计模式之单例模式
动机 在软件系统中,经常有一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性,以及良好的效率。 如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例? 这应该是类设计…...
给你一个整数n, 判断它是否是素数。注意1不是素数。:JAVA
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 给你一个整数n, 判断它是否是素数。注意1不是素数。 输入描述: 第一行输入一个整数T,表示需要判断的数的个数接下来T行每行一个整数n,表示需要判断的数。1<n<1e5,1<T<…...
Java项目实战II基于微信小程序的电子竞技信息交流平台的设计与实现(开发文档+数据库+源码)
目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着互联网技术的飞速发展…...
temu登录接口逆向分析(含Py纯算)
文章目录 1. 写在前面2. 接口分析3. 算法还原 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…...
Java ArrayList 详解
Java ArrayList 详解 ArrayList 是 Java 集合框架(Collection Framework)中最常用的类之一,是一种基于动态数组的数据结构,属于 List 接口的实现类。它允许存储重复的元素,有序,支持随机访问,且…...
CTF之密码学(仓颉编码)
一、仓颉码(用于建立中文索引) 定义与目标: 仓颉码是为了建立中文的索引观念而设计的一种编码方式。其主要目标是方便对中文资料或程式进行索引功能的处理。 工作原理: 仓颉码的索引以ASCII的字符码为基准,但在内部会转…...
OpenCV的圆形检测HoughCircles
HoughCircles 函数是 OpenCV 库中用于在灰度图像中检测圆的函数,它基于霍夫变换(Hough Transform)的一种变体——梯度霍夫变换(HOUGH_GRADIENT)函数原型如下: void HoughCircles( InputArray image, OutputArray circles,int method, double dp, double minDist,double …...
Latex 英文双栏排版时,摘要和引言之间的距离
目标:解决这个间隔 打开“cas-common.sty" 搜索“\NewDocumentCommand \dashrule" 本来是两个 m m 变成 m m m然后是增加下面这个代码,其他地方不动 \skip_vertical:n {#4} 搜索”MaketitleBox“和“LongMaketitleBox ” 本来的代码应该…...
AD学习笔记·空白工程的创建
编写不易,禁止搬运,仅供学习,感谢理解 序言 本文参考B站,凡亿教育,连接放在最后。 创建工程文件 在使用AD这个软件的电路板设计中,有很多的地方跟嘉立创eda还是有不一样的地方,其中一个地方就…...
非球面加工领域的佼佼者:倚光科技
在光学领域,非球面加工技术宛如一颗璀璨的明珠,以其独特的优势和广泛的应用,引领着光学元件制造的新潮流。 非球面透镜,其表面曲率半径从中心到边缘是变化的,这使得它在光学系统中具有诸多显著优势。首先,…...
Git分布式版本控制工具 Git基本概念、Git工作流程、Git常用命令、Git远程仓库、IDEA操作Git
目录 1.Git基本概念 1.1 概述 1.1.1 开发中的实际场景 1.1.2 版本控制器的方式 1.1.2.1 集中式版本控制工具(SVN) 1.1.2.2 分布式版本控制工具(Git) 2.概述git工作流程 3.Git常用命令 3.1 Git环境配置 3.1.1 下载与安装 3.1.2 基本配置 3.1.3 为常用指令配置别名&…...
Spring 容器管理 Bean
Bean是什么 Bean 是指 Java 中的可重用软件组件,容器会根据提供的元数据来创建和管理这些 Bean,也包括它们之间的依赖关系。Spring 容器对 Bean 并没有太多的要求,无须实现特定接口或依赖特定库,只要是最普通的 Java 对象即可,这类对象也被称为 POJO(Plain Old Java Obj…...
Spring 容器 详解
Spring 容器详解 Spring 容器 是 Spring 框架的核心组件之一,它负责创建和管理应用程序中的 Bean(对象)以及处理它们之间的依赖关系。容器通过控制反转(IoC)和依赖注入(DI)实现对象的生命周期管…...
ubuntu环境下安装electron环境,并快速打包
1.配置镜像源 关闭防火墙,命令:sudo ufw disable 1.1配置国内镜像源: vim /etc/apt/source.list deb https://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiversedeb-src https://mirrors.aliyun.com/ubuntu/ jammy main…...
Yeeco成长型一体化数智赋能平台:科技矩阵重塑企业数字生态
随着科技的飞速发展,我们正在步入一个被称为“数智化时代”的新时代。在这个时代中,数据处理和分析的能力被提升到一个前所未有的高度,而这种变化背后的重要推动力量就是各种新兴的技术趋势。 为了在激烈的市场竞争中脱颖而出,Yee…...
DP、CP、Mn是什么?有什么关系?双径节齿轮又是什么?
有一些刚刚接触齿轮的小伙伴们,经常听到和齿轮相关的是Mn这个代号,有时候拿到图纸会碰到DP和CP的图纸,今天就简单数一数他们三个的关系: 径节DP 齿轮的节距定义为两个相邻齿轮齿上两个相同点之间的距离。在理想情况下,…...
Python 中的生成器是什么?
生成器(Generator)是Python中一种特殊的迭代器,它允许你逐步生成一系列值,而不是一次性创建整个列表或集合。 这在处理大型数据集或流式数据时特别有用,因为你可以逐个处理元素,而不需要将所有元素加载到内…...
如何参加华为欧拉考试?
华为欧拉考试主要针对的是华为欧拉(EulerOS/openEuler)操作系统的认证考试,这一认证体系旨在培养和认证具备基于欧拉操作系统进行企业级应用运行基础环境搭建、管理和调测能力的工程师以及云计算架构师。以下是对华为欧拉考试的详细介绍&…...
基于STM32设计的智能家居控制系统(华为云IOT)_275
文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】设计意义【5】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发1.5 参考文献1.6 系统框架图1.7 系统原理图1.8 实物图1.9…...
2024年第七届传智杯程序设计挑战赛第一场初赛题解
文章目录 2024年第七届传智杯程序设计挑战赛初赛第一场A-吃糖果(B组、C组)B-汤姆和杰瑞(A组、C组)C-游游的重组偶数(A组、B组、C组)D-开心还是难过(B组、C组)E-小欧的平面连线(A组、B组、C组)F-小红的四子棋(A组、B组、C组)G-小红的数组操作(A组、B组)H-游游的不相邻取数(A组) …...
iOS视图控制器的生命周期及各阶段的作用
iOS视图控制器(UIViewController)的生命周期是指从它被创建到最终被销毁的过程中所经历的一系列阶段。每个阶段都有其特定的作用和执行时机,这些阶段和作用对于开发高效、稳定的iOS应用至关重要。以下是iOS视图控制器的生命周期及其各个阶段的…...
stm32上电不能启动什么原因
STM32上电不能启动可能由多种原因造成,以下是一些常见的原因及解决方法: 一、软件原因 程序错误: 程序可能存在死循环、堆栈溢出、指针指向不允许的内存空间等问题。 解决方法:使用调试工具进行调试,检查程序流程,定位并修复错误。 时钟问题: 时钟切换失败或外部时钟源…...
【后端面试总结】golang channel深入理解
在Go语言中,Channel是一种用于在goroutine之间进行通信和同步的重要机制。它提供了一种安全、类型安全的方式来传递数据,使得并发编程变得更加直观和简单。本文将详细介绍Golang中Channel的基本概念、创建与关闭、发送与接收操作,以及相关的使…...
lobeChat安装
一、安装Node.js version > v18.17.0 二、下载 cd F:\AITOOLS\LobeChat git clone https://github.com/lobehub/lobe-chat.git (下载要是失败就手动下:https://codeload.github.com/lobehub/lobe-chat/zip/refs/heads/main) npm install …...
OpenCV 简介与安装方法
大家好啊,我是董董灿。 如果你在做计算机视觉相关的工作,肯定少不了使用 OpenCV 库。 在《计算机视觉专栏》的传统计算机视觉部分,我曾经使用 OpenCV 进行了很多图像的处理,比如边缘检测。 刚好最近在整理一份文稿,…...
力扣刷题TOP101:14.BM16 删除有序链表中重复的元素-II
目录: 目的 思路 复杂度 记忆秘诀 python代码 目的 1→1→2→3→3 删除重复后变成2。 思路 这个任务是删除链表里重复的节点包含本身。可以看成是一个抽奖活动的系统升级。某人通过多种方式报名(节点不同),后台数据检测到这些…...
Hadoop生态圈框架部署 伪集群版(四)- Zookeeper单机部署
文章目录 前言一、Zookeeper单机部署(手动部署)1. 下载Zookeeper安装包到Linux2. 解压zookeeper安装包3. 配置zookeeper配置文件4. 配置Zookeeper系统环境变量5. 启动Zookeeper6. 停止Zookeeper在这里插入图片描述 注意 前言 本文将详细介绍Zookeeper的…...
【Linux】文件
声明:以下内容均学习自《Linux就该这么学》一书 1、文件权限及归属 对目录文件来说,“可读”表示能够读取目录内的文件列表;“可写”表示能够在目录内新增、删除、重命名文件;“可执行”表示能够进入该目录。 文件类型区分 -普通…...
仿真键盘输入遇到Edge环境不识别 回车符如何处理
这个问题我也是最近才遇到,可能现在大家都喜欢用新架构,基于网页来写应用管理软件。 当遇到Edge环境下,文本框不识别回车符如何处理,根据笔者经验可通过配置Edge 基于键盘管理设置来解决这个事情。如图 即在Edge浏览器环境下&…...
Python 列表操作详解
Python 列表操作详解 在 Python 中,列表(list)是一种用于存储有序集合的数据结构。列表可以包含各种类型的数据,如整数、浮点数、字符串等,甚至可以包含其他列表(这称为嵌套列表)。 示例列表 …...
Git操作学习2
1.使用git rm删除文件 查看文件夹的内容 ls -lr 删除文件rm 文件名 但是此时只删了工作区的文件,仓库还没有删 可以再使用git add更新提交给仓库 也可以直接通过git rm 删除仓库里面的文件 工作区也删除了 暂存区也删除了 最后记得提交 否则删除的文件在版本库还…...
Spring Event 监听与异步设置:深入解析与应用场景
在开发中,事件驱动编程(Event-Driven Programming)是一种常见的编程模式,Spring 提供了强大的事件机制,使得我们可以通过 EventListener 或 ApplicationListener 来监听和处理应用中的各种事件。这种机制不仅使得应用架…...
百度木木浆测试
本程序测试识别图片的文字 import cv2 from paddleocr import PaddleOCR, draw_ocr from matplotlib import pyplot as plt # 加载PaddleOCR模型,这里你可以根据需要选择语言和模型路径 ocr PaddleOCR(use_gpuFalse, langch) # 假设我们识别中文字符,…...
视频监控集中管理方案设计:Liveweb视频汇聚方案技术特点与应用
随着科技的发展,视频监控平台在各个领域的应用越来越广泛。然而,当前的视频监控平台仍存在一些问题,如视频质量不高、监控范围有限、智能化程度不够等。这些问题不仅影响了监控效果,也制约了视频监控平台的发展。 为了解决这些问…...
剑指offer(专项突破)---字符串
总目录:剑指offer(专项突破)---目录-CSDN博客 1.字符串的基本知识 C语言中: 函数名功能描述strcpy(s1, s2)将字符串s2复制到字符串s1中,包括结束符\0,要求s1有足够空间容纳s2的内容。strncpy(s1, s2, n)…...
Zygote启动流程(AndroidV)
一:背景 众所周知,Android应用及system_server基本都是由zygote fork出来的,那么zygote是如何启动的、又是如何接收fork进程的请求,接下来一步步揭秘。 二:启动流程 init进程是Android系统启动时,启动的第一…...
Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:智行无忧停车场管理系统(前后端源码 + 数据库 sql 脚本)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 项目介绍 1.1 项目功能 2.0 用户登录功能 3.0 首页界面 4.0 车辆信息管理功能 5.0 停车位管理功能 6.0 入场登记管理功能 7.0 预约管理功能 8.0 收费规则功能 9.0…...
岩体力学的材质-力学等属性的自动划分.
#背景: 在力学求解过程中,我们往往会对目标物体进行网格划分, 那么如何做到自动完成这个过程呢? 这里使用岩体力学中的地下岩层进行举例,这里只是简单的导入了4种界面, 复杂的可以一次性导入几十种界面,都可以计算(你能分多细,这个计算方式就可以帮你分层多细) 这里我只是导…...
注解 实现原理 详解
Java 注解实现原理详解 注解(Annotation)是 Java 提供的一种元数据机制,用于为代码元素(类、方法、字段、参数等)添加额外的信息。注解不会直接影响程序逻辑,但可以通过 工具(如编译器、运行时…...
第4章 陷入与系统调用
有三种类型的事件会让CPU停止正常执行的指令,强制切换到指定的代码,处理这些事件。一种是系统调用,当用户程序执行ecall指令来让内核为它做一些事。另一种是异常:一个指令(用户或内核)做了一些非法的事&…...
项目基于oshi库快速搭建一个cpu监控面板
后端: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.github.oshi</groupId><artifactId>oshi-…...
力扣C语言刷题记录 (二)移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作: 更改…...
多模态大语言模型的对比
简介 文章主要对比了包括 VideoLLaMA 2 、CogVLM2-video 、MiniCPM-V等模型 目前主流的多模态视觉问答大模型,大部分采用视觉编码器、大语言模型、图像到文本特征的投影模块 目录 简介1. VideoLLaMA 21.1 网络结构1.2 STC connector具体的架构 2. MiniCPM-V 2.62.…...
关于最近od机考中--树
题目 树按照层级遍历获取非叶子结点,然后将非叶子结点以后序遍历打印。 eg 图解 只需要将1,3,4,2进行后序遍历打印:既左-右-中方式打印 最后结果如:2,3,4,1。 思路&a…...
基数排序(代码+注释)
#include <stdio.h> #include <stdlib.h>// 获取数组中的最大值 int GetMax(int* a, int n) {int max a[0];for (int i 1; i < n; i) {if (a[i] > max) {max a[i];}}return max; }// 对数组按照某个位数进行计数排序 void CountingSortForRadix(int* a, i…...
NLP 相关知识的构成
自然语言处理(Natural Language Processing, NLP) 自然语言处理相关知识 自然语言处理(Natural Language Processing, NLP)什么是自然语言处理?自然语言处理的构成1. 基本术语1.1 分词(Segmentation&#x…...