当前位置: 首页 > news >正文

各种排序算法

前置知识

排序: 按照递增或者递减的顺序把数据排列好

稳定性: 值相等的元素在排序之后前后顺序是否发生了改变

内部排序: 数据放在内存上

外部排序: 数据放在磁盘上

内部排序

基于比较的排序

几大排序算法

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. 创建大根堆,把所有元素放在大根堆里…...

源码解读笔记:协程的 ViewModel.viewModelScope和LifecycleOwner.lifecycleScope

分析下ViewModel.viewModelScope public val ViewModel.viewModelScope: CoroutineScopeget() {val scope: CoroutineScope? this.getTag(JOB_KEY)if (scope ! null) {return scope}return setTagIfAbsent(JOB_KEY,CloseableCoroutineScope(SupervisorJob() Dispatchers.Ma…...

11.27周三F34-Day8打卡

文章目录 1. 学习让我感觉很棒。(什么关系?动作 or 描述?主语部分是?)解析答案:【解析答案分析】【对比分析】【拓展内容】2. 她忽然想起来钥匙放另一个包里了。解析答案:【拓展内容】3. 她来不来都没关系。(该由什么引导?这句话又属于什么关系,动作 or 描述?)解析答案…...

XG(S)-PON原理

前言 近年来&#xff0c;随着全球范围内接入市场的飞快发展以及全业务运营的快速开展&#xff0c;已有的PON技术标准在带宽需求、业务支撑能力以及接入节点设备和配套设备的性能提升等方面都面临新的升级需求XG(S)-PON(10G GPON)是在已有GPON技术标准上演进的增强下一代GPON技…...

C语言实例之9斐波那契数列实现

1. 斐波那契数列简介 斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列&#xff0c;因数学家莱昂纳多・斐波那契&#xff08;Leonardo Fibonacci&#xff09;以兔子繁殖为例子而引入&#xff0c;故又称为 “兔子数列”。 它的特点是从第三…...

YOLO系列论文综述(从YOLOv1到YOLOv11)【第1篇:概述物体检测算法发展史、YOLO应用领域、评价指标和NMS】

目录 1 前言2 YOLO在不同领域的应用3 物体检测指标和NMS3.1 mAP和IOU3.2 mAP计算流程3.2.1 VOC 数据集3.2.2 微软 COCO 数据集 3.3 NMS 1 前言 最近在做目标检测模型相关的优化&#xff0c;重新看了一些新的论文&#xff0c;发现了几篇写得比较好的YOLO系列论文综述&#xff0…...

数据结构--Map和Set

目录 一.二叉搜索树1.1 概念1.2 二叉搜索树的简单实现 二.Map2.1 概念2.2 Map常用方法2.3 Map使用注意点2.4 TreeMap和HashMap的区别2.5 HashMap底层知识点 三.Set3.1 概念3.2 Set常用方法3.3 Set使用注意点3.4 TreeSet与HashSet的区别 四.哈希表4.1 概念4.2 哈希冲突与避免4.3…...

计算机操作系统——进程控制(Linux)

进程控制 进程创建fork&#xff08;&#xff09;函数fork() 的基本功能fork() 的基本语法fork() 的工作原理fork() 的典型使用示例fork() 的常见问题fork() 和 exec() 结合使用总结 进程终止与$进程终止的本质进程终止的情况正常退出&#xff08;Exit&#xff09;由于信号终止非…...

【前端】ES6基础

1.开发工具 vscode地址 :https://code.visualstudio.com/download, 下载对应系统的版本windows一般都是64位的 安装可以自选目录&#xff0c;也可以使用默认目录 插件&#xff1a; 输入 Chinese&#xff0c;中文插件 安装&#xff1a; open in browser&#xff0c;直接右键文件…...

【排序算法 python实现】

排序算法 python实现 / 默写 # 汉诺塔 import copy import randomdef hanuo(n, a, b, c):if n 1:print(f{a} --> {c})returnhanuo(n - 1, a, c, b)print(f{a} --> {c})hanuo(n - 1, b, a, c)hanuo(3, A, B, C)# 冒泡排序 def bubble_sort(arr):n len(arr)for i in ran…...

Java图书管理系统(简易保姆级)

前面学习了这么多知识&#xff0c;为了巩固之前的知识&#xff0c;我们就要写一个图书管理系统来帮助大家复习&#xff0c;让大家的知识融会贯通~~~ 话不多说&#xff0c;直接开始今天的内容~ 首先呢&#xff0c;我们要有一个大体的思路&#xff1a; 实现效果思路有两种情况&a…...

嵌入式硬件设计:从概念到实现的全流程

嵌入式硬件设计是现代电子技术中一个至关重要的领域&#xff0c;涉及从硬件架构设计到硬件调试的各个方面。它为我们日常生活中的各类智能设备、家电、工业控制系统等提供了强大的支持。本文将介绍嵌入式硬件设计的基本流程、关键技术、常用工具以及常见的挑战和解决方案&#…...

第 4 章 Java 并发包中原子操作类原理剖析

原子变量操作类 AtomicLong 是原子性递增或者递减类&#xff0c;其内部使用 Unsafe 来实现&#xff0c;AtomicLong类也是在 rt.jar 包下面的&#xff0c;AtomicLong 类就是通过 BootStarp 类加载器进行加载的。这里的原子操作类都使用 CAS 非阻塞算法 private static final lon…...

从 0 到 1 掌握部署第一个 Web 应用到 Kubernetes 中

文章目录 前言构建一个 hello world web 应用项目结构项目核心文件启动项目 检查项目是否构建成功 容器化我们的应用编写 Dockerfile构建 docker 镜像推送 docker 镜像仓库 使用 labs.play-with-k8s.com 构建 Kubernetes 集群并部署应用构建 Kubernetes 集群环境编写部署文件 总…...

政安晨【零基础玩转各类开源AI项目】探索Cursor-AI Coder的应用实例

目录 Cusor的主要特点 Cusor实操 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; Cursor 是 Visual Studio Code 的一个分支。这使我们能够…...

CentOS 7 安装部署 KVM

1.关闭虚拟机 打开相关选项 打开虚拟机centos7 连接xshell 测试网络&#xff0c;现在就是没问题的&#xff0c;因为我们要使用网络源 安装 GNOME 桌面环境 安装KVM 模块 安装KVM 调试工具 构建虚拟机的命令行工具 qemu 组件,创建磁盘、启动虚拟机等 输入这条命令&#xff0c;…...

ArcGIS 10.2软件安装包下载及安装教程!

今日资源&#xff1a;ArcGIS 适用系统&#xff1a;WINDOWS 软件介绍&#xff1a;ArcGIS是一款专业的电子地图信息编辑和开发软件&#xff0c;提供一种快速并且使用简单的方式浏览地理信息&#xff0c;无论是2D还是3D的信息。软件内置多种编辑工具&#xff0c;可以轻松的完成地…...

一个专为云原生环境设计的高性能分布式文件系统

大家好&#xff0c;今天给大家分享一款开源创新的分布式 POSIX 文件系统JuiceFS&#xff0c;旨在解决海量云存储与各类应用平台&#xff08;如大数据、机器学习、人工智能等&#xff09;之间高效对接的问题。 项目介绍 JuiceFS 是一款面向云原生设计的高性能分布式文件系统&am…...

基于深度学习CNN算法的花卉分类识别系统01--带数据集-pyqt5UI界面-全套源码

文章目录 基于深度学习算法的花卉分类识别系统一、项目摘要二、项目运行效果三、项目文件介绍四、项目环境配置1、项目环境库2、环境配置视频教程 五、项目系统架构六、项目构建流程1、数据集2、算法网络Mobilenet3、网络模型训练4、训练好的模型预测5、UI界面设计-pyqt56、项目…...

3174、清除数字

3174、[简单] 清除数字 1、题目描述 给你一个字符串 s 。你的任务是重复以下操作删除 所有 数字字符&#xff1a; 删除 第一个数字字符 以及它左边 最近 的 非数字 字符。 请你返回删除所有数字字符以后剩下的字符串。 2、解题思路 遍历字符串&#xff1a; 我们需要逐个遍…...

C++ 优先算法 —— 无重复字符的最长子串(滑动窗口)

目录 题目&#xff1a; 无重复字符的最长子串 1. 题目解析 2. 算法原理 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口&#xff08;同向双指针&#xff09; 3. 代码实现 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口 题目&#xff1a; 无重复字符的最长子串 1. 题目解析 题目截图&#xff1a; 此题所说的…...

ADS学习笔记 6. 射频发射机设计

基于ADS2023 update2 更多ADS学习笔记&#xff1a;ADS学习笔记 1. 功率放大器设计ADS学习笔记 2. 低噪声放大器设计ADS学习笔记 3. 功分器设计ADS学习笔记 4. 微带分支定向耦合器设计ADS学习笔记 5. 微带天线设计 -1、射频发射机性能指标 在射频电路和系统中&#xff0c;发送…...

上海乐鑫科技一级代理商飞睿科技,ESP32-C61高性价比WiFi6芯片高性能、大容量

在当今快速发展的物联网市场中&#xff0c;无线连接技术的不断进步对智能设备的性能和能效提出了更高要求。为了满足这一需求&#xff0c;乐鑫科技推出了ESP32-C61——一款高性价比的Wi-Fi 6芯片&#xff0c;旨在为用户设备提供更出色的物联网性能&#xff0c;并满足智能设备连…...

QT QRadioButton控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例,包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizontalSpacer)、…...

51单片机从入门到精通:理论与实践指南(一)

单片机在智能控制领域的应用已非常普遍&#xff0c;发展也很迅猛&#xff0c;学习和使用单片机的人员越来越多。虽然新型微控制器在不断推出&#xff0c;但51单片机价格低廉、易学易用、性能成熟&#xff0c;在家电和工业控制中有一定的应用&#xff0c;而且学好了51单片机&…...

零基础3分钟快速掌握 ——Linux【终端操作】及【常用指令】Ubuntu

1.为啥使用Linux做嵌入式开发 能广泛支持硬件 内核比较高效稳定 原码开放、软件丰富 能够完善网络通信与文件管理机制 优秀的开发工具 2.什么是Ubuntu 是一个以桌面应用为主的Linux的操作系统&#xff0c; 内核是Linux操作系统&#xff0c; 具有Ubuntu特色的可视…...

C#中面试的常见问题007

1.在EF中实现一个实体对应多个表 1. 表拆分&#xff08;Table Splitting&#xff09; 表拆分是指将一个实体映射到两个或多个表中的行。这通常发生在实体的属性分布在不同的表中&#xff0c;但这些表通过外键关联到同一个主表。在EF Core中&#xff0c;可以通过Fluent API来配…...

人工智能——大语言模型

5. 大语言模型 5.1. 语言模型历史 20世纪90年代以前的语言模型都是基于语法分析这种方法&#xff0c;效果一直不佳。到了20世纪90年代&#xff0c;采用统计学方法分析语言&#xff0c;取得了重大进展。但是在庞大而复杂的语言信息上&#xff0c;基于传统统计的因为计算量巨大…...

nodejs第三方库sharp对图片的操作生成新图片、压缩、添加文字水印及图片水印等

Sharp是一个基于libvips的高性能Node.js图像处理库&#xff0c;它提供了广泛的功能&#xff0c;包括调整大小、裁剪、旋转、格式转换等。Sharp可以处理多种图像格式&#xff0c;并且能够高效地转换图像格式。 相关说明及用法看&#xff1a;https://sharp.nodejs.cn/ 安装&#…...

力扣第 67 题 “二进制求和”

题目描述 给你两个二进制字符串 a 和 b&#xff0c;以二进制字符串的形式返回它们的和。 示例 1: 输入: a "11", b "1" 输出: "100"示例 2: 输入: a "1010", b "1011" 输出: "10101"提示: 每个字符串仅由…...