数据结构之常见排序算法

news2024/11/17 11:26:57

文章目录

    • 1.排序概念
    • 2.10种排序比较
    • 3.排序算法
    • 3.1直接插入排序(元素越有序,越高效)
    • 3.2希尔排序序( 缩小增量排序 )
    • 3.3直接选择排序
    • 3.5堆排序
    • 3.6冒泡排序
    • 3.8快速排序 递归实现(无序使用最好)
      • 3.8.1挖坑法 (建议用这个 找基准)
      • 3.8.2Hoare法
      • 3.8.3三数取中法 优化排序算法
    • 3.9 快速排序 非递归实现
    • 4.0归并排序
    • 4.1计数排序
    • 4.2基数排序
    • 4.3桶排序

1.排序概念

排序:就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

稳定性:假设一组序列中,有两个相同的元素,在排序之后,两个相同元素的前后顺序颠倒了,说明这个排序算法是不稳定的,反之。

在这里插入图片描述

2.10种排序比较

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

3.排序算法

3.1直接插入排序(元素越有序,越高效)

思路:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到
一个新的有序序列 。

在这里插入图片描述

 /*
    * 时间复杂度:最坏:o(N^2)
    *            最好:O(N)   数据都有序,j不会往前走,直接break
    *               当数据趋于有序的时候,排序速度非常快
    *               一般场景就是数据基本有序,建议使用直接插入排序
    * 空间复杂度:O(1)
    * 稳定性:稳定
    *    如果一个排序是稳定的,那么就可以实现为不稳定的,
    *     但是如果一个排序本身就是不稳定的,那么不能变成稳定的
    *
    * */
 
    //插入排序
    public static void insertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            int temp = array[i];
            int j = i - 1;
            for (; j >= 0; j--) {
                if (array[j] > temp) {
                    array[j + 1] = array[j];
                } else {
                    break;
                }
            }
            array[j + 1] = temp;
        }

    }

3.2希尔排序序( 缩小增量排序 )

基本思想:希尔排序是选的一个增量值分组,然后对每组使用直接插入排序算法排序,随着增量值减小,每组包含的值也越来越多,当增量值减为1时,整个序列在一组内排序

在这里插入图片描述

上代码:

 //希尔排序   每组进行插入排序
   /*时间复杂度:O(N^1.3) - O(N ^ 1.5)
    *空间复杂度:o(1)
    * 稳定性:不稳定的排序
    **/
   public static void shellSort(int[] array) {
       int gap = array.length;
       while (gap > 1) {
           gap /= 2;
           shell(array, gap);
       }
   }

   //插入排序 ------->gap
   public static void shell(int[] array, int gap) {
       for (int i = gap; i < array.length; i++) {
           int temp = array[i];
           int j = i - gap;
           for (; j >= 0; j -= gap) {
               if (array[j] > temp) {
                   array[j + gap] = array[j];
               } else {
                   break;
               }
           }
           array[j + gap] = temp;
       }
   }

3.3直接选择排序

基本思想:在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
在这里插入图片描述

(1)第一种

/*选择排序
     *时间复杂度:O(N^2)
     * 空间复杂度:o(1)
     * 稳定性:不稳定
     *
     * */
    public static void selectSort(int[] arrays) {
        for (int i = 0; i < arrays.length; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arrays.length; j++) {
                if (arrays[j] < arrays[minIndex]) {
                    minIndex = j;
                }
            }
            swap(arrays, i, minIndex);
        }
    }
     private static void swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

(2)前面是用了一个minIndex去找最小值然后交换,最后排序

那么如果用两个一个minIndex去找最小值,一个maxIndex去找最大值,然后用left指向前,right指向后,比如说是升序那就minIndex和left交换,maxIndex和right交换,这样效率应该是比第一种方法要快

在这里插入图片描述

3.5堆排序

基本思想:堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。

