Java常用排序算法

算法复杂度
详解Java常用排序算法(10种,含演示动画)

冒泡排序(Bubble Sort)

arr[0] 与 arr[1]比较,如果前面元素大就交换,如果后边元素大就不交换。然后依次arr[1]与arr[2]比较,第一轮将最大值排到最后一位。
第二轮arr.length-1个元素进行比较,将第二大元素排到倒数第二位。直到某一轮元素位置没有交换或者结束最后一轮结束排序。这是冒泡排序改良版本。
冒泡排序的时间复杂度为O(n的2次方),这使得它在大型列表和实际应用中效率低下。
在这里插入图片描述

//冒泡排序
public void test1() {int[] arr = {5, 2, 8, 3, 1, 6};//i是冒泡次数for (int i = 0; i < arr.length - 1; i++) {//每一轮将flag设置成true,当已经排好后直接返回,不需要进行完整个循环boolean flag = true;//j需要排序的元素个数for (int j = 0; j < arr.length - i - 1; j++) {if (arr[j] > arr[j + 1]) {// 交换arr[j+1]和arr[j]int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;flag = false;}}if(flag == true){break;}}//arr = [1, 2, 3, 5, 6, 8]System.out.println("arr = " + Arrays.toString(arr));
}

选择排序(Selection Sort)

从数组中选择出最小值放在第一个,将之前第一个元素和最小值之前所在索引位交换,依次进行第二个、第三个…
选择排序每次从待排序的元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的元素排完。
选择排序的时间复杂度为O(n的2次方),这使得它在大型列表和实际应用中效率低下。
在这里插入图片描述

//选择排序
public void test2() {int[] arr = {5, 2, 8, 3, 1, 6};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;}}// 交换arr[i]和arr[minIndex]int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}//arr = [1, 2, 3, 5, 6, 8]System.out.println("arr = " + Arrays.toString(arr));
}

插入排序(Insertion Sort)

第一个元素天然排序;第二个元素如果比第一个小就插入到第一个前面;第三个与第一个小就插入到第一个前面,如果比第二个小就插入到第二个前面;依次类推…
插入排序是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。
插入排序的时间复杂度为O(n的2次方),这使得它在大型列表和实际应用中效率低下。但是,插入排序的实现非常简单,它在小型列表上的性能非常好。
在这里插入图片描述

//插入排序
public void test3() {int[] arr = {5, 2, 8, 3, 1, 6};// 外部循环从第二个元素开始,// 因为我们将第一个元素视为已排序部分for (int i = 1; i < arr.length; i++) {int temp  = arr[i];int j = i - 1;// 将当前值key和前面的值进行比较,// 如果前面的值>key 则将值往后移1位while (j >= 0 && arr[j] > temp ) {arr[j + 1] = arr[j];j--;}// 在不小当前值temp的位置,插入当前值temparr[j + 1] = temp;}//arr = [1, 2, 3, 5, 6, 8]System.out.println("arr = " + Arrays.toString(arr));
}

希尔排序(Shell Sort)

希尔排序是一种改进的插入排序算法,它的基本思想是将待排序的数组按照一定的间隔进行分组,对每组使用插入排序算法进行排序,然后缩小间隔,再对分组进行排序,直到间隔为1为止。
逐渐减小间隔大小的方法有助于提高排序过程的效率,可以减少比较和交换的次数。这是希尔排序算法的一个关键特点。

希尔排序的时间复杂度为O(n log n),但实际上它的性能比插入排序要好得多,特别是在大型列表上。希尔排序的性能取决于间隔序列的选择,但是目前还没有一种最优的间隔序列。

