Java 数据结构篇-深入了解排序算法(动态图 + 实现七种基本排序算法)

 🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍
  

文章目录

        1.0 实现冒泡排序

        2.0 实现选择排序

        2.1 选择排序的改良升级

        3.0 实现堆排序

        4.0 实现插入排序

        5.0 实现希尔排序

        6.0 实现归并排序

        6.1 递归实现归并排序

        6.2 使用非递归实现归并排序

        6.3 递归归并排序 + 插入排序

        7.0 快速排序

        7.1 单边循环快排

        7.2 双边循环快排

        7.3 快速排序的改良升级


        1.0 实现冒泡排序

        冒泡排序是一种简单的排序算法,它重复地遍历要排序的列表,比较相邻的元素,并交换它们直到列表排序完成。冒泡排序的时间复杂度为 O(n^2) ,在最坏的情况下需要进行 n*(n-1)/2 次比较和交换操作。是一个稳定排序。

具体步骤如下:

         -从列表的第一个元素开始,依次比较相邻的两个元素,如果它们的顺序不正确,则交换它们的位置。

        - 继续比较相邻的元素,直到达到列表的末尾。

        - 重复以上步骤,直到列表排序完成。

冒泡排序的详解过程:

        冒泡排序的过程可以用一个简单的示意图来说明,假设我们要对一个包含5个元素的列表进行冒泡排序:

        初始状态: [5, 3, 8, 2, 1]

        第一轮冒泡:比较相邻的元素并交换它们的位置,直到最大的元素被“冒泡”到列表的末尾。[3, 5, 2, 1, 8] ,[x, x, x, x, 8] 所在的位置就是最终的位置,因此不需要再进行交换了。

        第二轮冒泡:同样比较相邻的元素并交换它们的位置,直到最大的元素被“冒泡”到列表的末尾。[3, 2, 1, 5, 8] , [x, x, x, 5, 8] 所在的位置就是最终的位置,因此不需要再进行交换了。

        第三轮冒泡:同理,[2, 1, 3, 5, 8] , [x, x, 3, 5, 8] 所在的位置就是最终的位置,因此不需要再进行交换了。

        第四轮冒泡:[1, 2, 3, 5, 8] 完成排序了,一共需要进行(数组长度 - 1 )轮冒泡。

        

  数组的顺序为 [8,7,6,5,4,3,2,1] 来进行冒泡排序的动态演示过程:

        

代码如下:

import java.util.Arrays;public class BubbleSort {public static void main(String[] args) {int[] arr = {1,10,7,4,8,3,2,6,9,5};bubble(arr);System.out.println(Arrays.toString(arr));}//冒泡排序public static void bubble(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;}}}}
}

        2.0 实现选择排序

        选择排序(Selection Sort)是一种简单直观的排序算法。选择排序的时间复杂度为 O(n^2) ,因为在每一轮中需要进行n次比较,找到最小元素。(默认从小到大排序)

       基本思想:每次从待排序的数据元素中选出最小(或最大)的一个元素,然后放到已排序序列的末尾。内层循环代表的是:当前这次循环中,需要找到剩余数组中最小的元素;外层循坏代表的是:需要进行多少次内层循环,才能将数组中的元素按从小到大排序完成。

举例详解选择过程:

        初识状态:[3, 44, 5, 27, 2, 50, 48]

        第一轮选择过程:记录未排好序的元素 3 ,然后从元素 3 的后一个元素 44 出发,寻找比 3 小的元素,如果找到了,则需要进行交换;如果没有找到,这说明元素 3 就是当前循环过程中最小的元素。当前找到了比元素 3 小的元素 2 ,那么需要进行交换。

        第二轮选择过程:因为元素 2 已经排好序了,那么需要记录从排好序元素的后一个元素 44 ,寻找的范围是当前记录的元素的后一个元素开始出发直到数组最后一个元素。同样,重复以上操作,如果找到了比 44 要小的元素,需要进行记录 minIndex = i ,内层循环结束后,最小的元素下标为 minIndex  ,交换 44 与下标为 minIndex 的元素。

        第三轮选择过程也是一样流程,这里就不多赘述了......