在这里插入图片描述

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

    private static void createBigHeap(int[] array) {
        for (int parent = (array.length - 1 - 1) / 2; parent >= 0; parent--) {
            shiftDown(array, parent, array.length);
        }
    }

    private static void shiftDown(int[] array, int parent, int len) {
        int child = parent * 2 + 1;
        //至少有左孩子
        while (child < len) {
            if (child + 1 < len && array[child] < array[child + 1]) {
                //有右孩子,且右孩子最大
                child++;
            }
            if (array[child] > array[parent]) {
                swap(array, child, parent);
                parent = child;
                child = 2 * parent + 1;

            } else {
                //child比parent小,不需要调整
                break;
            }
        }

    }

3.6冒泡排序

基本思想:冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。重复的进行上面的步骤,直到没有再需要交换的
在这里插入图片描述

 /*
     * 冒泡排序
     * 时间复杂度:不考虑优化 O(N^2),优化后,o(N)
     *空间复杂度o(1)
     * 稳定性:稳定
     * */
    public static void bubbleSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            //考虑优化如果某一轮中没有发生交换,则证明已经有序,不必进行后面轮数
            boolean flg = false;
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    swap(array, j, j + 1);
                    flg = true;
                }
            }
            if (flg == false) {
                return;
            }
        }
    }

    private static void swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

3.8快速排序 递归实现(无序使用最好)

基本思想:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,
左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,
然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
在写递归的过程中可联想 二叉树的前序遍历 找基准值 进行区间划分

 //快速排序
    /*
     * 时间复杂度:N*logN
     *            最好情况:N*logN
     *            最坏情况:N^2   有序   倒序   (只有左树或者只有右树)
     * 空间复杂度:
     *            最好情况:logN
     *            最坏情况:N
     * 稳定性:不稳定
     *
     * */
    //1.递归实现快速排序
    public static void quickSort(int[] array) {
        quick(array, 0, array.length - 1);
    }

    private static void quick(int[] array, int start, int end) {
        //递归结束条件
        //为什么取大于号  :1,2,3,4   越界
        if (start >= end) {
            return;
        }
        //基准
        int pivot = partition(array, start, end);//划分
        quick(array, start, pivot - 1);
        quick(array, pivot + 1, end);
    }
     //插入排序
    public static void insertSort2(int[] array, int start, int end) {
        for (int i = start + 1; i <= end; i++) {
            int temp = array[i];
            int j = i - 1;
            for (; j >= 0; j--) {
                if (array[j] > temp) {
                    array[j + 1] = array[j];
                } else {
                    break;
                }
            }
            array[j + 1] = temp;
        }

    }
 

3.8.1挖坑法 (建议用这个 找基准)

必须先走右边,再走左边,这样就不会出现将大的放在前面的情况
在这里插入图片描述

//基准  挖坑法
    private static int partition(int[] array, int left, int right) {
        int tmp = array[left];
        while (left < right) {
            //left<right   不然会越界
            //“ = ”必须取,不然会发生死循环:6  23 1  3 6
            while (left < right && array[right] >= tmp) {
                right--;
            }
            array[left] = array[right];
            while (left < right && array[left] <= tmp) {
                left++;
            }
            array[right] = array[left];
        }
        array[left] = tmp;
        return left;
    }

3.8.2Hoare法

在这里插入图片描述

//Hoare法
    private static int partition2(int[] array, int left, int right) {
        int tmp = array[left];
        int i = left;
        while (left < right) {
            //为什么要先从右边走,因为左边先停下来就会比tmp大,与i位置交换就会把比tmp大的换到前面
            while (left < right && array[right] >= tmp) {
                right--;
            }
            while (left < right && array[left] <= tmp) {
                left++;
            }
            swap(array, left, right);
        }
        swap(array, left, i);
        return left;
    }

3.8.3三数取中法 优化排序算法

在这里插入图片描述