//希尔排序
public void test4() {//第一轮比如步长为5,拿出array[i],array[i+5]...,6与5,2与7,8与9等排序后array = {6, 2, 8, 3, 1, 5,7,9,4};//第二轮比如步长为3,第二轮拿出array[i],array[i+3]...,6与3与7,2与1与9,8与5与4,排序后array = {3, 1, 4, 6, 2, 5,7,9,8};//第三轮比如步长为1,进行插入排序int[] array = {5, 2, 8, 3, 1, 6,7,9,4};int increment = array.length / 2;while (increment >= 1){for (int i = increment; i < array.length; i++) {int j = i - increment;int temp = array[i];// 寻找插入位置并移动数据while (j >= 0 && array[j] > temp) {array[j + increment] = array[j];j -= increment;}array[j + increment] = temp;}// 设置新的增量increment /= 2;}//arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]System.out.println("arr = " + Arrays.toString(array));
}

快速排序(Quick Sort)

快速排序是一种分治思想的排序算法,它的基本思想是通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后再分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

快速排序的时间复杂度为O(n log n),它的性能比冒泡排序和插入排序要好得多,特别是在大型列表上。

int[] array = {5, 2, 8, 3, 1, 6,7,9,4};
第一次拿最大索引元素4,将比4大的都放后边,4小的都放前面
array = {3,1, 2,4,5,8, 6,7,9}
元素4索引位置已经确定
比4小的{3,1, 2}再以2为中心,小的排前面,大的排后边,确定了2的顺序。
因为1,32的前后,只有一个元素,也就确定了1,3顺序。
比4大的{5,8, 6,7,9}再以9为中心,依次类推...
public class Quick {public static void main(String[] args) {int[] arr = {5, 2, 8, 6, 1, 3};int[] expectedArr = {1, 2, 3, 5, 6, 8};Quick.quickSort(arr, 0, arr.length - 1);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}// 接收一个数组 arr,一个低索引 low ,和一个高索引 high 作为参数public static void quickSort(int[] arr, int low, int high) {// 检查 low 是否小于 high。如果不是,则意味着数组只有一个元素或为空,因此不需要排序if (low < high) {int pivot = partition(arr, low, high);quickSort(arr, low, pivot - 1);quickSort(arr, pivot + 1, high);}}/*** 取最后一个元素作为枢轴元素,将较小的元素放在左边,较大的元素放在右边* @param arr 输入数组* @param low 低位索引* @param high 高位索引* @return 枢轴所在位置*/private static int partition(int[] arr, int low, int high) {// 将最后一个元素作为枢轴元素( arr[high] )int pivot = arr[high];// 将 i 初始化为 low - 1,用于跟踪较小元素的索引int i = low - 1;for (int j = low; j < high; j++) {if (arr[j] < pivot) {// 如果当前元素 arr[j] 小于枢轴元素,则增加 i 并交换 arr[i] 和 arr[j]// 较小元素索引+1i++;// 将当前元素 arr[j] 放在较小元素索引位置// 将较小元素放在前面swap(arr, i, j);}// 其他情况,则较小元素索引没有增加,说明当前元素应该放在右边}// 将枢轴元素( arr[high] )与索引 i + 1 处的元素交换。// 确保枢轴元素左边是较小元素,右边是较大元素swap(arr, i + 1, high);// 将 i + 1 作为枢轴索引返回return i + 1;}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}
}

堆排序(Heap Sort)

维护堆的性质:
大顶堆:父节点永远大于左孩子和右孩子
比如父节点index为i,那么左孩子index为2i+1,右孩子index为2i+2

堆排序是一种树形选择排序算法,是将待排序的数组构建成一个大顶堆(或小顶堆),然后将堆顶元素与堆底元素交换位置,将交换后堆底元素(也就是最大值)拿出来并从堆中删除,再将剩余元素重新构建成堆,重复执行交换和重构堆的操作,直到整个数组有序。

堆排序是一种基于堆数据结构的排序算法,它的时间复杂度为O(n log n)。

