基础算法——排序算法(冒泡排序,选择排序,堆排序,插入排序,希尔排序,归并排序,快速排序,计数排序,桶排序,基数排序,Java排序)

1.概述

比较排序算法
算法最好最坏平均空间稳定思想注意事项
冒泡O(n)O( n 2 n^2 n2)O( n 2 n^2 n2)O(1)Y比较最好情况需要额外判断
选择O( n 2 n^2 n2)O( n 2 n^2 n2)O( n 2 n^2 n2)O(1)N比较交换次数一般少于冒泡
O( n l o g n nlogn nlogn)O( n l o g n nlogn nlogn)O( n l o g n nlogn nlogn)O(1)N选择堆排序的辅助性较强,理解前先理解堆的数据结构
插入O(n)O( n 2 n^2 n2)O( n 2 n^2 n2)O(1)Y比较插入排序对于近乎有序的数据处理速度比较快,复杂度有所下降,可以提前结束
希尔O(nlogn)O( n 2 n^2 n2)O( n l o g n nlogn nlogn)O(1)N插入gap序列的构造有多种方式,不同方式处理的数据复杂度可能不同
归并O( n l o g n nlogn nlogn)O( n l o g n nlogn nlogn)O( n l o g n nlogn nlogn)O(n)Y分治需要额外的O(n)的存储空间
快速O( n l o g n nlogn nlogn)O( n 2 n^2 n2)O( n l o g n nlogn nlogn)O(logn)N分治快排可能存在最坏情况,需要把枢轴值选取得尽量随机化来缓解最坏情况下的时间复杂度
非比较排序算法
非比较排序算法时间复杂度空间复杂度稳定性
计数排序O(n+k)O(n+k)稳定
桶排序O(n+k)O(n+k)稳定
基数排序O(d*(n+k))O(n+k)稳定

其中

  • n 是数组长度
  • k 是桶长度
  • d 是基数位数
稳定 vs 不稳定

在这里插入图片描述
说明:两个相同的数排序后没有发生改变,说明是稳定的

2.冒泡排序

  • 每轮冒泡不断地比较相邻的两个元素,如果它们是逆序的,则交换它们的位置
  • 下一轮冒泡,可以调整未排序的右边界,减少不必要比较

以数组 3、2、1 的冒泡排序为例,第一轮冒泡
在这里插入图片描述

第二轮冒泡
在这里插入图片描述
未排序区域内就剩一个元素,结束
在这里插入图片描述

public void bubbleSort(int[] nums) {for (int i = 0; i < nums.length - 1; i++) {for (int j = 0; j < nums.length - 1 - i; j++) {if (nums[j] > nums[j + 1]) {int temp = nums[j];nums[j] = nums[j + 1];nums[j + 1] = temp;}}}
}

优化手段:每次循环时,若能确定更合适的右边界,则可以减少冒泡轮数

以数组 3、2、1、4、5 为例,第一轮结束后记录的 x,即为右边界

在这里插入图片描述

public void bubbleSort(int[] nums) {int j = nums.length - 1;while (true) {int x = 0;for (int i = 0; i < j; i++) {if (nums[i] > nums[i + 1]) {int temp = nums[i];nums[i] = nums[i + 1];nums[i + 1] = temp;x = i;}}j = x;if (j == 0) {break;}}
}

3.选择排序

  • 每一轮选择,找出最大(最小)的元素,并把它交换到合适的位置

以下面的数组选择最大值为例
在这里插入图片描述

public void selectSort(int[] nums) {for (int i = 0; i < nums.length - 1; i++) {for (int j = i + 1; j < nums.length; j++) {if (nums[i] > nums[j]) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}}}
}

4.堆排序

  • 建立大顶堆
  • 每次将堆顶元素(最大值)交换到末尾,调整堆顶元素,让它重新符合大顶堆特性

建堆
在这里插入图片描述

交换,下潜调整
在这里插入图片描述

