java - 数据结构,算法,排序

news2024/11/18 3:40:04

一、概念

1.1、排序

排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
平时的上下文中,如果提到排序,通常指的是排升序(非降序)。 通常意义上的排序,都是指的原地排序(in place sort)
原地排序:就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。

1.2、稳定性(重要)

两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳定性的排序算法
在这里插入图片描述

1.3、应用

1. 各大商城的价格从低到高等
在这里插入图片描述
2. 中国大学排名
在这里插入图片描述

二、七大基于比较的排序-总览

在这里插入图片描述

三、插入排序

3.1、直接插入排序-原理

整个区间被分为

  1. 有序区间
  2. 无序区间
    每次选择无序区间的第一个元素,在有序区间内选择合适的位置插入

插入排序非常简单,就像打扑克牌一样,假设我们拿到第一张牌,那第一场牌肯定是有序的,然后那第二张牌和第一张牌比较,如果第二张牌比第一张小,那就将第一张牌放在前面,以此类推
在这里插入图片描述

根据这个思维:第一个数据是有序的,也就是说:在我们遍历的时候,是从下标1 开始的。
具体的操作见下图:

在这里插入图片描述

3.2、实现直接插入排序

/**
     * 直接插入排序,按照从小到达的循序
     * @param array
     */
    public static void insertSortUp(int[] array){
        for (int i = 1; i < array.length; i++) {
            int tmp = array[i];
            int j = i-1;
            for ( ;j >= 0; j--) {
                if(array[j] > tmp){
                    array[j+1] = array[j];
                }else {
                    break;
                }
            }
            array[j+1] = tmp;
        }
    }

3.3、插入排序的性能分析

插入排序的稳定性:
在这里插入图片描述

结论