选择过程的动态图演示过程:

代码如下:

import java.util.Arrays;public class SelectSort {public static void main(String[] args) {int[] arr = {1,10,7,4,8,3,2,6,9,5};select1(arr);System.out.println(Arrays.toString(arr));}public static void select1(int[] arr) {for (int i = 0;i < arr.length - 1;i++) {int minIndex = i;for (int j = i + 1;j < arr.length;j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}if (i != minIndex) {swap(arr,i,minIndex);}}}public static void swap(int[] arr,int i,int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}

        2.1 选择排序的改良升级

        在选择过程中,内层循环每一次都是寻找最小的元素,这次改进是在寻找最小元素的同时,又找最大的元素,定义两个 letf ,right 指针,一开始分别指向数组的左右两边。此时外层的循环条件:left < right 。一次内层循环中找到了最小、最大元素,接着就分别于 left、right 下标元素进行交换,交换完之后,left++ ,right-- 。

        一开始 minIndex、maxIndex 都是从 left 开始,从左到右进行查找元素的。重点需要需要注意的是:假如最大的元素就是当前的 left 下标时,且 minIndex 与 left 进行交换后,会导致 maxIndex 找的元素下标就会发生变化,所以在下标 minIndex 与 left 交换完之后,需要判断 maxInde == left 是否发生,如果发生了,那么 maxIndex 需要重新赋值为 maxIndex = minIndex 。

代码如下:

import java.util.Arrays;public class SelectSort {public static void main(String[] args) {int[] arr = {1,10,7,4,8,3,2,6,9,5};select2(arr);System.out.println(Arrays.toString(arr));}public static void swap(int[] arr,int i,int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void select2(int[] arr) {int left = 0;int right = arr.length-1;while (left < right) {int minIndex = left;int maxIndex = left;for (int i = left+1;i <= right; i++) {if (arr[i] < arr[minIndex]) {minIndex = i;}if (arr[i] > arr[maxIndex]) {maxIndex = i;}}swap(arr,minIndex,left);if (maxIndex == left) {maxIndex = minIndex;}swap(arr,maxIndex,right);left++;right--;}}}

        3.0 实现堆排序

        堆排序(Heap Sort)是一种高效的排序算法,它利用了堆这种数据结构来实现排序。堆是一种特殊的完全二叉树,分为最大堆和最小堆两种类型。在堆排序中,通常使用最大堆。堆排序的时间复杂度为 O(nlogn) ,并且是原地排序算法,不需要额外的存储空间。

        堆排序的基本思想:首先将待排序的数据构建成一个最大堆,然后将堆顶元素(最大元素)与堆的最后一个元素交换,然后对剩余的元素重新调整为最大堆,重复这个过程直到整个序列有序。

        两个动作:首先是将数组中的元素构建成一个大顶堆的形式,接着从堆的最后一个元素与堆顶元素进行交换,再对当前的堆顶元素进行下潜处理,循环该过程即可。

堆排序的动态演示过程:(该过程演示的是降序的排序过程,那么相反,建立一个小顶堆)

代码如下:

建立大顶堆的代码:下潜、交换元素

class Heap {int[] arr;int size = 0;public Heap(int[] arr) {this.arr = arr;this.size = arr.length;buildBigHeap(arr,size);heapSort(arr);}public void buildBigHeap(int[] arr,int size) {for (int i = size / 2 - 1; i >= 0 ; i--) {down(i,size);}}private void down(int i,int size) {int left = i * 2 + 1;int right = left + 1;int max = i;if (left < size && arr[max] < arr[left]) {max = left;}if (right < size && arr[max] < arr[right]) {max = right;}if (max != i) {swap(arr,max,i);down(max,size);}}private void swap(int[] arr,int i,int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}

堆排序的完整代码:

import java.util.Arrays;public class HeapSort {public static void main(String[] args) {int[] arr = {1,10,7,4,8,3,2,6,9,5};Heap heap = new Heap(arr);System.out.println(Arrays.toString(arr));}
}
class Heap {int[] arr;int size = 0;public Heap(int[] arr) {this.arr = arr;this.size = arr.length;buildBigHeap(arr,size);heapSort(arr);}public void buildBigHeap(int[] arr,int size) {for (int i = size / 2 - 1; i >= 0 ; i--) {down(i,size);}}private void down(int i,int size) {int left = i * 2 + 1;int right = left + 1;int max = i;if (left < size && arr[max] < arr[left]) {max = left;}if (right < size && arr[max] < arr[right]) {max = right;}if (max != i) {swap(arr,max,i);down(max,size);}}private void swap(int[] arr,int i,int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public void heapSort(int[] arr) {for (int i = arr.length - 1; i > 0 ; i--) {swap(arr,i,0);down(0,i);}}}

        4.0 实现插入排序

        插入排序是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对未排序的数据逐个进行插入,从而达到排序的目的。插入排序的时间复杂度为 O(n^2) ,在最坏情况下(逆序排列的数组),需要进行 n*(n-1)/2 次比较和交换操作。插入排序适用于小规模数据或部分有序的数据。是一个稳定排序。

具体来说,插入排序的算法步骤如下:

        1.从第一个元素开始,该元素可以认为已经被排序。

        2.取出下一个元素,在已经排序的元素序列中从后向前扫描。

        3.如果该元素(已排序)大于新元素,将该元素移到下一位置。

        4.重复步骤3,直到找到已排序的元素小于或等于新元素的位置。

        5.将新元素插入到该位置后。

        6.重复步骤2~5。

插入排序动态图演示过程:

代码如下:

import java.util.Arrays;public class InsertSort {public static void main(String[] args) {int[] arr = {1,10,7,4,8,3,2,6,9,5};insert(arr);System.out.println(Arrays.toString(arr));}public static void insert(int[] arr) {for (int i = 1; i < arr.length; i++) {int key = arr[i];int j = i - 1;while(j >= 0 && arr[j] > key) {arr[j+1] = arr[j];j--;}arr[j+1] = key;}}}

        5.0 实现希尔排序

        希尔排序(Shell Sort)是一种改进的插入排序算法,也被称为“缩小增量排序”。它通过将数组分割成若干个子序列,对每个子序列进行插入排序,最终进行一次完整的插入排序得到有序序列。希尔排序的工作原理是通过逐步减小增量的方式,最终达到增量为1的插入排序。希尔排序的时间复杂度取决于增量序列的选择,通常为 O(n logn)

希尔排序的算法步骤如下:

        1. 选择一个增量序列,通常为 n/2、n/4、n/8……直到增量为 1 。

        2. 对每个增量进行插入排序,即将数组分割成若干个子序列,对每个子序列进行插入排序。

        3. 逐步缩小增量,重复步骤 2 ,直到增量为 1 。

        4. 最后进行一次增量为 1 的插入排序,完成排序过程。

希尔排序的动态演示过程:

代码如下:

import java.util.Arrays;public class ShellSort {public static void main(String[] args) {int[] arr = {8,9,1,7,2,3,5,4,6,0};shell(arr);System.out.println(Arrays.toString(arr));}public static void shell(int[] arr) {int size = arr.length;for (int gap = size >> 1;gap >= 1; gap >>= 1) {for (int i = gap; i < size;i++) {int key = arr[i];int j = i-gap;while(j >= 0 && arr[j] > key) {arr[j+gap] = arr[j];j -= gap;}arr[j + gap] = key;}}}}

        6.0 实现归并排序

        归并排序(Merge Sort)是一种经典的分治算法,它的基本思想是将待排序的数组递归地分成两个子数组,分别对两个子数组进行排序,然后将两个已排序的子数组合并成一个有序的数组。归并排序的过程可以描述为“分而治之”。

        归并排序是一种稳定的排序算法,它的时间复杂度始终为 O(n log n) ,这使得它在处理大规模数据时具有较好的性能。然而,归并排序的空间复杂度较高,因为它需要额外的空间来存储临时数组。

        6.1 递归实现归并排序

归并排序的算法步骤如下:

        1. 分:将待排序的数组分成两个子数组,直到子数组的长度为1。

        2. 治:对每个子数组进行递归排序,直到子数组有序。

        3. 合:将两个有序的子数组合并成一个有序的数组。

使用递归实现归并的动态演示过程:

代码如下:

import javax.print.DocFlavor;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.IllegalFormatCodePointException;public class mergeSort {public static void main(String[] args) {int[] arr = {1,10,7,4,8,3,2,6,9,5};int[] a = new int[arr.length];//spilt(arr,0, arr.length - 1,a);//merge(arr);spiltInsert(arr,0,arr.length,a);System.out.println(Arrays.toString(arr));}//使用递归实现归并排序public static void spilt(int[] arr,int left,int right, int[] a) {if (left == right) {return;}//分int mid = (left + right) >>> 1;spilt(arr,left,mid,a);spilt(arr,mid+1,right,a);//合mergeArr(arr,left,mid,mid + 1,right,a);System.arraycopy(a,left,arr,left,right - left + 1);}//非递归实现两个有序数组合并public static void mergeArr(int[] arr,int i,int iEnd,int j,int jEnd,int[] a) {int k = i;while(i <= iEnd && j <= jEnd) {if (arr[i] < arr[j]) {a[k] = arr[i];i++;}else {a[k] = arr[j];j++;}k++;}if (i > iEnd) {System.arraycopy(arr,j,a,k,jEnd - j + 1);}if (j > jEnd) {System.arraycopy(arr,i,a,k,iEnd - i + 1);}}}

         6.2 使用非递归实现归并排序

        非递归归并排序的关键是正确地计算子数组的大小并进行合并操作,直到整个数组都被合并为一个有序序列。

以下是非递归归并排序的主要步骤:

        1. 从数组中的每个元素开始,将其视为一个大小为1的有序序列。

        2. 通过迭代,将相邻的有序序列合并为更大的有序序列,直到整个数组变为一个有序序列。

        3. 在每次迭代中,合并的子数组大小以指数级增加,直到整个数组都被合并为一个有序序列。

代码如下:

    //使用递归实现归并排序public static void spilt(int[] arr,int left,int right, int[] a) {if (left == right) {return;}//分int mid = (left + right) >>> 1;spilt(arr,left,mid,a);spilt(arr,mid+1,right,a);//合mergeArr(arr,left,mid,mid + 1,right,a);System.arraycopy(a,left,arr,left,right - left + 1);}//非递归实现两个有序数组合并public static void mergeArr(int[] arr,int i,int iEnd,int j,int jEnd,int[] a) {int k = i;while(i <= iEnd && j <= jEnd) {if (arr[i] < arr[j]) {a[k] = arr[i];i++;}else {a[k] = arr[j];j++;}k++;}if (i > iEnd) {System.arraycopy(arr,j,a,k,jEnd - j + 1);}if (j > jEnd) {System.arraycopy(arr,i,a,k,iEnd - i + 1);}}

        6.3 递归归并排序 + 插入排序

        即集合了递归排序的优点与插入排序的优点实现更加高效排序。

代码如下:

    //递归归并 + 插入排序public static void spiltInsert(int[] arr,int left,int right,int[] a) {if (right - left <= 32) {insert(arr,left,right);return;}int m = (left + right) >>> 1;spiltInsert(arr,left,m,a);spiltInsert(arr,m+1,right,a);mergeArr(arr,left,m,m+1,right,a);System.arraycopy(a,left,arr,left,right-left+1);}//插入排序public static void insert(int[] arr,int left, int right) {for (int i = left + 1; i < right; i++) {int key = arr[i];int j = i - 1;while (j >= left && arr[j] > key) {arr[j+1] = arr[j];j--;}arr[j+1] = key;}}

        7.0 快速排序

        快速排序是一种常用的排序算法,它基于分治的思想。快速排序的基本思想是选择一个基准值,然后将数组分割成两部分,使得左边的元素都小于基准值,右边的元素都大于基准值。然后对左右两部分分别进行递归排序,直到整个数组有序。

以下是快速排序的主要步骤:

        1.选择一个基准值(通常是数组中的第一个元素)。

        2.将数组分割成两部分,使得左边的元素都小于基准值,右边的元素都大于基准值。这一步称为分区操作。

        3. 递归地对左右两部分进行快速排序。

        4. 当左右两部分都有序时,整个数组也就有序了。

        7.1 单边循环快排

        单边循环快排的时间复杂度为 O(n logn)空间复杂度为 O(logn)。单边循环快排(也称为荷兰国旗问题解法)是快速排序算法的一种实现方式,它通过使用单个指针在数组中进行循环遍历,实现数组的分区和排序。

代码如下:

//单边循环快排要点://选择最右侧元素作为基准点//j 找比基准点小的,i 找基准点大的,一旦找到,二者进行交换://                   交换时机: j 找到小的,且与 i 不相等//                   i 找到 >= 基准点元素后,不应自增// 最后基准点与 i 交换, i 即为基准点最终索引public static void quickSort(int[] arr) {recursion(arr,0,arr.length-1);}private static void recursion(int[] arr,int left,int right) {if (left >= right) {return;}//先找到基准点int m = benchmark(arr,left,right);//切分基准点两侧recursion(arr, left, m - 1);recursion(arr, m + 1, right);}private static int benchmark(int[] arr,int left,int right) {int temp = arr[right];//i 找最大值、 j 找最小值,一旦 j 找到最小值且 j != i 就可以交换了int i = left;int j = left;while (j < right) {if (arr[j] < temp) {if (i != j) {//交换swap(arr,i,j);}i++;}j++;}swap(arr,i,right);return i;}private static void swap(int[] arr,int i,int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}

        7.2 双边循环快排

        双边循环快排是一种快速排序算法的实现方式,它通过不断地将数组分割成两部分并对每一部分进行递归排序来实现排序。与单边循环快排相比,双边循环快排在分割数组时使用两个指针分别从数组的两端向中间移动,以实现更高效的分割操作。

        双边循环快排的时间复杂度为 O(nlogn)空间复杂度为 O(logn)。它是一种高效的排序算法,在大多数情况下都能够快速地对数组进行排序。

具体实现过程如下:

        1. 选择数组中的一个元素作为基准值(通常选择第一个元素)。

        2. 设置两个指针,一个指向数组的起始位置,另一个指向数组的末尾位置。

        3. 从起始位置开始,找到第一个大于基准值的元素,并将其位置记录下来。

        4. 从末尾位置开始,找到第一个小于基准值的元素,并将其位置记录下来。

        5. 交换这两个元素的位置,然后继续寻找下一个需要交换的元素,直到两个指针相遇。

        6. 将基准值与指针相遇的位置的元素交换位置,这样基准值左边的元素都小于基准值,右边的元素都大于基准值。

        7. 对基准值左右两个子数组分别进行递归排序。

代码如下:

    //双边循环快排要点://选择最左侧元素作为基准点//j 找比基准点小的, i 找比基准点大的,一旦找到,二者进行交换//       i 从左向右//       j 从右先左// 最后基准点与 i 交换, i 即为基准点最终索引public static void quickSort1(int[] arr) {recursion1(arr,0,arr.length-1);}private static void recursion1(int[] arr,int left,int right) {if (left >= right) {return;}int m = benchmark1(arr,left,right);recursion1(arr,left,m - 1);recursion1(arr,m + 1,right);}private static int benchmark1(int[] arr,int left,int right) {int temp = arr[left];int i = left;int j = right;while (i < j) {while (i < j && temp < arr[j]) {j--;}while (i < j && temp >= arr[i]) {i++;}swap(arr,i,j);}swap(arr,left,i);return i;}private static void swap(int[] arr,int i,int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}

        7.3 快速排序的改良升级

        考虑快排时,遇到的重复元素过多而进行改良。

代码如下:

    public static void quickSort1(int[] arr) {recursion1(arr,0,arr.length-1);}private static void recursion1(int[] arr,int left,int right) {if (left >= right) {return;}int m = benchmark2(arr,left,right);recursion1(arr,left,m - 1);recursion1(arr,m + 1,right);}//考虑快排时,遇到的重复元素过多而进行改良private static int benchmark2(int[] arr,int left,int right) {int temp = arr[left];int i = left + 1;int j = right;while(i <= j) {while(i <= j && arr[i] < temp) {i++;}while (i <= j && arr[j] > temp ) {j--;}if (i <= j) {swap(arr,i,j);i++;j--;}}swap(arr,left,j);return j;}

 

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

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

相关文章

HarmonyOS鸿蒙学习基础篇 - 通用事件

一、引言 HarmonyOS鸿蒙是华为推出的分布式操作系统&#xff0c;旨在为各种智能设备提供统一的操作系统。鸿蒙系统的一大特色是其强大的分布式能力&#xff0c;而通用事件则是实现这一能力的关键技术之一&#xff0c;本篇博客将介绍HarmonyOS鸿蒙中的通用事件。 二、 点击事件…

STM32-LwESP 移植

LwESP 是一个专门解析 Espressif 公司旗下 ESP 系列芯片 AT 指令的开源库&#xff0c;具有以下特性&#xff1a; 支持 Espressif 公司 ESP32, ESP32-C2, ESP32-C3, ESP32-C6 和 ESP8266 芯片。独立平台&#xff0c;采用 C99 标准编写&#xff0c;易于移植。允许不同的配置来优…

通讯录项目(终)

Start And Stick 上一期我们将通讯录的项目的基本功能已经实现&#xff0c;这一篇文章我们将对通讯录进行完善。 目录 Start And Stick 上期回顾&#xff1a; 上期必要代码&#xff1a; 数据打印&#xff1a; 代码讲解&#xff1a; 头部插入数据&#xff1a; 代码讲解&…

【Linux】专栏文章索引

为了方便 快速定位 和 便于文章间的相互引用等 作为一个快速准确的导航工具 Linux 目录&#xff1a; &#xff08;一&#xff09;CentOS 7 安装&配置Python

CSS 多色正方形上升

<template><view class="loop cubes"><view class="item cubes"></view> <!-- 方块1 --><view class="item cubes"></view> <!-- 方块2 --><view class="item cubes"></vie…

day23 其他事件(页面加载事件、页面滚动事件)

目录 页面加载事件页面/元素滚动事件页面滚动事件——获取位置 页面加载事件 加载外部资源&#xff08;如图片、外联CSS和JavaScript等&#xff09;加载完毕时触发的事件为什么使用&#xff1a; 有时候需要等页面资源全部处理完毕再做一些事老代码喜欢把script写在head中&…

20.2K Star,一个简洁美观、易用的云盘系统

Hi&#xff0c;骚年&#xff0c;我是大 G&#xff0c;公众号「GitHub指北」会推荐 GitHub 上有趣有用的项目&#xff0c;一分钟 get 一个优秀的开源项目&#xff0c;挖掘开源的价值&#xff0c;欢迎关注。 现在的网盘动不动就限速&#xff0c;涨价&#xff0c;非常不爽&#x…

如何“做好冲突管理”?

一、工作实际案例 产品经理在主导跨部门需求项目时&#xff0c;项目在验收阶段&#xff0c;产品经理与业务人员完成初步验收&#xff0c;接下来需要开发同学解决验收问题。 开发小组长反馈&#xff1a;经开发内部评估&#xff0c;按当前项目排期&#xff0c;因上线时间紧张&a…

数据监控-Prometheus/Grafana

一、数据监控Prometheus 1、什么是Prometheus Prometheus是由SoundCloud开源监控告警解决方案,从2012年开始编写代码,到2015年github上开源以来,吸引不少用户以及公司的使用。Prometheus作为新一代的开源解决方案,很多理念与Google SRE的运维之道不谋而合。 2、Promet…

讯飞大模型定制训练平台尝鲜

文章目录 前言进入平台功能探索余额数据集管理 先训为快讯飞星火3.0Chinese-Aplaca-2-7BLlama2-7BInternLM-7BBloomz-7Bfalcon-7BBloomz-3B 前言 众所周知&#xff0c;国产大模型如千问、书生、易等等都有开源大模型&#xff0c;但是出场时效果就很不错的讯飞星火大模型却迟迟…

OpenHarmony关系型数据库

1 概述 关系型数据库(Relational Database, 以下简称RDB)是一种基于关系模型来管理数据的数据库&#xff0c;是在SQLite基础上提供一套完整的对本地数据库进行管理的机制&#xff0c;为开发者提供无需编写原生SQL语句即可实现数据增、删、改、查等接口&#xff0c;同时开发者也…

通讯录小项目(上)

Start And Stick 通讯录的实现有很多种方式&#xff0c;今天我们将用结构体实现简单的通讯录项目功能。包括通讯录的增、删、查、改等功能。 思路&#xff1a; 此次代码文件分别为&#xff1a; 文件名用途sqlist.h用于函数和结构体的声明sqlist.c用于函数的实现test.c用于通讯…

DevOps系列文章之 Git命令:过滤日志

使用git log命令查找特定提交历史的高级技巧。其中的一些技巧配合格式化日志命令使用有奇效。 按照数量过滤 使用git log命令时最基本的过滤方式就是按照可以显示的日志条数进行过滤。如果你只对最近几次提交感兴趣&#xff0c;这会节省在页面上查看所有提交的麻烦。 git lo…

Vue3在css中使用v-bind绑定js/ts变量,也可以在scss和less中使用方式

主要介绍Vue3中的新增的v-bind()的常用使用方式&#xff0c;主要包括在css,less,scss中的使用&#xff0c;可以参考官方文档查看&#xff1a;Vue3官方文档 特别提醒 如果你想在scss中或者less中使用&#xff0c;可能会报各种乱七八糟的错误&#xff0c;最快最好用的方式就是单…

RBD —— 不同材质破碎

目录 Working with concrete Chipping Details Proxy geometry Constraints Working with glass Chipping Proxy geometry Constraints Resolving issues with glass fracturing Working with wood Clustering Using custom cutters Working with concrete Concr…

【RT-DETR有效改进】EfficientFormerV2移动设备优化的视觉网络(附对比试验效果图)

前言 大家好&#xff0c;我是Snu77&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持Re…

THM学习笔记——john

John the Ripper是目前最好的哈希破解工具之一。 John基本语法&#xff1a; john [options] [path to file] john&#xff1a;调用John the Ripper程序。 [path to file]&#xff1a;包含你要尝试破解的哈希的文件&#xff0c;如果它们在同一个目录中&#xff0c;你就不需要命名…

理解虚拟内存

虚拟内存管理 分页管理 将用户程序的地址空间分为若干个固定大小的区域&#xff0c;称为“页面”。典型的页面大小为 1KB。相应地&#xff0c;也将内存空间分为若干个物理块&#xff0c;页和块的大小相同。然后通过映射表&#xff0c;把连续的虚拟内存空间&#xff0c;映射到离…

C++: 内联函数

目录 概念&#xff1a; 与宏的对比&#xff1a; 函数膨胀&#xff1a; 内联函数的特性&#xff1a; 概念&#xff1a; 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调 用建立栈帧的开销&#xff0c;内联函数…

Feign 体系架构解析

正所谓麻雀虽小五脏俱全&#xff0c;HTTP 调用看着简单&#xff0c;实则下面隐藏的是一套非常复杂的流程。 从上古时代 jspservlet&#xff0c;到后面的 SpringMVC&#xff0c;在 HTTP 请求解析和封装上同样是煞费苦心。 我们在学习中经常会碰到这种 case&#xff0c;有些开源…