public class HeapSort {public static void main(String[] args) {int[] nums = new int[]{3, 2, 1, 4, 5, 7, 9, 6, 8};new HeapSort().heapSort(nums);System.out.println(Arrays.toString(nums));}//堆排序public void heapSort(int[] nums) {//1.建堆操作,符合大顶堆的特性heapify(nums, nums.length);//2.每次将堆顶元素(最大值)交换到末尾,调整堆顶元素,让它重新符合大顶堆特性for (int i = nums.length - 1; i > 0; i--) {swap(nums, 0, i);down(nums, 0, i);//交换完了以后不符合大顶堆的特性}}//建堆private void heapify(int[] nums, int size) {//从倒数第一个非叶子节点开始以此下潜int start = (size - 2) / 2;//非叶子节点的索引for (int i = start; i >= 0; i--) {down(nums, i, size);}}//下潜private void down(int[] nums, int parent, int size) {/*** 方式一:递归实现*//*int left = 2 * parent + 1;int right = 2 * parent + 2;int max = parent;if (left < size && nums[left] > nums[max]) {max = left;}if (right < size && nums[right] > nums[max]) {max = right;}if (parent != max) {swap(nums, parent, max);down(nums, max, size);}*//*** 方式二:循环实现*/while (true) {int left = 2 * parent + 1;int right = 2 * parent + 2;int max = parent;if (left < size && nums[left] > nums[max]) {max = left;}if (right < size && nums[right] > nums[max]) {max = right;}if (parent == max) {break;}swap(nums, parent, max);parent = max;}}//交换private void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

5.插入排序

  • 将数组分为两部分 [0 … low-1] [low … a.length-1]
    • 左边 [0 … low-1] 是已排序部分
    • 右边 [low … a.length-1] 是未排序部分
  • 每次从未排序区域取出 low 位置的元素, 插入到已排序区域
    在这里插入图片描述
递归版
public void insertSort(int[] nums) {sort(nums, 1);
}private void sort(int[] nums, int low) {if (low == nums.length) {return;}int t = nums[low];int i = low - 1;while (i >= 0 && t < nums[i]) {nums[i + 1] = nums[i];i--;}if (i != low - 1) {nums[i + 1] = t;}sort(nums, low + 1);
}
非递归版
public void insertSort(int[] nums) {for (int low = 1; low < nums.length; low++) {int t = nums[low];int i = low - 1;while (i >= 0 && t < nums[i]) {nums[i + 1] = nums[i];i--;}if (i != low - 1) {nums[i + 1] = t;}}
}

6.希尔排序