一个稳定的排序,可以实现为 不稳定的排序。 但是,一个本身就不稳定的排序是 无法变成 稳定的排序。
直接插入排序 是 有序的。 它的时间复杂度是 O(N^2);最好情况:O(N【数组有序】 也就是说:对于直接插入排序,数据越有序越快!
由此,不难联想到:直接插入排序有时候 会用于 优化 排序。
【假设:假设我们有一百万个数据需要排序,在排序的过程中,区间越来越小,数据越来越有序。直接插入排序的时间复杂度为 O(N),N
越来越小,那么,使用 直接插入排序是不是越来越快!也就是说:直接插入排序 有时候会 用于 排序优化】 直接插入排序经常使用在
数据量不多,且整体数据趋于有序的。

四、希尔排序

4.1、原理

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数n,把待排序文件中所有记录分成n个组,所有距离为 (数据量/n) 的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达只有一个组时,所有记录在统一组内排好序。

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1(gap就是要分成的组数)时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很
    快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比

正常情况下我们进行分组的时候都是按照顺序进行分组的
比如说:
在这里插入图片描述
那么,问题来了!我们怎去确定分多少组,而且越分越少。
【取自清华大学出版的一本书《数据结构》】
在这里插入图片描述

但是科学家的思维不同,他们分组的时候是跳着分组的
比如说:
在这里插入图片描述
在这里插入图片描述

上图转载于:https://blog.csdn.net/DarkAndGrey/article/details/122792097

4.2、模拟实现 - 希尔排序

/*
     * 时间复杂度和增量有关系,所以无法得出准确的时间复杂度
     * 但只需要记住:在一定的范围里,希尔排序的时间复杂度为 O(N^1.3 ~ N^1.5)
     * 空间复杂度为 O(1)
     * 稳定性:不稳定
     * 判断稳定性的技巧:如果在比较的过程中 发生了 跳跃式交换。那么,就是不稳定的排序。
     * */
    public static void shell(int[] array,int group){
        for (int i = group; i < array.length; i++) {
            int j = i - group;
            int tmp = array[i];
            for( ; j >=0; j = j-group){
                if(tmp < array[j]){
                    //交换元素
                    array[j+group] = array[j];
                    array[j] = tmp;
                }else {
                    break;
                }
            }
            array[j+group] = tmp;
        }
    }

    public static void shellSort(int[] array){
        //将整个数组分为5组
        int gap = 5;
        while(gap > 1){
            //将分好组的数进行插入排序
            shell(array, gap);
            //循环得到分多少组,将分的组数按照 group / 2 来分组
            gap = gap / 2;
        }
        //循环结束,那就说明前面分好组的数都排序好了,只剩下最后的一组 就是 gap = 1的组
        shell(array, 1);
    }

五、选择排序

5.1、原理

这里是引用
上图转载于:https://blog.csdn.net/DarkAndGrey/article/details/122792097

优化
定义 一个 变量, 用来记录 此时的 i 后面最小值的下标。等 j 遍历完了,最小值的下标也就拿到了。此时,再进行交换。
这样就不必让上面那样,遇到比 i下标元素 小的,就交换。

5.2、模拟实现- 选择排序

/*
     * 选择排序
     * 稳定性: 不稳定 见附图
     * 时间复杂度:O(N^2) 》》 外层循环 n -1,内层循环 n -1
     * 空间复杂度:O(1)
     * */
    public static void selectSort(int[] array){
        for (int i = 0; i < array.length; i++) {

            for (int j = i+1; j < array.length; j++) {
                if(array[i] > array[j]){
                    int tmp = array[i];
                    array[i] = array[j];
                    array[j] = tmp;
                }
            }
        }
    }

5.3、双向选择排序 (了解)

每一次从无序区间选出最小 + 最大的元素,存放在无序区间的最前和最后,直到全部待排序的数据元素排完 。
在这里插入图片描述
上图转载于:https://blog.csdn.net/DarkAndGrey/article/details/122792097

public static void selectSortOP(int[] array){
        int low = 0;
        int high = array.length - 1;
        // [low,high] 表示整个无序区间
        while(low < high){
            int min = low;
            int max = low;
            for (int i = low+1; i <= high; i++) {
                if(array[i] < array[min]){
                    min = i;
                }
                if(array[i] > array[max]){
                    max = i;
                }
            }
            swap(array,min,low);
            if(max == low){
                max = min;
            }
            swap(array,max,high);
            low++;
            high--;
        }

    }
    public static void swap(int[] array,int x,int y){
        int tmp = array[x];
        array[x] = array[y];
        array[y] = tmp;
    }

六、堆排序

前面一篇文章讲过:Java -数据结构,【优先级队列 / 堆】

/**
     * 堆排序
     * @param array
     */
    public static void heapSort(int[] array){
        /*
         * 时间复杂度:O(N * log2 N)
         * 空间复杂度:O(1)
         * 稳定性:不稳定
         * */
        int end = array.length - 1;
        while(end>0){
            int tmp = array[end];
            array[end] = array[0];
            array[0] = tmp;
            shiftDown(array,0,end);
            end--;
        }
    }

     // 创建一个大根堆
    public static void creMaxHeap(int[] arr){
        for (int preant = (arr.length-1-1)/2; preant >= 0; preant--) {
            shiftDown(arr,preant, arr.length);
        }
    }

    /**
     * 向下调整
     * @param arr 数组
     * @param preant 父亲节点的下标
     * @param len 调整结束位置
     */
    public static void shiftDown(int[] arr, int preant, int len){
        int child = 2*preant+1;//孩子节点的下标
        while (child < len){
             if(child + 1 < len && arr[child] < arr[child+1]){
                 child = child+1;
             }

             if(arr[child] > arr[preant]){
                 int tmp = arr[child];
                 arr[child] = arr[preant];
                 arr[child] = tmp;

                 preant = child;
                 child = 2*preant+1;
             }else {
                 break;
             }
        }
    }

七、冒泡排序

/*
     * 时间复杂度:O(N^2) 【无论是最好情况,还是最坏情况,时间复杂度都不变】
     * 空间复杂度:O(1)
     * 稳定性:稳定【未发生跳跃式交换】
     * */
    public static void bubbleSort(int[] array){
        // 比较的趟数 = 数组的长度 - 1 【 0 ~ 3 一共 4趟】
        for (int i = 0; i < array.length-1; i++) {
            // 比较完一趟后,可以比较的元素个数减一。【因为靠后的数据已经有序】
            // 内循环中,之所以要减一个 1,是因为防止 下面的if语句 发生 数组越界异常
            for(int j = 0;j< array.length-1-i;j++){
                if(array[j] > array[j+1]){
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }
        }
    }

八、快速排序 - 重点

8.1、原理

  1. 从待排序区间选择一个数,作为基准值(pivot);
  2. Partition: 遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的(可以包含相等的)放到基准值的右边;
  3. 采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序,或者小区间的长度 == 0,代表没有数据。

在这里插入图片描述

总结
快速排序,其实说白了 和 二叉树 很像,先根,再左,后右。利用递归去实现!

8.2、模拟实现 - 快速排序

/**
     * 快速排序 - 将这组数据从小到大排序
     * 时间复杂度:O(N^2) 【数据有序或者逆序的情况】
     * 最好情况【每次可以均匀的分割待排序序列】:O(N * log2 N)
     * 空间复杂度:O(N)[单分支的一棵树]
     * 最好:log2 N
     * 稳定性:不稳定
     * @param array
     */
    public static void quickSort(int[] array){
        quick(array,0,array.length-1);
    }

    //排序
    public static void quick(int[] array, int left, int right){
        //排序
        if(left >= right){
            return;
        }
        //找基准
        int pivot = partition(array,left, right);
        quick(array,left,pivot-1);
        quick(array,pivot+1,right);
    }

    /**
     * 找基准
     */
    public static int partition(int[] array, int start, int end){
        int tmp = array[start];
        while (start < end){
            while (start < end && array[end] >= tmp){
                end--;
            }
            array[start] = array[end];

            while (start < end && array[start] <= tmp){
                start++;
            }
            array[end] = array[start];
        }
        array[start] = tmp;
        return start;
    }

8.3、快速排序 的 时间 与 空间复杂度分析

这里是引用
上图转载于:https://blog.csdn.net/DarkAndGrey/article/details/122792097

细节拓展

if语句中 比较大小的代码中 等号是不能省略的

当 下面框选的代码 没有等号时,会造成死循环。
在这里插入图片描述
我就改了一下,末尾元素的值。
在这里插入图片描述
那么,问题来了:为什么没有等号就死循环了?
在这里插入图片描述
所以,在 写快排的时候,比较大小的代码,记住一定要加上等号!!!!!

目前版本的 快排代码 不支持 大量数据进行排序 - 会导致栈溢出。

在这里插入图片描述

这是因为 我们递归的太深了,1百万数据,4百万字节。 1TB等于1024GB;1GB等于1024MB;1MB等于1024KB;1KB等于1024Byte(字节);1Byte等于8bit(位);
在这里插入图片描述
有的朋友会说:这才多大啊?栈怎么会被挤爆? 这是因为在递归的时候,开辟的栈帧【函数的信息,参数等等等…都有】,所以,每次开辟的栈帧不止 4byte。故栈被挤爆了。  
所以,我们要优化快排的 代码。【优化:数据有序的情况】

基准值的选择 - 优化前的知识补充

1、选择边上(左或者右) 【重点,上面使用的就是这种方法】
2、随机选择(针对 有序数据)【了解】
在这里插入图片描述
上图转载于:https://blog.csdn.net/DarkAndGrey/article/details/122792097

 /*
     * 时间复杂度:O(N^2) 【数据有序或者逆序的情况】
     * 最好情况【每次可以均匀的分割待排序序列】:O(N * log2 N)
     * 空间复杂度:O(N)[单分支情况]
     * 最好:log2 N
     * 稳定性:不稳定
     * */
    public static void quickSort(int[] array){
        quick(array,0, array.length-1);
    }
    public static void quick(int[] array,int start,int end){
        if(start >= end){
            return;
        }
        // 在找基准之前,先确定 start 和 end 的 中间值。[三数取中法]
        int midValIndex = findMidValIndex(array,start,end);
        //将它 与 start 交换。这样后面的程序,就不用改动了。
        swap(array,start,midValIndex);
        int pivot = partiton(array,start,end);
        quick(array,start,pivot-1);// 递归左边
        quick(array,pivot+1,end);// 递归右边
    }
    // 确定基准值下标
    private static int findMidValIndex(int[] array,int start,int end){
        // 确定 start 和 end 的中间下标
        int mid = start + ((end - start)>>>1);// == (start + end)/ 2
        // 确定 mid、start、end 三个下标,谁指向的元素是三个元素中的中间值
        if(array[end] > array[start]){
            if(array[start] > array[mid]){
                return start;
            }else if(array[mid] > array[end]){
                return end;
            }else{
                return mid;
            }
        }else{
            // array[start] >= array[end]
            if(array[end] > array[mid]){
                return end;
            }else if(array[mid] > array[start]){
                return start;
            }else {
                return mid;
            }
        }
    }
    // 交换两个下标元素
    private static void swap(int[] array,int x,int y){
        int tmp = array[x];
        array[x] = array[y];
        array[y] = tmp;
    }

    // 分割 - 找基准
    private static int partiton(int[] array,int start,int end){
        int tmp = array[start];
        while(start < end){
            while(start < end && array[end] >= tmp){
                end--;
            }
            // 此时 end 下标 元素的值 是 小于 tmp的。
            array[start] = array[end];
            while(start<end && array[start] <= tmp){
                start++;
            }
            array[end] = array[start];
        }
        array[start] = tmp;
        return start;
    }

8.4、快速排序 - 非递归实现

在这里插入图片描述

public static void quickSort(int[] array){
        Stack<Integer> stack = new Stack<>();
        int left = 0;
        int right = array.length-1;
        int pivot = partiton(array,left,right);
        if(pivot > left+1){
            stack.push(left);
            stack.push(pivot-1);
        }
        if(pivot < right -1){
            stack.push(pivot+1);
            stack.push(right);
        }
        while(!stack.isEmpty()){
            right = stack.pop();
            left = stack.pop();
            pivot = partiton(array,left,right);
            if(pivot>left+1){
                stack.push(left);
                stack.push(pivot-1);
            }
            if (pivot<right-1){
                stack.push(pivot+1);
                stack.push(right);
            }
        }
    }

    
    // 分割 - 找基准
    private static int partiton(int[] array,int start,int end){
        int tmp = array[start];
        while(start < end){
            while(start < end && array[end] >= tmp){
                end--;
            }
            // 此时 end 下标 元素的值 是 小于 tmp的。
            array[start] = array[end];
            while(start<end && array[start] <= tmp){
                start++;
            }
            array[end] = array[start];
        }
        array[start] = tmp;
        return start;
    }

九、归并排序 - 重点

首先做一个题:将两个有序表合并成一个有序表,称为二路归并。【简单说就是 将两个有序数组合并为一个有序数组,称为二路合并】
在这里插入图片描述

    //二路合并的代码如下
    public static int[] mergeArrays(int[] array1,int[] array2){
        if(array1 == null || array2 == null){
            return array1 == null ? array2: array1;
        }
        int[] arr = new int[array1.length + array2.length];
        int i = 0;// arr 的 遍历变量
        int s1 = 0;//array1 的 遍历变量
        int s2 = 0;//array2 的 遍历变量
        while(s1 < array1.length && s2 < array2.length){
            if(array1[s1] > array2[s2]){
                arr[i++] = array2[s2++];
//                s2++;
//                i++;
            }else{
                arr[i++] = array1[s1++];
//                s1++;
//                i++;
            }
        }
        // 循环结束,有一个数组的元素已经全部存入
        // 接下来就是将另一个数组的元素放入 arr 中
        while (s1 < array1.length){
            arr[i++] = array1[s1++];
//            i++;
//            s1++;
        }
        while (s2 < array2.length){
            arr[i++] = array2[s2++];
//            i++;
//            s2++;
        }
        return arr;
    }

9.1、归并排序 - 原理

归并排序(MERGE - SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
在这里插入图片描述

难点1 - 如何将一个数组拆分成一个个单独数组【每个数组里只包含一个元素】。

在这里插入图片描述

难点2 - 合并

在这里插入图片描述

总程序

/*
     * 时间复杂度:N * log2 N
     * 空间复杂丢:O(N)
     * 稳定性:稳定
     * */
    public static int[] mergeSort(int[] array){
        if(array == null){
            return array;
        }
        mergeSortFunc(array,0,array.length-1);
        return array;
    }
    private static void mergeSortFunc(int[] array,int low,int high){
        if(low >= high){
            return;
        }
//       int mid = (high + low) >>> 1
        int mid = low + ((high - low) >>> 1);
        mergeSortFunc(array,low,mid);// 左边
        mergeSortFunc(array,mid+1,high);// 右边
        merge(array,low,mid,high);
    }

    private static void merge(int[] array,int low,int mid,int high){
        int[] arr = new int[high - low +1];
        int start1 = low;
        int end1 = mid;
        int start2 = mid+1;
        int end2 = high;
        int i = 0;
        while (start1 <= end1 && start2 <= end2){
            if(array[start1] > array[start2]){
                arr[i++] = array[start2++];
            }else{
                arr[i++] = array[start1++];
            }
        }
        while(start1 <= end1){
            arr[i++] = array[start1++];
        }
        while(start2 <= end2){
            arr[i++] = array[start2++];
        }
        for (int j = 0; j < arr.length; j++) {
            array[low++] = arr[j];
        }
    }

归并排序 - 时间与空间复杂度分析、稳定性

在这里插入图片描述

9.2、归并排序 - 非递归实现

在这里插入图片描述

public static void mergeSort(int[] array){
        //归并排序非递归实现
        int groupNum = 1;// 每组的数据个数
        while(groupNum < array.length){
            // 无论数组含有几个元素, 数组每次都需要从下标 0位置,开始遍历。
            for(int i = 0;i<array.length;i+= groupNum * 2){
                int low = i;
                int mid = low + groupNum -1;

                // 防止越界【每组的元素个数,超过了数组的长度】
                if(mid >= array.length){
                    mid = array.length-1;
                }
                int high = mid + groupNum;

                // 防止越界【超过了数组的长度】
                if(high >= array.length){
                    high = array.length-1;
                }
                merge(array,low,mid,high);
            }
            groupNum *= 2;//每组的元素个数扩大到原先的两倍。
        }
    }
    public static void merge(int[] array,int low,int mid,int high){
        // high 与 mid 相遇,说明 此时数组分组只有一组,也就说没有另一组的数组与其合并
        // 即数组已经有序了,程序不用再往下走。
        if(high == mid){
            return;
        }
        int[] arr = new int[high -low + 1];
        int start1 = low;
        int end1 = mid;
        int start2 = mid+1;
        int end2 = high;
        int i = 0;
        while(start1 <= end1 && start2 <= end2){
            if(array[start1]>array[start2]){
                arr[i++] = array[start2++];
            }else{
                arr[i++] = array[start1++];
            }
        }
        while (start1 <= end1){
            arr[i++] = array[start1++];
        }
        while(start2 <= end2){
            arr[i++] = array[start2++];
        }
        for (int j = 0; j < arr.length; j++) {
            array[low++] = arr[j];
        }
    }

海量数据的排序问题

外部排序:排序过程需要在磁盘等外部存储进行的排序
前提:内存只有 1G,需要排序的数据有 100G
因为内存中因为无法把所有数据全部放下,所以需要外部排序,而归并排序是最常用的外部排序

  1. 先把文件切分成 200 份,每个 512 M
  2. 分别对 512 M 排序,因为内存已经可以放的下,所以任意排序方式都可以
  3. 进行 200 路归并,同时对 200 份有序文件做归并过程,最终结果就有序了

十、排序总结

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

ESP32设备驱动-AM2301(DHT21)温度湿度传感器驱动

AM2301(DHT21)温度湿度传感器驱动 文章目录 AM2301(DHT21)温度湿度传感器驱动1、AM2301(DHT21)介绍2、硬件准备3、软件准备4、驱动实现1、AM2301(DHT21)介绍 AM2301 湿敏电容数字温湿度模块是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温…

腾讯安全SOC+与广州农商银行联合安全体系入选工信部试点示范项目

近日&#xff0c;工信部、央行、银保监、国家互联网信息办公室等十二部门联合发布“2022年网络安全技术应用试点示范项目名单”&#xff0c;由腾讯云和广州农村商业银行股份有限公司联合共建的“金融云平台安全运营体系”成功入选。该体系依托腾讯安全SOC产品&#xff0c;构建了…

java——了解反射

目录 什么是反射&#xff1f; 反射如何获取类信息&#xff1f; 小结&#xff1a; 什么是反射&#xff1f; 反射是用代码分析类信息的能力 类中有哪些信息&#xff1a;方法、对象、构造器、全局变量、父类、接口等.... 反射如何获取类信息&#xff1f; 三种方式 1.通过对象…

k8s client-go源码解析之informer 二

Informer&#xff08;二&#xff09; 注意&#xff1a;本文内容为学习笔记&#xff0c;内容为个人见解&#xff0c;不保证准确性&#xff0c;但欢迎大家讨论何指教。 本篇介绍cache.SharedIndexInforme中 Controller及其组件 informer大致工作流程如下&#xff1a; sharedI…

CVS Health 西维斯健康EDI需求

CVS Health西维斯健康在特拉华州成立&#xff0c;通过旗下的 CVS Pharmacy 和 Longs Drugs 零售店以及 CVS.com 电商提供处方药、美容产品、化妆品、电影和照片加工服务、季节性商品、贺卡和方便食品。CVS Health通过使高质量的护理变得更经济、更易获得、更简单、更无缝&#…

中国通信行业十大杰出女性,看看你认识几个?

注&#xff1a;排名不分先后█ 01 中国信息通信研究院副院长 王志勤王志勤王志勤在中国乃至全球通信行业具有极高的知名度。她1992年毕业于北京邮电大学无线通信专业&#xff0c;在通信领域辛勤耕耘了三十余年&#xff0c;长期从事标准研究和制定工作&#xff0c;参与了中国从2…

C 语言网络编程 — 高并发 TCP 网络服务器

目录 文章目录目录TCP Socket 编程示例服务端客户端测试高并发 TCP 网络服务器I/O 并发模型设计系统文件描述符数量限制完全断开连接导致的性能问题关注 TCP 连接的状态合理配置 TCP 连接内核参数使用 shutdown() 来确保 Connection 被正常关闭断开重连问题使用 Heartbeat 来判…

【强化学习】强化学习数学基础:时序差分方法

时序差分方法Temporal Difference Learning举个例子TD learning of state values算法描述TD learning of action values: SarsaTD learning of action values: Expected SarsaTD learning of action values: n-step SarsaTD learning of optimal action values: Q-learningA un…

【Redis】主从集群 实现读写分离(二)

目录 2.Redis主从 2.1.搭建主从架构 2.2.主从数据同步原理 2.2.1.全量同步 2.2.2.增量同步 2.2.3.repl_backlog原理 2.3.主从同步优化 2.4.小结 2.Redis主从 2.1.搭建主从架构 单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;…

YOLOv7、YOLOv5改进之打印热力图可视化:适用于自定义模型,丰富实验数据

💡该教程为改进YOLO高阶指南,属于《芒果书》📚系列,包含大量的原创改进方式🚀 💡更多改进内容📚可以点击查看:YOLOv5改进、YOLOv7改进、YOLOv8改进、YOLOX改进原创目录 | 唐宇迪老师联袂推荐🏆 💡🚀🚀🚀内含改进源代码 按步骤操作运行改进后的代码即可�…

【毕业设计】Java局域网聊天室系统的设计与实现

点击免费下载源码 视频聊天系统作为一种新型的通信和交流工具&#xff0c;突破了地域的限制&#xff0c;可以提供更为便捷、灵活、全面的音、视频信息的传递和服务&#xff0c;具有极其广泛的发展前景。 介绍了采用JAVA编程开发视频聊天系统的一套比较常用的解决方案。文字聊…

Spring之实例化Bean _ @Resource和@Autowired实现原理(3)

目录 1. 搜集注解信息 applyMergedBeanDefinitionPostProcessor(*) 2. 将实例化的Bean放入3级缓存中 addSingletonFactory&#xff08;***&#xff09;为循环依赖做准备 3. 根…

RS232/RS485信号接口转12路模拟信号 隔离D/A转换器LED智能调光控制

特点&#xff1a;● RS-485/232接口&#xff0c;隔离转换成12路标准模拟信号输出● 可选型输出4-20mA或0-10V控制其他设备● 模拟信号输出精度优于 0.2%● 可以程控校准模块输出精度● 信号输出 / 通讯接口之间隔离耐压3000VDC ● 宽电源供电范围&#xff1a;10 ~ 30VDC● 可靠…

搭建SpringBoot多模块微服务项目脚手架(一)

搭建SpringBoot多模块微服务项目脚手架(一) 文章目录搭建SpringBoot多模块微服务项目脚手架(一)1.概述2.微服务环境搭建介绍1.微服务环境描述2.搭建环境组件和版本清单3.搭建父模块环境3.1.创建springboot父工程1.创建springboot2.配置maven和java3.精简父模块4.pom文件配置5.父…

记录--服务端推送到Web前端有哪几种方式?

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 这个问题&#xff1f; 这个问题一般会出现在面试题里面&#xff0c;然后回答一些诸如轮询、WebSocket之类的答案。当然&#xff0c;实际开发中&#xff0c;也会遇到类似别人给你赞了&#xff0c;要通知…

华为OD机试题,用 Java 解【一种字符串压缩表示的解压】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…

20230309英语学习

What Is Sleep Talking? We Look at the Science 为什么人睡觉会说梦话&#xff1f;来看看科学咋说 Nearly everyone has a story about people talking in their sleep.Though it tends to be more common in children, it can happen at any age:A 2010 study in the jour…

如何恢复已清空的 Windows 回收站?

Windows 95 中引入的回收站文件夹&#xff08;也称为垃圾桶&#xff09;是有史以来最有用的功能之一&#xff0c;可以保护您免受自己的错误和粗心大意的影响。 通常&#xff0c;从文件夹中恢复丢失的文件就像单击桌面上的回收站图标并执行简单的拖放操作一样简单。 但是&…

Java实例实验项目大全源码企业通讯打印系统计划酒店图书学生管理进销存商城门户网站五子棋

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;java实例 获取完整源码源文件视频讲解文档资料等 文章目录1、企业通讯2、快递打印系统3、开发计划管理系统4、酒店管理系统5、图书馆管理系统6、学生成绩管理系统7、进销存管理系统8、神奇Book——图书商城9、企业门户网站…

数据库管理-第六十期 监听(20230309)

数据库管理 2023-03-09第六十期期 监听1 无法访问2 监听配置3 问题复现与解决4 静态监听5 记不住配置咋整总结第六十期期 监听 不知不觉又来到了一个整10期数&#xff0c;我承认上一期有很大的划水的。。。嫌疑吧&#xff0c;本期内容是从帮群友解决ADG前置配置时候的一个问题…