当前位置: 首页 > news >正文

数据结构第20节 快速排序以及优化

快速排序是一种非常高效的排序算法,由英国计算机科学家托尼·霍尔(Tony Hoare)在1960年代发明。它使用分治法(Divide and Conquer)策略来把一个序列分为较小的部分,然后递归地排序这些部分。

快速排序的基本步骤:

  1. 选择基准值(Pivot Selection):从序列中选择一个元素作为基准值。通常选择序列的第一个、最后一个或中间的元素,也可以随机选择。
  2. 分区操作(Partitioning):重新排列序列,使得所有小于基准值的元素都位于基准值的左边,所有大于基准值的元素都位于基准值的右边。完成这个操作后,基准值就位于最终排序后的位置。
  3. 递归排序子序列:递归地对基准值左边和右边的子序列应用快速排序算法。

分区操作细节:

  • 设置两个指针 leftrightleft 指针从序列的起始位置开始,right 指针从序列的结束位置开始。
  • 移动 right 指针,直到找到一个小于或等于基准值的元素。
  • 移动 left 指针,直到找到一个大于或等于基准值的元素。
  • 如果 left 指针在 right 指针的左边,交换两个指针所指向的元素。
  • 重复上述步骤,直到 leftright 指针相遇或交叉。
  • 当指针交叉时,将基准值与 right 指针所指向的元素交换,完成分区操作。

Java代码实现:

下面是一个简单的快速排序算法的Java实现:

public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {// pi is partitioning index, arr[pi] is now at right placeint pi = partition(arr, low, high);// Recursively sort elements before and after partitionquickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}}private static int partition(int[] arr, int low, int high) {int pivot = arr[high]; // pivotint i = (low - 1); // Index of smaller elementfor (int j = low; j < high; j++) {// If current element is smaller than the pivotif (arr[j] < pivot) {i++;// swap arr[i] and arr[j]int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// swap arr[i+1] and arr[high] (or pivot)int temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return i + 1;}// Function to print an arraypublic static void printArray(int[] arr) {for (int value : arr) {System.out.print(value + " ");}System.out.println();}public static void main(String[] args) {int[] arr = {10, 7, 8, 9, 1, 5};int n = arr.length;quickSort(arr, 0, n - 1);System.out.println("Sorted array:");printArray(arr);}
}

时间复杂度:

  • 最佳和平均情况:O(n log n)
  • 最差情况:O(n^2),当输入数组已经是排序好的或逆序的,基准值每次都是最小或最大值。

空间复杂度:

  • O(log n),由于递归调用栈的空间。

快速排序在实际应用中非常广泛,尤其是在大规模数据集上,因为它能够提供非常好的性能。然而,在某些情况下,例如数据已经接近排序的情况下,快速排序的性能可能会退化,这时可以考虑使用其他排序算法,如堆排序或归并排序。

要优化快速排序算法,我们可以采取几种不同的策略来提高其效率和稳定性。以下是一些常见的改进方法:

  1. 三数取中法(Median-of-three)选择基准值
    在选择基准值时,使用数组的第一个元素、中间元素和最后一个元素中的中位数作为基准值,这有助于避免最坏情况的发生,特别是在数组已经部分排序的情况下。

  2. 插入排序小数组
    对于小规模的子数组,使用插入排序替换快速排序。插入排序在小数组上的性能通常优于快速排序,因为它的常数因子较小。

  3. 尾递归优化
    可以优化递归调用,减少栈空间的使用。具体来说,你可以先递归处理较大的子数组,然后迭代处理较小的子数组,或者使用循环结构替代递归。

  4. 非递归版本
    使用显式栈来模拟递归调用,这样可以避免系统调用栈的开销。

下面是使用三数取中法和插入排序小数组的优化版快速排序示例代码:

public class OptimizedQuickSort {public static void quickSort(int[] arr, int low, int high) {while (low < high) {// Partition and get the partition index.int pi = partition(arr, low, high);// Recursively sort the left part, but only if it's larger than the right.if (pi - low < high - pi) {quickSort(arr, low, pi - 1);low = pi + 1;} else {quickSort(arr, pi + 1, high);high = pi - 1;}}}private static int partition(int[] arr, int low, int high) {// Median-of-three pivot selectionint mid = (low + high) / 2;if (arr[mid] > arr[high]) {swap(arr, mid, high);}if (arr[low] > arr[high]) {swap(arr, low, high);}if (arr[mid] > arr[low]) {swap(arr, mid, low);}int pivot = arr[low];int i = low + 1;int j = high;while (true) {while (i <= j && arr[i] <= pivot) {i++;}while (i <= j && arr[j] >= pivot) {j--;}if (i <= j) {swap(arr, i, j);} else {break;}}swap(arr, low, j);return j;}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void insertionSort(int[] arr, int low, int high) {for (int i = low + 1; i <= high; i++) {int key = arr[i];int j = i - 1;while (j >= low && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}}public static void main(String[] args) {int[] arr = {10, 7, 8, 9, 1, 5};int n = arr.length;// Optimize: Use insertion sort for small subarraysfor (int i = 0; i < n; i += 16) {insertionSort(arr, i, Math.min((i + 15), (n - 1)));}quickSort(arr, 0, n - 1);System.out.println("Sorted array:");for (int value : arr) {System.out.print(value + " ");}System.out.println();}
}

在这个优化版本中,我们使用了三数取中法来选择更合理的基准值,并且对于小于16个元素的小数组使用插入排序进行排序。此外,我们还通过循环结构代替递归来减少栈的使用。这些修改可以帮助提高快速排序在各种情况下的性能和稳定性。

尾递归优化

尾递归优化是指在递归函数中,如果递归调用是函数执行的最后一个操作,那么可以通过一些技巧将其转换为迭代,从而避免栈溢出的风险和减少递归调用的开销。对于快速排序而言,可以优先递归处理较小的子数组,然后返回处理较大的子数组,这样可以保证递归深度不会过大。

下面是一个利用尾递归优化的快速排序Java实现示例:

public class TailRecursiveQuickSort {public static void quickSort(int[] arr, int low, int high) {while (low < high) {// Partitioning indexint pi = partition(arr, low, high);// Recursively sort elements before partition and after partitionif (pi - low < high - pi) {// Sort the smaller part firstquickSort(arr, low, pi - 1);// Update the range for the larger partlow = pi + 1;} else {// Sort the larger part firstquickSort(arr, pi + 1, high);// Update the range for the smaller parthigh = pi - 1;}}}private static int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = (low - 1); // index of smaller elementfor (int j = low; j < high; j++) {// If current element is smaller than or equal to pivotif (arr[j] <= pivot) {i++;// swap arr[i] and arr[j]int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// swap arr[i+1] and arr[high] (or pivot)int temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return i + 1;}public static void main(String[] args) {int[] arr = {10, 7, 8, 9, 1, 5};int n = arr.length;quickSort(arr, 0, n - 1);System.out.println("Sorted array:");for (int value : arr) {System.out.print(value + " ");}System.out.println();}
}

在这个版本中,quickSort 函数使用了一个循环来处理子数组的排序。在每次循环中,它首先对当前的子数组进行分区操作,然后根据左右两部分的大小决定先递归处理哪一部分。这样做可以确保每次递归调用之后,剩余需要处理的子数组的大小总是比前一次小,从而减少了递归的深度。

然而,值得注意的是,尽管这种优化减少了递归调用的次数,但在最坏情况下,如果每次分区都偏向一侧,递归深度仍然可能较大。因此,结合其他优化策略,如三数取中法选择基准值,可以进一步提高算法的稳定性和性能。

为了进一步提高快速排序的稳定性和性能,可以结合多种优化策略。以下是几种常见的改进方法:

  1. 三数取中法选择基准值:选取第一个、中间的和最后一个元素中的中值作为基准值,以减少最坏情况的发生。

  2. 插入排序小数组:对于小规模的子数组,使用插入排序。插入排序在小数组上的效率高于快速排序。

  3. 随机化基准值选择:随机选择数组中的一个元素作为基准值,可以避免最坏情况的发生,尤其是当数组已部分排序时。

  4. 双路快速排序(Dual-Pivot QuickSort):同时使用两个基准值,可以减少比较和交换的次数,从而提高性能。

  5. 尾递归优化:减少递归调用的深度,使用循环结构替代递归。