  • 简单的说,就是分组实现插入,每组元素间隙称为 gap
  • 每轮排序后 gap 逐渐变小,直至 gap 为 1 完成排序
  • 对插入排序的优化,让元素更快速地交换到最终位置

下图演示了 gap = 4,gap = 2,gap = 1 的三轮排序前后比较
在这里插入图片描述

public void shellSort(int[] nums) {for (int gap = nums.length >> 1; gap >= 1; gap = gap >> 1) {//原插入排序for (int low = gap; low < nums.length; low++) {int t = nums[low];int i = low - gap;while (i >= 0 && t < nums[i]) {nums[i + gap] = nums[i];i -= gap;}if (i != low - gap) {nums[i + gap] = t;}}}
}

7.归并排序

  • 分 - 每次从中间切一刀,处理的数据少一半
  • 治 - 当数据仅剩一个时可以认为有序
  • 合 - 两个有序的结果,可以进行合并排序

在这里插入图片描述

递归实现
public class MergeSort {public static void main(String[] args) {int[] nums = new int[]{3, 2, 1, 4, 5, 7, 9, 6, 8, 0};new MergeSort().mergeSort(nums);System.out.println(Arrays.toString(nums));}private void mergeSort(int[] nums) {int[] merge = new int[nums.length];split(nums, merge, 0, nums.length - 1);}//对数组进行切分private void split(int[] nums, int[] merge, int left, int right) {if (left == right) {//不可再切了return;}//寻找中间点,以中间点进行切分int mid = (left + right) >>> 1;//切分split(nums, merge, left, mid);split(nums, merge, mid + 1, right);merge(nums, merge, left, mid, mid + 1, right);System.arraycopy(merge, left, nums, left, right - left + 1);}/*** 合并两个有序数组** @param array 原始数组* @param merge 合并后的数组* @param i     第一个有序范围的起始位置* @param iEnd  第一个有序范围的结束位置* @param j     第二个有序范围的起始位置* @param jEnd  第二个有序范围的结束位置*/private void merge(int[] array, int[] merge, int i, int iEnd, int j, int jEnd) {int k = i;while (i <= iEnd && j <= jEnd) {if (array[i] < array[j]) {merge[k] = array[i];i++;} else {merge[k] = array[j];j++;}k++;}if (i > iEnd) {System.arraycopy(array, j, merge, k, jEnd - j + 1);}if (j > jEnd) {System.arraycopy(array, i, merge, k, iEnd - i + 1);}}
}
非递归实现
public class MergeSort {public static void main(String[] args) {int[] nums = new int[]{3, 2, 1, 4, 5, 7, 9, 6, 8, 0};new MergeSort().mergeSort(nums);System.out.println(Arrays.toString(nums));}private void mergeSort(int[] nums) {int length = nums.length;int[] merge = new int[length];//width代表有序区间的宽度,取值是1,2,4,8for (int width = 1; width < length; width *= 2) {//[left,right]代表待合并区间的左右边界for (int left = 0; left < length; left += 2 * width) {int right = Integer.min(2 * width + left - 1, length - 1);int mid = Integer.min(left + width - 1, length - 1);merge(nums, merge, left, mid, mid + 1, right);}//合并数组System.arraycopy(merge, 0, nums, 0, length);}}/*** 合并两个有序数组** @param array 原始数组* @param merge 合并后的数组* @param i     第一个有序范围的起始位置* @param iEnd  第一个有序范围的结束位置* @param j     第二个有序范围的起始位置* @param jEnd  第二个有序范围的结束位置*/private void merge(int[] array, int[] merge, int i, int iEnd, int j, int jEnd) {int k = i;while (i <= iEnd && j <= jEnd) {if (array[i] < array[j]) {merge[k] = array[i];i++;} else {merge[k] = array[j];j++;}k++;}if (i > iEnd) {System.arraycopy(array, j, merge, k, jEnd - j + 1);}if (j > jEnd) {System.arraycopy(array, i, merge, k, iEnd - i + 1);}}
}
归并排序 + 插入排序
  • 小数据量且有序度高时,插入排序效果高
  • 大数据量用归并效果好
  • 可以结合二者
public class MergeInsertSort {public static void main(String[] args) {int[] nums = new int[]{3, 2, 1, 4, 5, 7, 9, 6, 8, 0};new MergeInsertSort().mergeSort(nums);System.out.println(Arrays.toString(nums));}private void mergeSort(int[] nums) {int[] merge = new int[nums.length];split(nums, merge, 0, nums.length - 1);}private void split(int[] nums, int[] merge, int left, int right) {/*** 当元素数量少时,使用插入排序* 之前是切分至剩余一个元素时再合并*/if (right - left < 32) {insertSort(nums, left, right);return;}//寻找中间点,以中间点进行切分int mid = (left + right) >>> 1;//切分split(nums, merge, left, mid);split(nums, merge, mid + 1, right);merge(nums, merge, left, mid, mid + 1, right);System.arraycopy(merge, left, nums, left, right - left + 1);}public void insertSort(int[] nums, int left, int right) {for (int low = left + 1; low <= right; low++) {int t = nums[low];int i = low - 1;while (i >= left && t < nums[i]) {nums[i + 1] = nums[i];i--;}if (i != low - 1) {nums[i + 1] = t;}}}/*** 合并两个有序数组** @param array 原始数组* @param merge 合并后的数组* @param i     第一个有序范围的起始位置* @param iEnd  第一个有序范围的结束位置* @param j     第二个有序范围的起始位置* @param jEnd  第二个有序范围的结束位置*/private void merge(int[] array, int[] merge, int i, int iEnd, int j, int jEnd) {int k = i;while (i <= iEnd && j <= jEnd) {if (array[i] < array[j]) {merge[k] = array[i];i++;} else {merge[k] = array[j];j++;}k++;}if (i > iEnd) {System.arraycopy(array, j, merge, k, jEnd - j + 1);}if (j > jEnd) {System.arraycopy(array, i, merge, k, iEnd - i + 1);}}
}

8.快速排序

单边快排(lomuto分区)
  • 选择最右侧元素作为基准点
  • j 找比基准点小的,i 找比基准点大的,一旦找到,二者进行交换
    • 交换时机:j 找到小的,且与 i 不相等
    • i 找到 >= 基准点元素后,不应自增
  • 最后基准点与 i 交换,i 即为基准点最终索引

例如:
i 和 j 都从左边出发向右查找,i 找到比基准点4大的5,j找到比基准点小的2,停下来交换
在这里插入图片描述

i 找到了比基准点大的5,j 找到比基准点小的3,停下来交换
在这里插入图片描述

j 到达right 处结束,right 与 i 交换,一轮分区结束
在这里插入图片描述

public class QuickSort {public static void main(String[] args) {int[] nums = new int[]{3, 2, 1, 4, 5, 7, 9, 6, 8, 0};new QuickSort().quickSort(nums);System.out.println(Arrays.toString(nums));}/*** 洛穆托分区方案** @param nums*/public void quickSort(int[] nums) {quick(nums, 0, nums.length - 1);}public void quick(int[] nums, int left, int right) {if (left >= right) {return;}int index = partition(nums, left, right);//返回基准点元素的索引quick(nums, left, index - 1);quick(nums, index + 1, right);}//分区操作,返回基准点元素的索引public int partition(int[] nums, int left, int right) {int value = nums[right];//基准点元素int i = left;int j = left;while (j < right) {if (nums[j] < value) {//找到比基准点小的值了if (i != j) {swap(nums, i, j);}i++;}j++;}swap(nums, i, right);return i;}public void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}
双边快排
  • 选择最左侧元素作为基准点
  • j 找比基准点小的,i 找比基准点大的,一旦找到,二者进行交换
    • i 从左向右
    • j 从右向左
  • 最后基准点与 i 交换,i 即为基准点最终索引

例:

i 找到比基准点大的5停下来,j 找到比基准点小的1停下来(包含等于),二者交换

在这里插入图片描述
i 找到8,j 找到3,二者交换,i 找到7,j 找到2,二者交换
在这里插入图片描述
i == j,退出循环,基准点与 i 交换
在这里插入图片描述

public int partition(int[] nums, int left, int right) {int value = nums[left];//基准点元素int i = left;int j = right;while (i < j) {//j 从右向左找小的while (i < j && nums[j] > value) {j--;}//i 从左向右找大的while (i < j && nums[i] <= value) {i++;}//交换swap(nums, j, i);}swap(nums, left, i);return i;
}

优化

public int partition(int[] nums, int left, int right) {int index = ThreadLocalRandom.current().nextInt(right - left + 1) + left;swap(nums, index, left);int value = nums[left];//随机元素作为基准点元素int i = left;int j = right;while (i < j) {//j 从右向左找小的while (i < j && nums[j] > value) {j--;}//i 从左向右找大的while (i < j && nums[i] <= value) {i++;}//交换swap(nums, j, i);}swap(nums, left, i);return i;
}

解决数组中重复元素

public int partition(int[] nums, int left, int right) {int value = nums[left];//随机元素作为基准点元素int i = left + 1;int j = right;while (i <= j) {//j 从右向左找小的while (i <= j && nums[i] < value) {i++;}//i 从左向右找大的while (i <= j && nums[j] > value) {j--;}if (i <= j) {swap(nums, j, i);i++;j--;}}swap(nums, left, j);return j;
}

9.计数排序

  1. 确定范围:确定待排序数据中的最大值和最小值。
  2. 计数:创建一个计数数组,统计每个元素出现的次数。
  3. 累加计数:将计数数组转化为累加数组,确定每个元素在排序后的位置。
  4. 排序:将元素按照累加数组中的位置放入输出数组。
public void countSort(int[] nums) {//1.找出数组中的最大值与最小值int max = nums[0];int min = nums[0];for (int num : nums) {if (num > max) {max = num;}if (num < min) {min = num;}}//2.创建新数组,长度是 max - min + 1,用来保存原数组中的数据出现的次数int[] count = new int[max - min + 1];for (int num : nums) {count[num - min]++;}//3.循环新数组int k = 0;for (int i = 0; i < count.length; i++) {while (count[i] > 0) {nums[k++] = i + min;count[i]--;}}
}

10.桶排序

public void bucketSort(int[] nums) {//1.创建10个桶,每个桶里保存了一定的序列ArrayList<Integer>[] bucket = new ArrayList[10];//2.初始化for (int i = 0; i < bucket.length; i++) {bucket[i] = new ArrayList<>();}//3.把数据放入桶中for (int num : nums) {bucket[num / 10].add(num);}int k = 0;//4.排序每个桶内元素for (ArrayList<Integer> buck : bucket) {//转数组int[] array = buck.stream().mapToInt(i -> i).toArray();insertSort(array);//插入排序//遍历数组依次放入数组中for (int v : array) {nums[k++] = v;}}
}//插入排序
public void insertSort(int[] nums) {for (int low = 1; low < nums.length; low++) {int i = low - 1;int t = nums[low];while (i >= 0 && t < nums[i]) {nums[i + 1] = nums[i];i--;}if (i != low - 1) {nums[i + 1] = t;}}
}

通用

public void bucketSort(int[] nums, int range) {//1.找出数组中的最大值与最小值int max = nums[0];int min = nums[0];for (int num : nums) {if (num > max) {max = num;}if (num < min) {min = num;}}//1.创建10个桶,每个桶里保存了一定的序列ArrayList<Integer>[] bucket = new ArrayList[(max - min) / range + 1];//2.初始化for (int i = 0; i < bucket.length; i++) {bucket[i] = new ArrayList<>();}//3.把数据放入桶中for (int num : nums) {bucket[(num - min) / range].add(num);}int k = 0;//4.排序每个桶内元素for (ArrayList<Integer> buck : bucket) {//转数组int[] array = buck.stream().mapToInt(i -> i).toArray();insertSort(array);//插入排序//遍历数组依次放入数组中for (int v : array) {nums[k++] = v;}}
}

11.基数排序

基数排序(Radix Sort)是一种非比较型的排序算法,其基本原理是将整数按位数分配,然后按每个位数进行排序。基数排序的稳定性与子排序的稳定性有关。基数排序方法有几种,最常见的是LSD(Least Significant Digit,最低位优先)和MSD(Most Significant Digit,最高位优先)。

public class RadixSort {public static void main(String[] args) {String[] phoneNumbers = new String[]{"13812345678","13912345678","13612345678","13712345678","13512345678","13412345678","15012345678","15112345678","15212345678","15712345678"};new RadixSort().radixSort(phoneNumbers, 3);System.out.println(Arrays.toString(phoneNumbers));}public void radixSort(String[] nums, int length) {//1.准备10个桶并初始化ArrayList<String>[] buckets = new ArrayList[10];for (int i = 0; i < buckets.length; i++) {buckets[i] = new ArrayList<>();}//2.依次把数据放入桶内for (int i = length - 1; i >= 0; i--) {for (String num : nums) {buckets[num.charAt(i) - 48].add(num);}int k = 0;for (ArrayList<String> bucket : buckets) {for (String s : bucket) {nums[k++] = s;}bucket.clear();}}}
}

12.Java排序

Arrays.sort

JDK 7~13 中的排序实现

排序目标条件采用算法
int[] long[] float[] double[]size < 47混合插入排序 (pair)
size < 286双基准点快排
有序度低双基准点快排
有序度高归并排序
byte[]size <= 29插入排序
size > 29计数排序
char[] short[]size < 47插入排序
size < 286双基准点快排
有序度低双基准点快排
有序度高归并排序
size > 3200计数排序
Object[]-Djava.util.Arrays.useLegacyMergeSort=true传统归并排序
TimSort

JDK 14~20 中的排序实现

排序目标条件采用算法
int[] long[] float[] double[]size < 44 并位于最左侧插入排序
size < 65 并不是最左侧混合插入排序 (pin)
有序度低双基准点快排
递归次数超过 384堆排序
对于整个数组或非最左侧 size > 4096,有序度高归并排序
byte[]size <= 64插入排序
size > 64计数排序
char[] short[]size < 44插入排序
再大双基准点快排
递归次数超过 384计数排序
size > 1750计数排序
Object[]-Djava.util.Arrays.useLegacyMergeSort=true传统归并排序
TimSort
  • 其中 TimSort 是用归并+二分插入排序的混合排序算法
  • 值得注意的是从 JDK 8 开始支持 Arrays.parallelSort 并行排序
  • 根据最新的提交记录来看 JDK 21 可能会引入基数排序等优化
LeetCode题目

1题
912题
在这里插入图片描述

1122题
1636题
164题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/885008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索 Python 视频编辑新纪元:MoviePy库的神秘面纱

文章目录 探索 Python 视频编辑新纪元&#xff1a;MoviePy 库的神秘面纱第一部分&#xff1a;背景介绍第二部分&#xff1a;MoviePy 是什么&#xff1f;第三部分&#xff1a;如何安装这个库&#xff1f;第四部分&#xff1a;简单的库函数使用方法第五部分&#xff1a;结合场景使…

计算机网络:网络层 —— 多播路由选择协议

文章目录 多播路由选择协议多播转发树构建多播转发树基于源树的多播路由选择建立广播转发树建立多播转发树 组共享树的多播路由选择基于核心的生成树的建立过程 因特网的多播路由选择协议 多播路由选择协议 仅使用 IGMP 并不能在因特网上进行IP多播。连接在局域网上的多播路由…

Jenkins插件使用问题总结

Git Push插件 插件介绍 主要是用于git推送代码到远程仓库中使用&#xff0c;插件地址 pipeline中使用 官方说明中只有一句代码gitPush(gitScm: scm, targetBranch: env.BRANCH_NAME, targetRepo: origin) 流水线语法中也做的不齐全所以一开始我老是设置错&#xff0c;导致代…

【命令操作】Linux三剑客之awk详解 _ 统信 _ 麒麟 _ 方德

原文链接&#xff1a;【命令操作】Linux三剑客之awk详解 | 统信 | 麒麟 | 方德 Hello&#xff0c;大家好啊&#xff01;今天带来一篇关于Linux三剑客之awk命令详解的文章。在文本处理工具中&#xff0c;awk以其强大的文本筛选、格式化和数据处理功能而闻名。它能够在处理结构化…

操作系统概念(一)——IOMMU学习

系列文章目录 提示&#xff1a;本系列主要记录工作过程中遇到的操作系统基础概念以及工作原理 第一章 操作系统之IOMMU 文章目录 系列文章目录1. 设备访问内存的几种主要方式1.1 传统的 I/O 访问&#xff08;程序控制 I/O&#xff09;1.2 直接内存访问&#xff08;DMA&#xf…

计算机网络:网络层 —— IP 多播技术

文章目录 基本概念IP多播地址和多播组 IP多播的类型硬件多播将IPv4多播地址映射为多播MAC地址 基本概念 多播&#xff08;Multicast&#xff0c;也称为组播&#xff09;是一种实现“一对多”通信的技术&#xff0c;允许一台或多台主机&#xff08;多播源&#xff09;发送单一数…

windows运行ffmpeg的脚本报错:av_ts2str、av_ts2timestr、av_err2str => E0029 C4576

问题描述 我目前的环境是&#xff1a; 编辑器&#xff1a; Microsoft Visual Studio Community 2022 (64 位) 运行的脚本是ffmpeg自带的remux样例&#xff0c;只不过我想用c语言执行这个样例。在执行的过程中报错如下图&#xff1a; C4576 后跟初始值设定项列表的带圆括…

翻译工具开发技术笔记:《老挝语翻译通》app支持语音识别翻译功能,怎么提高语音识别的准确度呢?

《老挝语翻译通》app是一款专为老挝语翻译设计的免费工具&#xff0c;支持文本翻译、老挝文OCR文字识别提取、文字转语音。这款工具以其技术优势和用户友好的界面&#xff0c;为用户提供了便捷的老挝语翻译体验。 技术特点 文本翻译&#xff1a;支持双语输入&#xff0c;提供精…

Linux系统每日定时备份mysql数据

一、创建存储脚本的文件夹 创建文件夹&#xff0c;我的脚本放在/root/dbback/mysql mkdir ... cd /root/dbback/mysql 二、编写脚本 vi backup_mysql.sh 复制脚本内容 DB_USER"填写用户名" DB_PASSWORD"填写密码" DB_NAME"数据库名称" # …

MySQL基础-单表查询

语法 select [distinct] 列名1&#xff0c;列名2 as 别名... from数据表名 where组前筛选 group by分组字段 having组后筛选 order by排序的列 [asc | desc] limit 起始索引&#xff0c;数据条数 测试数据 # 建测试表 create table products (id int primary key a…

【Linux】Linux管道揭秘:匿名管道如何连接进程世界

&#x1f308;个人主页&#xff1a;Yui_ &#x1f308;Linux专栏&#xff1a;Linux &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;数据结构专栏&#xff1a;数据结构 &#x1f308;C专栏&#xff1a;C 文章目录 1.什么是管道 &#xff1f;2. 管道的类型2.1 匿…

前端学习Day13 CSS盒子的定位(固定定位篇“附练习”)

一、固定定位 固定定位 &#xff08;position:fixed&#xff09;其实是绝对定位的子类别&#xff0c;一个设置了 position:fixed 的元素是相对于视窗固定的&#xff0c;就算页面文档发生了滚动&#xff0c;它也会一直待在相同的地方。 ⚠️&#xff1a;固定定位会脱离文档流。…

Linux云计算 |【第五阶段】CLOUD-DAY9

主要内容&#xff1a; Metrics资源利用率监控、存储卷管理&#xff08;临时卷ConfitMap、EmptyDir、持久卷HostPath、NFS(PV/PVC)&#xff09; 一、Metrics介绍 metrics是一个监控系统资源使用的插件&#xff0c;可以监控Node节点上的CPU、内存的使用率&#xff0c;或Pod对资…

BM25:最佳匹配 ,文本相关性评分算法

目录 BM25:最佳匹配 一、BM25算法原理 二、BM25算法的应用场景 三、BM25算法的举例说明 BM25:最佳匹配 BM25(Best Matching 25)是一种在信息检索领域中广泛使用的文本相关性评分算法。它基于概率模型,考虑了词频(Term Frequency,TF)、逆文档频率(Inverse Documen…

论文阅读笔记:Image Processing GNN: Breaking Rigidity in Super-Resolution

论文阅读笔记&#xff1a;Image Processing GNN: Breaking Rigidity in Super-Resolution 1 背景2 创新点3 方法4 模块4.1 以往SR模型的刚性4.2 图构建4.2.1 度灵活性4.2.2 像素节点灵活性4.2.3 空间灵活性 4.3 图聚合4.4 多尺度图聚合模块MGB4.5 图聚合层GAL 5 效果5.1 和SOTA…

【游戏引擎之路】登神长阶(十二)——DirectX11教程:If you‘re going through hell, keep going!

【游戏引擎之路】登神长阶&#xff08;十二&#xff09;——DirectX11教程&#xff1a;If youre going through hell, keep going! 2024年 5月20日-6月4日&#xff1a;攻克2D物理引擎。 2024年 6月4日-6月13日&#xff1a;攻克《3D数学基础》。 2024年 6月13日-6月20日&#x…

编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用

往期内容 本专栏往期内容&#xff1a; Pinctrl子系统和其主要结构体引入Pinctrl子系统pinctrl_desc结构体进一步介绍Pinctrl子系统中client端设备树相关数据结构介绍和解析inctrl子系统中Pincontroller构造过程驱动分析&#xff1a;imx_pinctrl_soc_info结构体Pinctrl子系统中c…

toolkit二次开发学习之程序集(ProAsmcomp)和装配体组件路径对象(ProAsmcomppath)

程序集ProAsmcomp可以理解为装配体组件对象。 对象ProAssembly是ProSolid的一个实例&#xff0c;并共享相同的声明。因此&#xff0c;ProAssembly对象可以作为适用于装配体的任何ProSolid和ProMdl函数的输入。特别是&#xff0c;因为你可以使用函数ProSolidFeatVisit()来遍历特…

【启程Golang之旅】深入理解 Protocol Buffers 及其应用

如果你是 Go 语言的开发者&#xff0c;理解如何在 Go 中使用 Protobuf&#xff0c;将帮助你大幅提升数据传输的效率&#xff0c;并实现更高性能的系统设计。 本篇文章将深入探讨 Go 语言中使用 Protobuf 的基础知识、常见应用以及最佳实践&#xff0c;带你一步步了解如何在项目…

Intent介绍#1

Intent 它是Android里非常重要的角色&#xff0c;基本上是核心人物。 能做的 startActivity --> 启动activitybroadcastIntent -> BroadcastContext.startService(Intent) Context.bindService(Intent, BindServiceFlags, Executor, ServiceConnection) -> Service…