public class Heap {// 堆排序方法public static void heapSort(int[] arr) {int n = arr.length;// 构建大根堆,// 这段代码是构建大根堆的过程,它的循环次数为n/2-1次,是因为在完全二叉树中,叶子节点不需要进行堆化操作,// 所以只需要对非叶子节点进行堆化,而非叶子节点的数量为n/2-1个。因此,只需要循环n/2-1次即可完成大根堆的构建。// 非叶子节点在一维数组中就是前面 n/2-1for (int i = n / 2 - 1; i >= 0; i--) {// 从最底层的根节点开始堆化,每次执行完成后,都找出最大值,并放在根节点位置// 逐层往上找,循环结束后,第一个元素肯定是最大值heapify(arr, n, i);}// 依次取出堆顶元素,并将余下元素继续堆化,得到有序序列for (int i = n - 1; i >= 0; i--) {// 第一个for循环已经找出最大值,所以先做交换,把最大值换到最后一个位置// 把最大值交换到最后一个位置,下一次循环最后一个位置就不比较了swap(arr, 0, i);// 继续找出最大值,放在第一个位置heapify(arr, i, 0);}}private static void heapify(int[] arr, int heapSize, int i) {int largest = i; // 初始化假设最大值为根节点int left = 2 * i + 1; // 相对于索引i的左节点索引int right = 2 * i + 2; // 相对于索引i的右节点索引// 找到左右子节点中的最大值if (left < heapSize && arr[left] > arr[largest]) {// 如果有左节点,且左节点大于根节点,则记录左节点为最大值largest = left;}if (right < heapSize && arr[right] > arr[largest]) {// 如果有右节点,且右节点大于最大值,则记录右节点为最大值largest = right;}// 上面两个if之后,肯定找到最大值if (largest != i) {// i 是根节点下标// 如果最大值不是根节点,则交换根节点与最大值节点,// 并递归地对最大值节点进行堆化swap(arr, i, largest);heapify(arr, heapSize, largest);}}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void main(String[] args) {int[] arr = {5, 2, 8, 3, 12, 35, 57, 1, 6};int[] expectedArr = {1, 2, 3, 5, 6, 8, 12, 35, 57};Heap.heapSort(arr);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}
}

计数排序(Counting Sort)

计数排序是一种非比较排序算法,它的基本思想是统计数组中每个元素出现的次数,然后根据元素出现的次数依次将元素放入有序的数组中。
计数排序时间复杂度为O(n+k),其中k为待排序的元素的最大值。

