(java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
目录
冒泡排序(BubbleSort):
代码详解:
冒泡排序的优化:
选择排序(SelectSort):
代码详解:
插入排序(InsertSort):
代码详解:
希尔排序(ShellSort):
法一(交换法)代码详解:
法二(移位法-->插入排序的优化)代码详解:
快速排序(QuickSort):
代码详解:
归并排序(MergetSort):
代码详解:
基数排序(RadixSort):
代码详解:
最后,一张图概括:
冒泡排序(BubbleSort):
冒泡排序(BubbleSort)的基本思路:通过对待排序从前往后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前往后移动,较小的往上挪动,就像水底下的气泡一样逐渐向上冒。
图解:

代码详解:
public class BubbleSort {public static void main(String[] args){Scanner sc=new Scanner(System.in);int[] arr=new int[5];//假设测试案例只有五个数字System.out.print("请输入要排序的数组:");for(int i=0;i<5;i++){arr[i]=sc.nextInt();}bubblesort(arr);System.out.println();System.out.print("请输出排序好的数组:"+Arrays.toString(arr));}public static void bubblesort(int[] arr){for(int i=0;i<arr.length-1;i++){for(int j=0;j<arr.length-1-i;j++){if(arr[j]>arr[j+1]){int temp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;}}System.out.printf("第%d趟排序后的数组",i+1);//展示每次冒泡排序的过程System.out.println(Arrays.toString(arr));//将数组转化为字符串的形式输出}}
}
运行结果:(通过运行结果来展示“气泡”向上挪动的过程,较大的数逐渐沉底)

冒泡排序的优化:
因为排序的过程中,各个元素不断接近自己要排好时所对应的位置,如果一趟比较下来没有进行交换,就说明序列有序。通过设置一个标志flag判断元素是否进行过交换,从而减少不必要的比较。
优化代码:
// 将前面额冒泡排序算法,封装成一个方法
public static void bubbleSort(int[] arr) {// 冒泡排序 的时间复杂度 O(n^2), 自己写出int temp = 0; // 临时变量boolean flag = false; // 标识变量,表示是否进行过交换for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {// 如果前面的数比后面的数大,则交换if (arr[j] > arr[j + 1]) {flag = true;temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}//System.out.println("第" + (i + 1) + "趟排序后的数组");//System.out.println(Arrays.toString(arr));if (!flag) { // 在一趟排序中,一次交换都没有发生过break;} else {flag = false; // 重置flag!!!, 进行下次判断}}
}
时间复杂度:最坏情况:O(N^2)
最好情况:O(N)
空间复杂度:O(1)
小结冒泡排序规则
(1) 一共进行 数组的大小-1 次 的循环
(2)每一趟排序的次数在逐渐的减少
(3) 如果我们发现在某趟排序中,没有发生一次交换, 可以提前结束冒泡排序。这个就是优化
选择排序(SelectSort):
选择排序(SelectSort)的基本思路:
1. 选择排序一共有 数组大小 - 1 轮排序
2. 每1轮排序,又是一个循环, 循环的规则(代码)
2.1先假定当前这个数是最小数
2.2 然后和后面的每个数进行比较,如果发现有比当前数更小的数,就重新确定最小数,并得到下标
2.3 当遍历到数组的最后时,就得到本轮最小数和下标
2.4 交换 [代码中再继续说 ]
图解:

代码详解:
import java.util.*;
public class SelectSort {//selectsort排序的方法、public static void selectSort(int[] arr){for(int i=0;i<arr.length-1;i++){int minIdex=i;//设第一个数为最小,同时将其索引(在数组中的位置)用minIndex表示int min=arr[i];//用min记录最小的数for(int j=i+1;j<arr.length;j++){if(min>arr[j]){min=arr[j];//通过选择将最小的数选出,然后更新min和minIndexminIdex=j;}}arr[minIdex]=arr[i];//将当前位置的数和最小数交换arr[i]=min;System.out.println("这是第"+i+"次排序,结果是:");//记录排序的过程System.out.println(Arrays.toString(arr));}}
//测试排序public static void main(String[] args){Scanner sc=new Scanner(System.in);int[] arr=new int[5];System.out.println("请输入你要排序的数组:");for(int i=0;i<5;i++){arr[i]=sc.nextInt();}selectSort(arr);System.out.println("排序好后的数组是:");for(int i=0;i<5;i++){System.out.print(arr[i]+" ");}}
}
运行结果:(通过运行过程来展示排序过程)

时间复杂度:最坏情况:O(N^2)
最好情况:O(N^2)
空间复杂度:O(1)
插入排序(InsertSort):
插入排序(InsertSort)基本思路:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素(数组的第一个元素),.无序表中包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序的排序码进行比较,将它插入到有序表中的适当位置,使其成为新的有序表
图解:

代码详解:
import java.util.*;
public class InsertSort {
//InsertSort方法public static void insertSort(int[] arr){for(int i=1;i<arr.length;i++){int insertVal=arr[i];//将无序的数组的第一个元素记录,是后面要插入的数据int insertIndex=i-1;//同时有序的数组的最后一个元素的索引(元素在数组中的位置)记录while(insertIndex>=0 && insertVal<arr[insertIndex]){//判断条件,二者要同时满足arr[insertIndex+1]=arr[insertIndex];//将有序数组比insertVal小的元素后挪insertIndex--;}arr[insertIndex+1]=insertVal;//将insertVal插入合适的位置System.out.println("第"+i+"趟的排序为:");//记录排序过程System.out.println(Arrays.toString(arr));}}
//排序测试public static void main(String[] args){Scanner sc=new Scanner(System.in);int[] arr=new int[5];System.out.println("请输入要排序的数组:");for(int i=0;i< arr.length;i++){arr[i]=sc.nextInt();}insertSort(arr);System.out.println("输出排好序的数组");for(int i=0;i<arr.length;i++){System.out.print(arr[i]+" ");}}
}
运行结果:(通过运行过程来展示排序过程)

时间复杂度:最坏情况下为O(N*N),此时待排序列为逆序,或者说接近逆序
最好情况下为O(N),此时待排序列为升序,或者说接近升序。
空间复杂度:O(1)
希尔排序(ShellSort):
希尔排序(ShellSort)基本思路:希尔排序,先将待排序列进行预排序,使待排序列接近有序,然后再对该序列进行一次插入排序,此时插入排序的时间复杂度为O(N)
图解:

静态图解:

法一(交换法)代码详解:
import java.util.*;
public class ShellSort {
//ShellSort的方法public static void shellSort(int[] arr){int count=0;for(int gap= arr.length/2;gap>0;gap/=2){//将每次要排序的组别逐渐缩小for(int i=gap;i<arr.length;i++){//gap~arr.length是该组别一共要交换的次数for(int j=i-gap;j>=0;j-=gap){if(arr[j]>arr[j+gap]){//通过交换对数组进行排序int temp=arr[j];arr[j]=arr[j+gap];arr[j+gap]=temp;}}}System.out.println("第"+(++count)+"趟希尔排序是:"+Arrays.toString((arr)));//记录希尔排序的过程}}//ShellSort的测试public static void main(String[] args){Scanner sc=new Scanner(System.in);int[] arr=new int[]{8,9,1,7,2,3,5,4,6,0};System.out.println("排序前"+Arrays.toString((arr)));System.out.println();shellSort(arr);System.out.println("排序后"+Arrays.toString(arr));}
}
运行结果:(通过运行过程来展示排序过程)

法二(移位法-->插入排序的优化)代码详解:
import java.util.*;
public class ShellSort2 {//对交换式的希尔排序进行优化->移位法public static void shellSort2(int[] arr){int count=0;// 增量gap, 并逐步的缩小增量for (int gap = arr.length / 2; gap > 0; gap /= 2) {// 从第gap个元素,逐个对其所在的组进行直接插入排序for (int i = gap; i < arr.length; i++) {int j = i;int temp = arr[j];if (arr[j] < arr[j - gap]) {while (j - gap >= 0 && temp < arr[j - gap]) {//移动arr[j] = arr[j-gap];j -= gap;}//当退出while后,就给temp找到插入的位置arr[j] = temp;}}}}//shellSort2测试public static void main(String[] args){Scanner sc=new Scanner(System.in);int[] arr=new int[]{8,9,1,7,2,3,5,4,6,0};System.out.println("排序前"+ Arrays.toString((arr)));System.out.println();shellSort2(arr);System.out.println("排序后"+Arrays.toString(arr));}
}
运行结果:

时间复杂度平均:O(N^1.3)
空间复杂度:O(1)
快速排序(QuickSort):
快速排序(QuickSort)的基本思路:
1.选出一个数据(一般是最左边或是最右边的)存放在temp变量中,在该数据位置形成一个坑
2、还是定义一个l和一个R,L从左向右走,R从右向左走。(若在最左边挖坑,则需要R先走;若在最右边挖坑,则需要L先走)
图解:

代码详解:
import java.util.*;
public class QuickSort {
//QuickSort方法public static void quickSort(int[] arr, int left, int right) {int l = left; //左下标int r = right; //右下标//pivot 中轴值int pivot = arr[(left + right) / 2];int temp = 0; //临时变量,作为交换时使用//while循环的目的是让比pivot 值小放到左边//比pivot 值大放到右边while (l < r) {//在pivot的左边一直找,找到大于等于pivot值,才退出while (arr[l] < pivot) {l += 1;}//在pivot的右边一直找,找到小于等于pivot值,才退出while (arr[r] > pivot) {r -= 1;}//如果l >= r说明pivot 的左右两的值,已经按照左边全部是//小于等于pivot值,右边全部是大于等于pivot值if (l >= r) {break;}//交换temp = arr[l];arr[l] = arr[r];arr[r] = temp;//如果交换完后,发现这个arr[l] == pivot值 相等 r--, 前移if (arr[l] == pivot) {r -= 1;}//如果交换完后,发现这个arr[r] == pivot值 相等 l++, 后移if (arr[r] == pivot) {l += 1;}}// 如果 l == r, 必须l++, r--, 否则为出现栈溢出if (l == r) {l += 1;r -= 1;}//向左递归if (left < r) {quickSort(arr, left, r);}//向右递归if (right > l) {quickSort(arr, l, right);}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);//测试排序int[] arr = new int[5];System.out.println("请输入你要排序的数组:");for (int i = 0; i < 5; i++) {arr[i] = sc.nextInt();}quickSort(arr, 0, arr.length - 1);System.out.println("排序好后的数组是:");for (int i = 0; i < 5; i++) {System.out.print(arr[i] + " ");}}
}
运行结果:

时间复杂度平均:O(N^LogN)
空间复杂度:O(LogN)
归并排序(MergetSort):
归并排序(MergetSort)基本思路:
该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。代价是需要额外的内存空间。若将两个有序表合并成一个有序表,称为2-路归并。
图解:
动态图解:

代码详解:
import java.util.Arrays;
public class MergetSort {//分+合方法public static void mergeSort(int[] arr, int left, int right, int[] temp) {if(left < right) {int mid = (left + right) / 2; //中间索引//向左递归进行分解mergeSort(arr, left, mid, temp);//向右递归进行分解mergeSort(arr, mid + 1, right, temp);//合并merge(arr, left, mid, right, temp);}}//合并的方法/**** @param arr 排序的原始数组* @param left 左边有序序列的初始索引* @param mid 中间索引* @param right 右边索引* @param temp 做中转的数组*/public static void merge(int[] arr, int left, int mid, int right, int[] temp) {int i = left; // 初始化i, 左边有序序列的初始索引int j = mid + 1; //初始化j, 右边有序序列的初始索引int t = 0; // 指向temp数组的当前索引//(一)//先把左右两边(有序)的数据按照规则填充到temp数组//直到左右两边的有序序列,有一边处理完毕为止while (i <= mid && j <= right) {//继续//如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素//即将左边的当前元素,填充到 temp数组//然后 t++, i++if(arr[i] <= arr[j]) {temp[t] = arr[i];t += 1;i += 1;} else { //反之,将右边有序序列的当前元素,填充到temp数组temp[t] = arr[j];t += 1;j += 1;}}//(二)//把有剩余数据的一边的数据依次全部填充到tempwhile( i <= mid) { //左边的有序序列还有剩余的元素,就全部填充到temptemp[t] = arr[i];t += 1;i += 1;}while( j <= right) { //右边的有序序列还有剩余的元素,就全部填充到temptemp[t] = arr[j];t += 1;j += 1;}//(三)//将temp数组的元素拷贝到arr//注意,并不是每次都拷贝所有t = 0;int tempLeft = left; ////第一次合并 tempLeft = 0 , right = 1 // tempLeft = 2 right = 3 // tL=0 ri=3//最后一次 tempLeft = 0 right = 7while(tempLeft <= right) {arr[tempLeft] = temp[t];t += 1;tempLeft += 1;}}public static void main(String[] args){int[] arr={56,78,13,78,33};int[] temp=new int[arr.length];System.out.println("排序前:"+ Arrays.toString(arr));mergeSort(arr, 0, arr.length - 1, temp);System.out.println("排序后:"+Arrays.toString(arr));}
}
运行结果:

时间复杂度平均:O(N^LogN)
空间复杂度:O(N)
基数排序(RadixSort):
基数排序(RadixSort)基本思路:
基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
图解:

代码详解:
import java.util.*;
public class RadixSort {public static void radixSort(int[] arr) {//根据前面的推导过程,我们可以得到最终的基数排序代码//1. 得到数组中最大的数的位数int max = arr[0]; //假设第一数就是最大数for (int i = 1; i < arr.length; i++) {if (arr[i] > max) {max = arr[i];}}//得到最大数是几位数int maxLength = (max + "").length();//定义一个二维数组,表示10个桶, 每个桶就是一个一维数组//说明//1. 二维数组包含10个一维数组//2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length//3. 名明确,基数排序是使用空间换时间的经典算法int[][] bucket = new int[10][arr.length];//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数//可以这里理解//比如:bucketElementCounts[0] , 记录的就是 bucket[0] 桶的放入数据个数int[] bucketElementCounts = new int[10];//这里我们使用循环将代码处理for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {//(针对每个元素的对应位进行排序处理), 第一次是个位,第二次是十位,第三次是百位..for (int j = 0; j < arr.length; j++) {//取出每个元素的对应位的值int digitOfElement = arr[j] / n % 10;//放入到对应的桶中bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];bucketElementCounts[digitOfElement]++;}//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)int index = 0;//遍历每一桶,并将桶中是数据,放入到原数组for (int k = 0; k < bucketElementCounts.length; k++) {//如果桶中,有数据,我们才放入到原数组if (bucketElementCounts[k] != 0) {//循环该桶即第k个桶(即第k个一维数组), 放入for (int l = 0; l < bucketElementCounts[k]; l++) {//取出元素放入到arrarr[index++] = bucket[k][l];}}//第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!bucketElementCounts[k] = 0;}//System.out.println("第"+(i+1)+"轮,对个位的排序处理 arr =" + Arrays.toString(arr));}}public static void main(String[] args){Scanner sc = new Scanner(System.in);//测试排序int[] arr = new int[5];System.out.println("请输入你要排序的数组:");for (int i = 0; i < 5; i++) {arr[i] = sc.nextInt();}radixSort(arr);System.out.println("排序好后的数组是:");for (int i = 0; i < 5; i++) {System.out.print(arr[i] + " ");}}
}
运行结果:

时间复杂度平均:O(N*K)
空间复杂度:O(N*K)
最后,一张图概括:

博客到这里也是结束了,制作不易,喜欢的小伙伴可以点赞加关注支持下博主,这对我真的很重要~~
相关文章:
(java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
目录 冒泡排序(BubbleSort): 代码详解: 冒泡排序的优化: 选择排序(SelectSort): 代码详解: 插入排序(InsertSort): 代码详解: 希尔排序(ShellSort): 法一…...
服务器托管的作用是什么?
服务器托管是将企业的服务器和相关设备托管到具有完善机房设施、高品质网络环境与运营经验的网络数据中心内,服务器托管在维护方面一般是由客户负责的,或者是由其他的授权人进行远程维护。 那服务器托管的作用都有哪些呢? 服务器托管不需要企…...
美团启动架构调整:聚力核心本地商业,提升科技与境外业务优先级
2月2日,美团CEO王兴发布内部邮件宣布新的组织架构调整。邮件显示,美团对核心本地商业相关多项业务进行了整合,并进一步提升了科技与国际化相关业务的优先级。 在核心本地商业上,美团对过去相对独立的事业群进行了整合。主要调整包…...
监测Tomcat项目宕机重启脚本(Linux)
1.准备好写好的脚本 #!/bin/sh # 获取tomcat的PID TOMCAT_PID$(ps -ef | grep tomcat | grep -v tomcatMonitor |grep -v grep | awk {print $2}) # tomcat的启动文件位置 START_TOMCAT/mnt/tomcat/bin/startup.sh # 需要监测的一个GET请求地址 MONITOR_URLhttp://localhost:…...
道可云元宇宙每日资讯|北京:推进元宇宙在智慧城市应用
道可云元宇宙每日简报(2024年2月2日)讯,今日元宇宙新鲜事有: 石狮市检察院“元宇宙智慧展馆”正式启用 为深入实施数字检察战略,主动探索元宇宙技术在未成年人检察、公益诉讼检察等方面的应用,打造集案件…...
Logback学习
logback 1、logback介绍 Logback是由log4j创始人设计的另一个开源日志组件,性能比log4j要好。 lockback优点: 内核重写、测试充分、初始化内存加载更小,这一切让logback性能和log4j相比有诸多倍的提升。logback非常自然地直接实现了slf4j…...
【Chrono Engine学习总结】2-可视化
由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。 0、基本概念 类型说明: Chrono的可视化包括两块:实时可视化,以及离线/后处理可视化。 其中,实时可视化,又…...
pytorch创建tensor
目录 1. 从numpy创建2. 从list创建3. 创建未初始化tensor4. 设置默认tensor创建类型5. rand/rand_like, randint6. randn生成正态分布随机数7. full8. arange/range9. linspace/logspace10. Ones/zeros/eye11. randperm 1. 从numpy创建 2. 从list创建 3. 创建未初始化tensor T…...
Cmake语法学习3:语法
1.双引号 1.1 命令参数 1)介绍 命令中多个参数之间使用空格进行分隔,而 cmake 会将双引号引起来的内容作为一个整体,当它当成一个参数,假如你的参数中有空格(空格是参数的一部分),那么就可以使…...
JavaScript 基础 - 第1天
介绍 掌握 JavaScript 的引入方式,初步认识 JavaScript 的作用 引入方式 JavaScript 程序不能独立运行,它需要被嵌入 HTML 中,然后浏览器才能执行 JavaScript 代码。通过 script 标签将 JavaScript 代码引入到 HTML 中,有两种方式…...
人口增长问题 T1063
#include<bits/stdc.h> using namespace std; int main(){int n;double x;cin>>x>>n;for(int i1;i<n;i){xx*1.001;}printf("%.4lf",x);return 0; }...
2024年Java算法面试题
2024年Java实战面试题(北京)_java 5 年 面试-CSDN博客 一、波菲那契递归 System.out.println("banc " banc(10)) public static int banc(int n){if( n0 ){return 0;}else if( n1 ){return 1;}else{return banc(n-1) banc(n-2);} } 二、冒…...
C#——三角形面积公式
已知三角形的三个边,求面积,可以使用海伦公式。 因此,可以执行得到三角形面积公式的计算方法代码如下: /** / <summary>* / 三角形面积公式* / </summary>* / <param name"a">边长a</param>*…...
tcpdump在手机上的使用
首先手机得root才可以,主要分析手机与手机的通信协议 我使用的是一加9pro, root方法参考一加全能盒子、一加全能工具箱官方网站——大侠阿木 (daxiaamu.com)https://optool.daxiaamu.com/index.php tcpdump,要安装在/data/local/tmp下要arm6…...
unity 导出H5
Unity 输出html5_mob649e8157aaee的技术博客_51CTO博客 Unity打包WebGL报Unable to parse Build/*.framework.js.gz This can happen if build compression was......._unable to load file build/out.framework.js.gz! che-CSDN博客...
认识 SYN Flood 攻击
文章目录 1.什么是 SYN Flood 攻击?2.半连接与全连接队列3.如何防范 SYN Flood 攻击?增大半连接队列开启 SYN Cookie减少 SYNACK 重传次数 参考文献 1.什么是 SYN Flood 攻击? SYN Flood 是互联网上最原始、最经典的 DDoS(Distri…...
Node需要了解的知识
Node能执行javascript的原因。 浏览器之所以能执行Javascript代码,因为内部含有v8引擎。Node.js基于v8引擎封装,因此可以执行javascript代码。Node.js环境没有DOM和BOM。DOM能访问HTML所有的节点对象,BOM是浏览器对象。但是node中提供了cons…...
网络服务综合实验项目
目录 实验要求 运行环境 基础配置 业务需求 实验步骤 一、基础配置 1.1、配置静态IP 1.1.1、 在192.168.159.130中配置 1.1.2、 在192.168.159.131中配置 编辑 1.2、修改主机名及hosts映射 1.2.1、在192.168.159.130中配置 1.2.2、 编辑配置hosts文件 1.2.3、重启…...
工厂模式与抽象工厂模式
如有错误或有补充,以及任何的改进意见,请在评论区留下您的高见 工厂模式 工厂模式是一种创建型设计模式。在工厂模式中,类的实例化过程通常是通过一个专门的工厂类来完成的,而不是直接在客户端代码中进行的。这样可以提供更好的…...
Springboot整合Websocket实现ws和wss连接
1. 引入pom依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.10</version> </dependency>2. 新建websocket配置文件 import org.springf…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