在这里插入图片描述

 //1.递归实现快速排序
    public static void quickSort(int[] array) {
        quick(array, 0, array.length - 1);
    }

    private static void quick(int[] array, int start, int end) {
        //递归结束条件
        //为什么取大于号  :1,2,3,4   越界
        if (start >= end) {
            return;
        }
        //优化2:解决减少递归的次数
        if (end - start + 1 <= 14) {
            //假设有十万条数据,还剩十几条,那么数据基本有序,用插入排序更高效
            insertSort2(array, start, end);
            return;
        }

        // 三数取中法优化1:不用每一次都用start,而是从start ,mid  ,end中取一个中间数来作为基准然后将它与start位置的数交换位置即可,
        // 后续不用改变
        int i = minThree(array, start, end);
        swap(array, i, start);
        //基准
        int pivot = partition2(array, start, end);//划分
        quick(array, start, pivot - 1);
        quick(array, pivot + 1, end);
    }
     //三数取中法
    private static int minThree(int[] array, int start, int end) {
        int mid = (start + end) / 2;
        if (start < end) {
            if (mid < start) {
                return start;
            } else if (mid > end) {
                return end;
            } else {
                return mid;
            }
        } else {
            if (mid < end) {
                return end;
            } else if (mid > start) {
                return start;
            } else {
                return mid;
            }
        }
    }

3.9 快速排序 非递归实现

第一个分析:
在这里插入图片描述
第二个分析:
在这里插入图片描述
上代码:

//2.非递归实现快速排序
    /*
     * 时间复杂度:O(Nlog n)
     * 空间复杂度:O(log n)
     * 稳定性:不稳定
     * */
    public static void quickSort2(int[] array) {
        Deque<Integer> stack = new LinkedList<>();
        int left = 0;
        int right = array.length - 1;
        int pivot = partition(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 = partition(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);
            }
        }
    }

4.0归并排序

基本思想:归并排序是建立在归并操作上的一种有效的排序算法,将已有序的子序列合并,得到完全有序的序列;也就是先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

递归实现:
在这里插入图片描述


 //归并排序
    public static void mergeSort(int[] array) {
        mergeSortFunc(array, 0, array.length - 1);

    }

    private static void mergeSortFunc(int[] array, int start, int end) {
        //和快速排序原因一样
        if (start >= end) {
            return;
        }
        int mid = (end + start) / 2;
        //分
        mergeSortFunc(array, start, mid);
        mergeSortFunc(array, mid + 1, end);
        //并
        merge(array, start, end, mid);
    }

    private static void merge(int[] array, int start, int end, int mid) {
        int s1 = start;
        int s2 = mid + 1;
        //tmp数组下标
        int k = 0;
        //合并成一个临时数组
        int[] tmp = new int[end - start + 1];
        while (s1 <= mid && s2 <= end) {
            if (array[s1] <= array[s2]) {
                tmp[k++] = array[s1++];
            } else {
                tmp[k++] = array[s2++];
            }
        }
        //s2数组为空时,s1还有数据
        while (s1 <= mid) {
            tmp[k++] = array[s1++];
        }
        //同样的
        while (s2 <= end) {
            tmp[k++] = array[s2++];
        }
        //将tmp临时数组数据给原数组
        for (int i = 0; i < tmp.length; i++) {
            //这里start+i意思是,不一定start都是0下标开始的
            array[i + start] = tmp[i];
        }
    }

非递归实现归并排序:

  //非递归实现归并排序
    public static void mergeSort2(int[] array) {
        int gap = 1;
        while (gap < array.length) {
            //i += gap * 2,当前组拍序好后,i往后移动,排序下一组
            for (int i = 0; i < array.length; i += gap * 2) {
                int left = i;
                int mid = i + gap - 1;
                if (mid >= array.length) {避免越界异常
                    mid = array.length - 1;
                }
                int right = mid + gap;//
                if (right >= array.length) {//避免越界异常
                    right = array.length - 1;
                }
                merge(array, left, right, mid);
            }
            //间隙为1的每组排序好后,改为间隙为2的每组,重复上述步骤,接着排序下一组,直到gap
            //超过array.lengh,就排序好了
            gap *= 2;
        }

    }