import org.junit.jupiter.api.Assertions;
import java.util.Arrays;public class Counting {public static void countingSort(int[] arr) {int n = arr.length;// 取出数组中最大值int max = getMax(arr);int[] count = new int[max + 1];// 统计每个元素出现的次数for (int i = 0; i < n; i++) {count[arr[i]]++;}// 计算每个元素在有序序列中的位置for (int i = 1; i <= max; i++) {// 因为count包含了每个数据出现的次数,所以从小到大,// 逐个往前加得到就是原数组中每个元素在有序序列中应有的位置count[i] += count[i - 1];}// 输出有序序列int[] sortedArr = new int[n];for (int i = n - 1; i >= 0; i--) {int item = arr[i];//元素int itemPos = count[item];// 元素在有序数组中的位置sortedArr[itemPos - 1] = item; // 将元素填入有序数组count[item]--;}// 将有序序列复制回原数组System.arraycopy(sortedArr, 0, arr, 0, n);}private static int getMax(int[] arr) {int max = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > max) {max = arr[i];}}return max;}public static void main(String[] args) {int[] arr = {5, 2, 6, 8, 3, 1, 6, 5, 12};int[] expectedArr = {1, 2, 3, 5, 5, 6, 6, 8, 12};Counting.countingSort(arr);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}
}

基数排序(Radix Sort)

基数排序是一种非比较排序算法,它的基本思想是将待排序的数组按照位数(个位、十位、百位)进行划分,然后依次对每个位上的数字进行排序,最终得到有序的数组。

基数排序的时间复杂度为O(d n),其中d为最大元素的位数,n为待排序元素的个数。

123,69,87,234排序
排序个位:123,234,87,69
排序十位:123,234,69,87
排序百位:069,087,123,234
public class Radix {public static void radixSort(int[] arr) {if (arr.length == 0) {return;}// 循环取得数组中的最大值int maxNum = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > maxNum) {maxNum = arr[i];}}// 根据最大值算出数组中的最大位数,个位、十位、百位、千位等int maxDigit = 0;while (maxNum != 0) {maxNum /= 10;maxDigit++;}// 初始化10个list,分别存放位数是0-9的10组数字List<List<Integer>> buckets = new ArrayList<>(10);for (int i = 0; i < 10; i++) {buckets.add(new ArrayList<>());}int mod = 10; // 初始10,用于数据个位数取模int div = 1; // 桶序号除数// 按位数循环数组,个位循环1次,十位循环2次,百位循环3次,以此类推!for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {// 循环数组,将数据分别存入桶中// 第一次循环,桶里面的个位数顺序排序完成// 第二次循环,个位、十位都排序完成// 第三次循环,个位、十位、百位都排序完成for (int j = 0; j < arr.length; j++) {// 计算当前位数的桶序号int bucketIndex = (arr[j] % mod) / div;buckets.get(bucketIndex).add(arr[j]);}// 循环桶列表,将当前位数已排序的数据放入数组中int currentIndex = 0;for (int j = 0; j < 10; j++) {List<Integer> bucket = buckets.get(j);for (int k = 0; k < bucket.size(); k++) {arr[currentIndex++] = bucket.get(k);}bucket.clear();}}}public static void main(String[] args) {int[] arr = {5, 2, 8, 3, 12, 35, 57, 1, 6};int[] expectedArr = {1, 2, 3, 5, 6, 8, 12, 35, 57};Radix.radixSort(arr);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}
}

归并排序(Merge Sort)

归并排序是一种分治思想的排序算法,它的基本思想是将待排序的数组分成若干个子序列,每个子序列都是有序的,然后再将子序列合并成一个有序的数组。
归并排序的时间复杂度为O(n log n),它的性能比冒泡排序和插入排序要好得多,特别是在大型列表上。

arr = {5, 2, 8, 3, 1, 6,7}
拆分:0+6=6/2=3,{5, 2, 8}{3, 1, 6,7}
{5, 2}{8}{3, 1}{ 6,7}
{5}{ 2}{8}{3}{ 1}{ 6}{7}
合并:{2,5,8}{1,3,6,7}
{1,2,3,5,6,7,8}
import org.junit.jupiter.api.Assertions;
import java.util.Arrays;public class Merge {public static void main(String[] args) {int[] arr = {5, 2, 8, 3, 1, 6};int[] expectedArr = {1, 2, 3, 5, 6, 8};Merge.mergeSort(arr, 0, arr.length - 1);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}public static void mergeSort(int[] arr, int left, int right) {if (left < right) {int mid = (left + right) / 2;mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);merge(arr, left, mid, right);}}public static void merge(int[] arr, int left, int mid, int right) {// 子数组 L 的大小int n1 = mid - left + 1;// 右子数组 R 的大小int n2 = right - mid;// 创建两个临时数组 L 和 R ,分别用来存储左子数组和右子数组的元素int[] L = new int[n1];int[] R = new int[n2];// 使用 for 循环将原始数组 arr 中的元素复制到临时数组 L 和 R 中,分别从 left 和 mid + 1 开始for (int i = 0; i < n1; i++) {L[i] = arr[left + i];}for (int j = 0; j < n2; j++) {R[j] = arr[mid + 1 + j];}// 初始化三个变量 i、j和k,分别指向数组 L 、R 和原始数组 arr 的起始位置int i = 0, j = 0, k = left;// 使用 while 循环,比较 L 和 R 的元素,并将较小的元素放回原始数组 arr 中while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k] = L[i];i++;} else {arr[k] = R[j];j++;}k++;}// 当 L 或 R 中的元素用完时,将剩余的元素依次放回原始数组 arr 中while (i < n1) {arr[k] = L[i];i++;k++;}while (j < n2) {arr[k] = R[j];j++;k++;}// merge 方法执行完毕后,两个子数组范围内的元素已经按照从小到大的顺序合并到了原始数组 arr 中}
}

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

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

相关文章

可视化工具选择指南:助力企业数字化转型和新质生产力发展

随着信息技术的快速发展和新质生产力概念的兴起&#xff0c;可视化工具在各个行业中的作用日益凸显。这些工具不仅能够帮助用户更直观地理解和分析数据&#xff0c;还能提升团队的协作效率和决策质量。 在当今数字化转型迅速发展的背景下&#xff0c;新质生产力的概念正在成为…

SpringBoot使用开发环境的application.properties

在Spring Boot项目中&#xff0c;application.properties 或 application.yml 文件是用于配置应用程序外部属性的重要文件。这些文件允许定制你的应用&#xff0c;而无需更改代码。根据不同的运行环境&#xff0c;可以通过创建以application-{profile}.properties格式命名的文件…

python-区间内的真素数(赛氪OJ)

[题目描述] 找出正整数 M 和 N 之间&#xff08;N 不小于 M&#xff09;的所有真素数。真素数的定义&#xff1a;如果一个正整数 P 为素数&#xff0c;且其反序也为素数&#xff0c;那么 P 就为真素数。 例如&#xff0c;11&#xff0c;13 均为真素数&#xff0c;因为 11 的反序…

利用Amazon Rekognition Face Liveness进行人脸活体检测的实践与探索

在人工智能、机器学习技术日渐普及的当下&#xff0c;出海企业都希望能够加快利用人工智能、机器学习技术&#xff0c;从而打造智能产品及其增值服务、为各地区提供本地化和个性化的服务体验及实现自身业务流程智能化。九河云将介绍人脸活体检测解决方案&#xff0c;亚马逊云科…

录频软件大盘点,哪款是你的最爱?

随着网络技术的飞速发展&#xff0c;人们对于录频软件的需求越来越强烈。无论是教育工作者、学生、游戏玩家还是商务人士&#xff0c;一款合适的录频软件都可以为他们提供便利。本文将介绍3款主流的录频软件&#xff0c;以帮助用户了解它们的特点、功能以及操作方法。 录频软件…

在Centos上安装MySQL

目录 在Centos上安装MySQL1.确认当前的系统版本2.添加 MySQL Yum 源2.1访问MySQL开发者专区2.2根据当前系统选择对应的发布包2.3补充 3.MySQL的历史发行版本4.安装发布包5.安装MySQL5.1启动MySQL服务器5.2查看服务器状态5.3开机自启动5.4 登入MySQL5.5修改密码 在Centos上安装M…

Spring Data Redis + Redis数据缓存学习笔记

文章目录 1 Redis 入门1.1 简介1.2 Redis服务启动与停止&#xff08;Windows&#xff09;1.2.1 服务启动命令1.2.2 客户端连接命令1.2.3 修改Redis配置文件1.2.4 Redis客户端图形工具 2. Redis数据类型2.1 五种常用数据类型介绍 3. Redis常用命令3.1 字符串操作命令3.2 哈希操作…

Docker-Nvidia(NVIDIA Container Toolkit)

安装NVIDIA Container Toolkit工具&#xff0c;支持docker使用GPU 目录 1.NVIDIA Container Toolkit 安装1.1 nvidia-docker安装1.2 验证1.2.1 验证安装1.2.2 额外补充 1.NVIDIA Container Toolkit 安装 1.1 nvidia-docker安装 NVIDIA/nvidia-docker Installing the NVIDIA …

SQL Server Query Store Settings (查询存储设置)

参考&#xff1a;Query Store Settings - Erin Stellato 在 SQL Server 2017 中&#xff0c;有九 (9) 个设置与查询存储相关。虽然这些设置记录在sys.database_query_store_options中&#xff0c;但我经常被问到每个设置的值“应该”是多少。我在下面列出了每个设置&am…

AI数字人直播源码解析:灰豚私有化部署背后的技术分析

随着AI数字人技术的应用潜力不断显现&#xff0c;与AI数字人相关的多个项目逐渐成为创业者们的重点关注对象&#xff0c;作为当前AI数字人典型应用场景之一的数字人直播意向人数更是屡创新高&#xff0c;AI数字人直播源码部署的热度也因此不断飙升&#xff0c;与各大数字人源码…

Centos7 安装私有 Gitlab

在 CentOS 7上&#xff0c;下面的命令也会在系统防火墙中打开 HTTP、HTTPS 和 SSH 访问。这是一个可选步骤&#xff0c;如果您打算仅从本地网络访问极狐GitLab&#xff0c;则可以跳过它。 sudo yum install -y curl policycoreutils-python openssh-server perl sudo systemct…

昇思25天学习打卡营第20天|应用实践之RNN实现情感分类

基本介绍 今天的应用实践是RNN实现情感分类&#xff0c;情感分类是自然语言处理中的经典任务&#xff0c;是典型的分类问题。RNN是一种循环神经网络&#xff0c;接收序列数据作为输入。模型训练所采用的数据集是IMDB影评数据集&#xff0c;数据集包含Positive和Negative两类。由…

数据库基础-进阶

数据库管理&#xff1a; *sql语句 数据库用来增删改查的语句 *** 备份 数据库的数据进行备份 * 主从复制&#xff0c;读写分离&#xff0c;高可用 原理 数据库的概念和相关的语法和规范&#xff1a; 数据库&#xff1a;组织&#xff0c;存储&#xff0c;管理数据的仓库。 数据…

cpp 强制转换

一、static_cast static_cast 是 C 中的一个类型转换操作符&#xff0c;用于在类的层次结构中进行安全的向上转换&#xff08;从派生类到基类&#xff09;或进行不需要运行时类型检查的转换。它主要用于基本数据类型之间的转换、对象指针或引用的向上转换&#xff08;即从派生…

使用phpMyAdmin操作MYSQL(四)

一. 学会phpMyAdmin&#xff1f; phpMyAdminhttp://water.ve-techsz.cn/phpmyadmin/ 虽然我我们可以用命令行操作数据库&#xff0c;但这样难免没有那么直观&#xff0c;方便。所以接下来我们使用phpMyAdmin来操作MySQL&#xff0c;phpMyAdmin是众多MySQL图形化管理工具中使用…

编程从零基础到进阶(更新中)

题目描述 依旧是输入三个整数&#xff0c;要求按照占8个字符的宽度&#xff0c;并且靠左对齐输出 输入格式 一行三个整数&#xff0c;空格分开 输出格式 输出它们按格式输出的效果&#xff0c;占一行 样例输入 123456789 -1 10 样例输出 123456789-1 10 #include "stdio.…

2024年7月20日(星期六)骑行支里山

2024年7月20日 (星期六&#xff09;骑行支里山&#xff0c;早8:00到8:30&#xff0c;大观公园门口集合&#xff0c;9:00准时出发【因迟到者&#xff0c;骑行速度快者&#xff0c;可自行追赶偶遇。】 偶遇地点:大观公园门口集合 &#xff0c;家住东&#xff0c;南&#xff0c;北…

【数据结构】树和二叉树及堆的深入理解

【数据结构】树和二叉树及堆的深入理解 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;数据结构 文章目录 【数据结构】树和二叉树及堆的深入理解前言一.树1.1 树的概念1.2 树的相关概念1.3 树的表示1.4 树的应用 二.二叉树2.1 二叉树概念及…

智慧煤矿:AI视频智能监管解决方案引领行业新变革

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经渗透到各个行业&#xff0c;为传统产业的转型升级提供了强大的动力。在煤矿行业中&#xff0c;安全监管一直是一个重要的议题。为了提高煤矿的安全生产水平&#xff0c;降低事故发生率&#xff0c;智…

ubuntu 虚拟机扩容

在使用vmware创建的ubuntu虚拟机进行linux开发时&#xff0c;安装了docker容器&#xff0c;编译会占用很大的磁盘空间&#xff0c;不想创建新的更大空间的虚拟机linux系统&#xff0c;可以通过gparted图形化工具进行扩容&#xff0c;以下是操作方法 虚拟机设置&#xff0c;扩展…