  6. 并行化:利用多核处理器的优势,使用并行计算技术对子数组进行排序。

下面是一个结合了三数取中法、插入排序小数组和尾递归优化的快速排序Java实现:

public class OptimizedQuickSort {private static final int INSERTION_SORT_THRESHOLD = 16; // 阈值用于插入排序public static void quickSort(int[] arr, int low, int high) {while (low < high) {// 使用三数取中法选择基准值int pivotIndex = medianOfThree(arr, low, high);int pivot = arr[pivotIndex];// 将基准值放到最后swap(arr, pivotIndex, high);// Partitioning indexint pi = partition(arr, low, high);// Recursively sort elements before partition and after partitionif (pi - low < high - pi) {// Sort the smaller part firstquickSort(arr, low, pi - 1);// Update the range for the larger partlow = pi + 1;} else {// Sort the larger part firstquickSort(arr, pi + 1, high);// Update the range for the smaller parthigh = pi - 1;}}}private static int medianOfThree(int[] arr, int low, int high) {int mid = (low + high) >>> 1; // 使用无符号右移获得中间索引if (arr[mid] > arr[high]) {swap(arr, mid, high);}if (arr[low] > arr[high]) {swap(arr, low, high);}if (arr[mid] > arr[low]) {swap(arr, mid, low);}return low; // 返回中位数的索引}private static int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = low - 1;for (int j = low; j < high; j++) {if (arr[j] <= pivot) {i++;swap(arr, i, j);}}swap(arr, i + 1, high);return i + 1;}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void insertionSort(int[] arr, int low, int high) {for (int i = low + 1; i <= high; i++) {int key = arr[i];int j = i - 1;while (j >= low && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}}public static void main(String[] args) {int[] arr = {10, 7, 8, 9, 1, 5};int n = arr.length;// 使用插入排序处理小数组for (int i = 0; i < n; i += INSERTION_SORT_THRESHOLD) {insertionSort(arr, i, Math.min(i + INSERTION_SORT_THRESHOLD - 1, n - 1));}// 使用快速排序处理大数组quickSort(arr, 0, n - 1);System.out.println("Sorted array:");for (int value : arr) {System.out.print(value + " ");}System.out.println();}
}

这个版本的快速排序算法结合了多种优化策略,提高了排序的性能和稳定性。在实际应用中,根据数据的特点和环境的限制,还可以尝试其他的优化策略以达到最佳效果。例如,对于大规模数据集,可以考虑使用并行快速排序来充分利用多核处理器的能力。

在Java中,利用并行流(parallel streams)或java.util.concurrent包中的工具可以实现并行快速排序。这里,我将展示如何使用Fork/Join框架来实现并行快速排序。

Fork/Join框架是Java 7引入的一种并行编程模型,它允许任务被分割成更小的任务,然后并行执行。在快速排序中,我们可以将大的数组分割成小的子数组,并在不同的线程上并行地对它们进行排序。

下面是一个使用Fork/Join框架的并行快速排序实现:

import java.util.Arrays;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.ForkJoinPool;public class ParallelQuickSort {public static void main(String[] args) {int[] arr = new int[1_000_000];// 初始化数组...for (int i = 0; i < arr.length; i++) {arr[i] = (int)(Math.random() * 1000);}long startTime = System.currentTimeMillis();ForkJoinPool pool = new ForkJoinPool();pool.invoke(new SortTask(arr, 0, arr.length - 1));long endTime = System.currentTimeMillis();System.out.println("Sorting took " + (endTime - startTime) + " ms");// 检查排序是否正确boolean isSorted = true;for (int i = 1; i < arr.length; i++) {if (arr[i] < arr[i - 1]) {isSorted = false;break;}}System.out.println("Is sorted: " + isSorted);}static class SortTask extends RecursiveAction {private final int[] arr;private final int low;private final int high;public SortTask(int[] arr, int low, int high) {this.arr = arr;this.low = low;this.high = high;}@Overrideprotected void compute() {if (low < high) {int pi = partition(arr, low, high);invokeAll(new SortTask(arr, low, pi - 1), new SortTask(arr, pi + 1, high));}}private int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = (low - 1); // index of smaller elementfor (int j = low; j < high; j++) {// If current element is smaller than or equal to pivotif (arr[j] <= pivot) {i++;// swap arr[i] and arr[j]int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// swap arr[i+1] and arr[high] (or pivot)int temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return i + 1;}}
}

在上述代码中,SortTask继承自RecursiveAction类,这是Fork/Join框架中的一个抽象类,用于表示一个可并行执行的任务。compute方法定义了任务的执行逻辑。当一个SortTask实例被创建并提交给ForkJoinPool时,它会根据子任务的大小决定是继续分割任务还是直接执行。如果任务足够小,它将直接进行排序;如果任务足够大,它将被分割成更小的子任务,并在多个线程上并行执行。

这种方法特别适用于多核处理器,因为它能有效利用所有可用的CPU核心。但是,对于较小的数据集,由于启动额外线程的开销,传统的单线程排序可能会更快。因此,在实际应用中,你可能还需要调整任务分割的阈值,以找到最适合特定硬件配置的平衡点。

优化后的非递归版本的快速排序算法通常使用显式栈来模拟递归调用的行为,从而避免了递归调用带来的栈溢出风险以及函数调用的开销。下面是一个使用显式栈的非递归快速排序算法的Java实现:

import java.util.ArrayDeque;
import java.util.Deque;public class NonRecursiveQuickSort {public static void quickSort(int[] arr) {Deque<Integer> stack = new ArrayDeque<>();stack.push(0);stack.push(arr.length - 1);while (!stack.isEmpty()) {int high = stack.pop();int low = stack.pop();int pivotIndex = partition(arr, low, high);if (pivotIndex - 1 > low) {stack.push(low);stack.push(pivotIndex - 1);}if (pivotIndex + 1 < high) {stack.push(pivotIndex + 1);stack.push(high);}}}private static int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = low - 1;for (int j = low; j < high; j++) {if (arr[j] <= pivot) {i++;swap(arr, i, j);}}swap(arr, i + 1, high);return i + 1;}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 = {10, 7, 8, 9, 1, 5};quickSort(arr);System.out.println("Sorted array:");for (int value : arr) {System.out.print(value + " ");}System.out.println();}
}

在这个实现中,我们使用了一个双向队列ArrayDeque作为栈,用于存储待处理的子数组的边界。quickSort函数初始化栈,然后在一个循环中不断弹出栈顶的高边界和低边界,进行分区操作,并根据分区结果更新栈的内容,直到栈为空为止。

这种非递归的方法可以有效地减少内存栈的使用,避免了在递归深度过深时可能出现的栈溢出问题,同时也能保持快速排序的高效性能。在实际应用中,你可以根据具体需求调整分区策略、基准值的选择方法等,以进一步优化排序过程。

相关文章:

数据结构第20节 快速排序以及优化

快速排序是一种非常高效的排序算法&#xff0c;由英国计算机科学家托尼霍尔&#xff08;Tony Hoare&#xff09;在1960年代发明。它使用分治法&#xff08;Divide and Conquer&#xff09;策略来把一个序列分为较小的部分&#xff0c;然后递归地排序这些部分。 快速排序的基本…...

3分钟理解超键、候选键、主键

1.超键 在关系模式中&#xff0c;能唯一标识实体实例的任何属性集 学生&#xff08;学号&#xff0c;姓名&#xff0c;性别&#xff0c;专业编号&#xff0c;年龄&#xff09; 通过学号可以找到一个学生的姓名、性别、专业号、年龄&#xff0c;但是通过姓名不一定能找到这些…...

Centos忘记密码,重置root密码

Centos忘记密码&#xff0c;重置root密码 操作环境&#xff1a;Centos7.6 1、选择包含rescue的选项&#xff0c;按e进入编辑模式 首先&#xff0c;我们需要重启系统&#xff0c;进入开机引导菜单界面。在这里&#xff0c;我们可以看到系统的内核版本和启动参数等信息。我们需…...

Android初学者书籍推荐

书单 1.《Android应用开发项目式教程》&#xff0c;机械工业出版社&#xff0c;2024年出版2.《第一行代码Android》第二版3.《第一行代码Android》第三版4.《疯狂Android讲义》第四版5.《Android移动应用基础教程&#xff08;Android Studio 第2版&#xff09;》 从学安卓到用安…...

安卓文件上传照片单张及多张照片上传实现

一、首先导入对应库 //网络请求库 implementation com.squareup.okhttp3:okhttp:3.9.0//Gson解析 implementation com.google.code.gson:gson:2.10.1 二、然后就是们实现上传方法 UploaderTool.java import android.util.Log;import com.google.gson.Gson;import java.io.File…...

小白学webgl合集-import.meta.url 和 new URL() bug

为什么使用 import.meta.url 和 new URL() 动态路径解析&#xff1a; 在 ESM&#xff08;ECMAScript Modules&#xff09;环境中&#xff0c;import.meta.url 提供了当前模块的完整 URL。结合 new URL()&#xff0c;你可以基于这个 URL 动态解析其他资源的路径。这样可以确保路…...

pico+unity3d开启彩色透视

1、点击游戏对象、点击XR、点击添加XR Origin&#xff0c;并把自带的摄像对象删除 2、添加脚本 using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.XR.PXR;//引入xr对象 public class toushi : MonoBehaviour {// Start is called…...

python常用命令

文章目录 1. 安装模块 1. 安装模块 pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple (切换数据源&#xff09;...

使用定时器消除抖动

问题&#xff1a;定时器中断和按键中断属于什么操作模式&#xff0c;轮询吗&#xff1f; 具体怎么实现 定时器中断 &#xff08;判断&#xff09; 时间参数 按键中断&#xff08;修改&#xff09; 中断 向量表.s文件 DCD SysTick_Handler …...

IOS热门面试题一

GCD&#xff08;Grand Central Dispatch&#xff09;是什么&#xff1f;如何在iOS中使用它&#xff1f; GCD&#xff08;Grand Central Dispatch&#xff09;是什么&#xff1f; GCD&#xff08;Grand Central Dispatch&#xff09;是苹果公司开发的一套多线程编程的API&…...

构建LangChain应用程序的示例代码:62、如何使用Oracle AI向量搜索和Langchain构建端到端的RAG(检索增强生成)pipeline

Oracle AI 向量搜索与文档处理 Oracle AI向量搜索专为人工智能(AI)工作负载设计&#xff0c;允许您基于语义而非关键词来查询数据。 Oracle AI向量搜索的最大优势之一是可以在单一系统中结合对非结构化数据的语义搜索和对业务数据的关系搜索。 这不仅功能强大&#xff0c;而且…...

ffmpeg转换MP4为gif命令

这里记录一下使用 ffmpeg去转化 gif 的一些快捷命令 # 直接转换 ffmpeg -i 222.mp4 -r 12 222.gif# 调色板优化处理 ffmpeg -i 222.mp4 -r 12 -vf "split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" 222.gif第二条命令的解释如下&#xff1a; split[s0][s1]&am…...

kotlin Flow 学习指南 (三)最终篇

目录 前言Flow生命周期StateFlow 替代LiveDataSharedFlow其他常见应用场景处理复杂、耗时逻辑存在依赖关系的接口请求组合多个接口的数据 Flow使用注意事项总结 前言 前面两篇文章&#xff0c;介绍了Flow是什么&#xff0c;如何使用&#xff0c;以及相关的操作符进阶&#xff…...

Memcached负载均衡:揭秘高效缓存分发策略

标题&#xff1a;Memcached负载均衡&#xff1a;揭秘高效缓存分发策略 在分布式缓存系统中&#xff0c;Memcached通过负载均衡技术来提高缓存效率和系统吞吐量。负载均衡确保了缓存请求能够均匀地分配到多个缓存节点上&#xff0c;从而防止任何一个节点过载。本文将深入探讨Me…...

【Python实战因果推断】31_双重差分2

目录 Canonical Difference-in-Differences Diff-in-Diff with Outcome Growth Canonical Difference-in-Differences 差分法的基本思想是&#xff0c;通过使用受治疗单位的基线&#xff0c;但应用对照单位的结果&#xff08;增长&#xff09;演变&#xff0c;来估算缺失的潜…...

ArcGIS中使用线快速构造成面的方法

准备工作&#xff1a;一个需要转化为面的封闭线&#xff1b;一个处于可编辑状态的面要素文件。 1.选中一个围合封闭成的线 2.点击高级编辑工具中的构造面小工具 3.弹出对话框&#xff0c;直接点确定即可 4.效果如下图&#xff1a; 特别注意&#xff1a;记得要把面图层编辑功能…...

Spring AOP的几种实现方式

1.通过注解实现 1.1导入依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.1.6.RELEASE</version></dependency> 1.2定义注解 import java.lang.annotation.*;Targ…...

字节码编程bytebuddy之实现抽象类并并添加自定义注解

写在前面 本文看下使用bytebuddy如何实现抽象类&#xff0c;并在子类中添加自定义注解。 1&#xff1a;代码 1.1&#xff1a;准备基础代码 类和方法注解 package com.dahuyou.bytebuddy.cc.mine;import java.lang.annotation.ElementType; import java.lang.annotation.Re…...

LLM-阿里云 DashVector + ModelScope 多模态向量化实时文本搜图实战总结

文章目录 前言步骤图片数据Embedding入库文本检索 完整代码 前言 本文使用阿里云的向量检索服务&#xff08;DashVector&#xff09;&#xff0c;结合 ONE-PEACE多模态模型&#xff0c;构建实时的“文本搜图片”的多模态检索能力。整体流程如下&#xff1a; 多模态数据Embedd…...

CentOS7安装部署git和gitlab

安装Git 在Linux系统中是需要编译源码的&#xff0c;首先下载所需要的依赖&#xff1a; yum install -y curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker方法一 下载&#xff1a; wget https://mirrors.edge.kernel.org/pub/s…...

《昇思25天学习打卡营第16天|基于MindNLP+MusicGen生成自己的个性化音乐》

MindNLP 原理 MindNLP 是一个自然语言处理&#xff08;NLP&#xff09;框架&#xff0c;用于处理和分析文本数据。 文本预处理&#xff1a;包括去除噪声、分词、词性标注、命名实体识别等步骤&#xff0c;使文本数据格式化并准备好进行进一步分析。 特征提取&#xff1a;将文…...

算法学习day10(贪心算法)

贪心算法&#xff1a;由局部最优->全局最优 贪心算法一般分为如下四步&#xff1a; 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 一、摆动序列&#xff08;理解难&#xff09; 连续数字之间的差有正负的交替&…...

卡尔曼滤波Kalman Filter零基础入门到实践(上部)

参考视频&#xff1a;入门&#xff08;秒懂滤波概要&#xff09;_哔哩哔哩_bilibili 一、入门 1.引入 假设超声波距离传感器每1ms给单片机发数据。 理论数据为黑点&#xff0c; 测量数据曲线为红线&#xff0c;引入滤波后的数据为紫线 引入滤波的作用是过滤数据中的噪声&a…...

力扣-dfs

何为深度优先搜索算法&#xff1f; 深度优先搜索算法&#xff0c;即DFS。就是找一个点&#xff0c;往下搜索&#xff0c;搜索到尽头再折回&#xff0c;走下一个路口。 695.岛屿的最大面积 695. 岛屿的最大面积 题目 给你一个大小为 m x n 的二进制矩阵 grid 。 岛屿 是由一些相…...

keepalived高可用集群

一、keepalived&#xff1a; 1.keepalive是lvs集群中的高可用架构&#xff0c;只是针对调度器的高可用&#xff0c;基于vrrp来实现调度器的主和备&#xff0c;也就是高可用的HA架构&#xff1b;设置一台主调度器和一台备调度器&#xff0c;在主调度器正常工作的时候&#xff0…...

文献翻译与阅读《Integration Approaches for Heterogeneous Big Data: A Survey》

CYBERNETICS AND INFORMATION TECHNOLOGIES’24 论文原文下载地址&#xff1a;原文下载 目录 1 引言 2 大数据概述 3 大数据的异构性 4 讨论整合方法 4.1 大数据仓库&#xff08;BDW&#xff09; 4.2 大数据联盟&#xff08;BDF&#xff09; 5 DW 和 DF 方法的比较、分…...

应用最优化方法及MATLAB实现——第3章代码实现

一、概述 在阅读最优方法及MATLAB实现后&#xff0c;想着将书中提供的代码自己手敲一遍&#xff0c;来提高自己对书中内容理解程度&#xff0c;巩固一下。 这部分内容主要针对第3章的内容&#xff0c;将其所有代码实现均手敲一遍&#xff0c;中间部分代码自己根据其公式有些许的…...

django的增删改查,排序,分组等常用的ORM操作

Django 的 ORM&#xff08;对象关系映射&#xff09;提供了一种方便的方式来与数据库进行交互。 1. Django模型 在 myapp/models.py 中定义一个示例模型&#xff1a;python from django.db import modelsclass Person(models.Model):name models.CharField(max_length100)age…...

Leetcode Java学习记录——树、二叉树、二叉搜索树

文章目录 树的定义树的遍历中序遍历代码 二叉搜索树 常见二维数据结构&#xff1a;树/图 树和图的区别就在于有没有环。 树的定义 public class TreeNode{public int val;public TreeNode left,right;public TreeNode(int val){this.val val;this.left null;this.right nu…...

华为HCIP Datacom H12-821 卷30

1.单选题 以下关于OSPF协议报文说法错误的是? A、OSPF报文采用UDP报文封装并且端口号是89 B、OSPF所有报文的头部格式相同 C、OSPF协议使用五种报文完成路由信息的传递 D、OSPF所有报文头部都携带了Router-ID字段 正确答案:A 解析: OSPF用IP报文直接封装协议报文,…...