4.1计数排序

在这里插入图片描述

 //计数排序
    /*
    * 时间复杂度:O(N+范围)
    * 空间复杂度:
    *
    * */
    public static void countSort(int[] array) {
        //1遍历数组,找到数组最大值和最小值
        int min = array[0];
        int max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i] < min) {
                min = array[i];
            }
            if (array[i] > max) {
                max = array[i];
            }
        }
        //2确定计数数组的长度
        int len = max - min + 1;
        int[] count = new int[len];
        //3遍历array数组,在计数数组中记录数字出现的个数
        for (int i = 0; i < array.length; i++) {
            count[array[i] - min]++;
        }
        //根据计数数组,将数字按照数组顺序重新返回array数组
        int index = 0;
        for (int i = 0; i < count.length; i++) {
            while (count[i] > 0) {
                //这里i+min:在array中加上min,反映真实数据
                array[index] = i + min;
                index++;
                count[i]--;
            }
        }
    }

4.2基数排序

基本思想:基数排序是利用分配和收集两种基本操作。
基数排序是一种按记录关键字的各位值逐步进行排序的方法。
此种排序一般适用于记录的关键字为整数类型的情况。所有对于字符串和文字排序不适合。

在这里插入图片描述

  private static void radixSort(int[] arr) {
        //待排序列最大值
        int max = arr[0];
        int exp;//指数
        //计算最大值
        for (int anArr : arr) {
            if (anArr > max) {
                max = anArr;
            }
        }
        //从个位开始,对数组进行排序
        for (exp = 1; max / exp > 0; exp *= 10) {
            //存储待排元素的临时数组
            int[] temp = new int[arr.length];
            //分桶个数
            int[] buckets = new int[10];
 
            //将数据出现的次数存储在buckets中
            for (int value : arr) {
                //(value / exp) % 10 :value的最底位(个位)
                buckets[(value / exp) % 10]++;
            }
            //更改buckets[i],
            for (int i = 1; i < 10; i++) {
                buckets[i] += buckets[i - 1];
            }
            //将数据存储到临时数组temp中
            for (int i = arr.length - 1; i >= 0; i--) {
                temp[buckets[(arr[i] / exp) % 10] - 1] = arr[i];
                buckets[(arr[i] / exp) % 10]--;
            }
            //将有序元素temp赋给arr
            System.arraycopy(temp, 0, arr, 0, arr.length);
        }
 
    }

4.3桶排序

基本思想:将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶内排完序之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了

在这里插入图片描述

public static void bucketSort(int[] arr){
    // 计算最大值与最小值
    int max = Integer.MIN_VALUE;
    int min = Integer.MAX_VALUE;
    for(int i = 0; i < arr.length; i++){
        max = Math.max(max, arr[i]);
        min = Math.min(min, arr[i]);
    }
    // 计算桶的数量
    int bucketNum = (max - min) / arr.length + 1;
    ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
    for(int i = 0; i < bucketNum; i++){
        bucketArr.add(new ArrayList<Integer>());
    }
    // 将每个元素放入桶
    for(int i = 0; i < arr.length; i++){
        int num = (arr[i] - min) / (arr.length);
        bucketArr.get(num).add(arr[i]);
    }
    // 对每个桶进行排序
    for(int i = 0; i < bucketArr.size(); i++){
        Collections.sort(bucketArr.get(i));
    }
    // 将桶中的元素赋值到原序列
	int index = 0;
	for(int i = 0; i < bucketArr.size(); i++){
		for(int j = 0; j < bucketArr.get(i).size(); j++){
			arr[index++] = bucketArr.get(i).get(j);
		}
	}  
}

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

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

相关文章

yo!这里是STL::string类简单模拟实现

