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

深入理解MySQL中的范围访问方法:单索引与多索引优化策略

深入理解MySQL中的范围访问方法&#xff1a;单索引与多索引优化策略 范围查询方法是数据库查询优化的一种重要手段&#xff0c;它通过利用索引来减少需要检查的数据行数&#xff0c;从而提高查询的执行效率。 范围查询使用单个索引来检索表中包含在一个或多个索引值区间内的子…

CSS 多色正方形上升

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

896.单调数列(Java)

目录 题目描述&#xff1a;输入&#xff1a;输出&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 如果数组是单调递增或单调递减的&#xff0c;那么它是 单调 的。 如果对于所有 i < j&#xff0c;nums[i] < nums[j]&#xff0c;那么数组 nums 是单调递增的。 如…

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

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

Midjourney图片生成描述词记录(今天一天)

抄别人的描述词 /imagine prompt:https://&#xff08;你的图片地址&#xff09;.jpg Super handsome boy IP by pop mart , green suit, no hair, bald head, Scenes in spring , pastel color , mockup , fine luster , clean background ,3D render , Soft focus , oc , bl…

NodeJS Express在线人数统计

NodeJS开发中&#xff0c;要在Express中实现一个在线人数统计系统&#xff0c;可以用下面的思路&#xff1a; 数据结构: 使用一个对象来存储每个 IP 地址的最后访问时间。 当有请求到来时: 1、检查该 IP 地址是否已存在于对象中。 2、如果存在&#xff0c;更新其访问时间。…

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

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

如何“做好冲突管理”?

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

linux如下显示目录和子目录的树形结构

目 录 一、需求 二、解决方法 三、tree工具的安装 1. centos中安装tree 2&#xff0c;在Ubuntu系统中安装tree 3&#xff0c;使用源码编译安装 四、tree的语法 1、语法 2、常用选项 一、需求 应用程序的目录中包含一些子目录&#xff0c;目录嵌套很多&am…

10个必学的Python编程小技巧

10个必学的Python编程小技巧 一、列表推导式&#xff08;List Comprehension&#xff09;二、生成器表达式&#xff08;Generator Expression&#xff09;三、使用enumerate()遍历列表四、使用zip()同时遍历两个列表五、使用setattr()和getattr()动态操作对象属性六、使用with语…

数据监控-Prometheus/Grafana

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

【大厂AI课学习笔记】1.1.1人工智能导论

这个系列&#xff0c;之前是百度的学习笔记&#xff0c;后来他们网站打不开了&#xff0c;现在换为另一个大厂的。 第一节 人工智能导论 1.1 人工智能导论 1.1.1 人工智能概念的诞生 AI&#xff0c;Artificial Intelligence 1956年&#xff0c;美国达特茅斯会议提出。 定义…

2024/1/28 备战蓝桥杯 1-3

目录 特殊日期 0特殊日期 - 蓝桥云课 (lanqiao.cn) 最大距离 0最大距离 - 蓝桥云课 (lanqiao.cn) 最长递增 0最长递增 - 蓝桥云课 (lanqiao.cn) 缩位求和 0缩位求和 - 蓝桥云课 (lanqiao.cn) ISBN号码 0ISBN号码 - 蓝桥云课 (lanqiao.cn) 串的处理 0串的处理 - 蓝桥…

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

文章目录 前言进入平台功能探索余额数据集管理 先训为快讯飞星火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用于通讯…