目录 前言 常见接口模拟实现 默认成员函数 1.构造函数 2.析构函数 3.拷贝构造函数 4.赋值运算符重载 迭代器 简单接口 1.size() 2.c_str() 3.clear() 操作符、运算符重载 1.操作符[] 2.运算符 3.运算符> 扩容接口 1.reserve() 2.resize() 增删查改接口 …

JS常用操作数组的方法整理

JavaScript提供了许多用于操作数组的方法。以下是其中一些常见的方法&#xff1a; 1. push() : 将一个或多个元素添加到数组的末尾&#xff0c;并返回新数组的长度。 2. pop() : 移除并返回数组的最后一个元素。 3. unshift() : 将一个或多个元素添加到数组的开头&#xff0…

一做PPT就抓耳挠腮?老码农掏心分享,选对工具才能事半功倍

今天老陈闲来无事摸个鱼&#xff0c;逛社区的时候看到一条有趣的帖子&#xff0c;HR怒喷UI设计师垃圾&#xff0c;说他们还不如应届生毕业生有能力&#xff0c;设计能力菜的惊人&#xff0c;给老陈平淡的生活增加了不少乐趣。 底下的评论也很有意思&#xff0c;有人说视觉表现…

JavaScript正则表达式之座机号/手机号验证校验规则

引用:https://www.bilibili.com/read/cv18300539/ 本文对利用正则表达式对手机号码进行了验证 支持格式&#xff1a; 座机 &#xff1a;xxx-xxxxxxxx、xxxxxxxxxxxx …座机区号的横杠可有可无 手机&#xff1a;xxxxxxxxxxx JavaScript&#xff1a; var: checkPhone (rule,…

想要理解Linux内核是什么

我们可以思考一下进程何时才能感知到内核的存在。例如&#xff0c;在进行内存分配时&#xff0c;最终需要调用内核的sys_mmap系统调用来申请虚拟内存空间&#xff1b;在创建子进程时&#xff0c;最终需要调用内核的sys_fork来复制父进程&#xff1b;在打开文件时&#xff0c;最…

10家国外直播加速CDN厂商PK2023版

以下是针对流媒体加速的10家主要CDN厂商的比较&#xff0c;我们将根据每家公司发展史、他们提供的功能以及他们的CDN定价比较&#xff0c;这样您就可以选择最适合您需求的 CDN。 1.Akamai Akamai Technologies是一家美国CDN厂商&#xff0c;它是全球领先的媒体和软件交付CDN…

dbscan

dbscan Density-based spatial clustering of applications with noise (DBSCAN), 基于密度的聚类方法。 算法的阈值只有两个&#xff0c;距离阈值eps&#xff0c; 最小点个数minPts。如果一个点在eps为半径的园内&#xff0c;包含点的个数>minPts,那么这个点以及这个圆内的…

JavaWeb教程笔记

JavaWeb Java Web 1、基本概念 1.1、前言 web开发&#xff1a; web&#xff0c;网页的意思 &#xff0c; www.baidu.com静态web html&#xff0c;css提供给所有人看的数据始终不会发生变化&#xff01; 动态web 淘宝&#xff0c;几乎是所有的网站&#xff1b;提供给所有人…

VBA_MF系列技术资料1-133

MF系列VBA技术资料 为了让广大学员在实际VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-04属…

【LeetCode热题100】打卡第45天:倒数第24~20题

文章目录 【LeetCode热题100】打卡第45天&#xff1a;倒数第24~20题⛅前言 最佳卖股票时机含冷冻期&#x1f512;题目&#x1f511;题解 戳气球&#x1f512;题目&#x1f511;题解 零钱兑换&#x1f512;题目&#x1f511;题解 打家劫舍III&#x1f512;题目&#x1f511;题解…

【高级数据结构】并查集

目录 修复公路&#xff08;带扩展域的并查集&#xff09; 食物链&#xff08;带边权的并查集&#xff09; 修复公路&#xff08;带扩展域的并查集&#xff09; 洛谷&#xff1a;修复公路https://www.luogu.com.cn/problem/P1111 题目背景 A 地区在地震过后&#xff0c;连接…

ReactRouterv5在BrowserRouter和HashRouter模式下对location.state的支持

结论&#xff1a;HashRouter不支持location.state 文档&#xff1a;ReactRouter v5 从文档可看到history.push()方法支持2个参数&#xff1a;path, [state] state即是location.state&#xff0c;常用于隐式地传递状态参数 但文档未提的是&#xff0c;仅适用于BrowserRouter&am…

面试-杨辉三角python递归实现,二进制转换

杨辉三角 def yang_hui(x,y):xint(x)yint(y)assert x>y,列数不应该大于行数# x 表示行&#xff0c;y表示列if y1 or yx:return 1else:return yang_hui(x-1,y-1)yang_hui(x-1,y)xinput(输入第几行) yinput(输入第几列) resultyang_hui(int(x),int(y)) print(result) #inclu…

微信聊天记录监管有多重要?

在现代企业中&#xff0c;微信成为了主流的沟通工具。越来越多企业开始关注员工聊天记录的监管问题&#xff0c;因为这直接关系到信息泄露的风险。监管员工聊天记录可以保障公司形象、保护员工的安全&#xff0c;并有助于提高员工的工作效率。 监管员工聊天记录到底有多重要&am…

算法通关村第一关——链表白银挑战笔记

文章目录 两个链表的第一个重合节点判断回文链表 两个链表的第一个重合节点 同LeetCode 160.相交链表 解法一&#xff1a;Hash和Set(集合&#xff09;&#xff0c;此处用Set合适。 把其中一个链表的所有节点引用放入set&#xff0c;再从头遍历另一个链表第一次重合的地方就是答…

【flutter】flutter如何让app内字体大小不随着系统改变而改变

如果我们不特意设置&#xff0c;flutter开发的app他的字体大小是会跟着系统设置的字体大小而改变&#xff0c;这样就会导致页面出现布局错乱问题&#xff0c;那么如何解决这个问题呢&#xff1f;我也搜索了相关资料&#xff0c;有两个常用也是网络上搜集到比较多的方法&#xf…

PostgreSQL 简洁、使用、正排索引与倒排索引、空间搜索、用户与角色

PostgreSQL使用 PostgreSQL 是一个免费的对象-关系数据库服务器(ORDBMS)&#xff0c;在灵活的BSD许可证下发行。PostgreSQL 9.0 &#xff1a;支持64位windows系统&#xff0c;异步流数据复制、Hot Standby&#xff1b;生产环境主流的版本是PostgreSQL 12 BSD协议 与 GPL协议 …

三. 多传感器标定方案(空间同步)--3

前面内容&#xff1a; 一. 器件选型心得&#xff08;系统设计&#xff09;--1_goldqiu的博客-CSDN博客 一. 器件选型心得&#xff08;系统设计&#xff09;--2_goldqiu的博客-CSDN博客 二. 多传感器时间同步方案&#xff08;时序闭环&#xff09;--1 三. 多传感器标定方案&…

UE5初学者快速入门教程

虚幻引擎是一系列游戏开发工具&#xff0c;能够将 2D 手机游戏制作为 AAA 游戏机游戏。虚幻引擎 5 用于开发下一代游戏&#xff0c;包括Senuas Saga: Hellblade 2、Redfall&#xff08;来自 Arkane Austin 的合作射击游戏&#xff09;、Dragon Quest XII: The Flames of Fate、…

AI 医疗:MONAI用于医疗影像领域的深度学习

软件介绍 一套开源、免费的协作框架&#xff0c;旨在加速医学成像领域的研究和临床协作。目标是通过构建一个强大的软件框架来加快创新和临床转化的步伐&#xff0c;该框架有利于几乎各个级别的医学成像、深度学习研究和部署。 MONAI利用 3D Slicer 和 DeepEdit 算法来注释您的…