2023.7.15排序算法合集

news2024/12/26 11:08:37

排序算法合集

  • 一、概述
  • 二、排序算法
    • 1.冒泡排序
    • 2.插入排序
    • 3.选择排序
    • 4.快速排序
    • 5.归并排序
    • 6.计数排序
  • 三、完整源码


一、概述

  排序算法是计算机科学中的一类常见算法,用于将一组数据按照特定的顺序进行排列;排序算法的应用非常广泛,涉及到数据处理、搜索算法、数据库操作等众多领域。常见的排序算法有以下几种:

  1. 冒泡排序(Bubble Sort)
  2. 插入排序(Insertion Sort)
  3. 选择排序(Selection Sort)
  4. 快速排序(Quick Sort)
  5. 归并排序(Merge Sort)
  6. 堆排序(Heap Sort)
  7. 希尔排序(Shell Sort)
  8. 计数排序(Counting Sort)
  9. 桶排序(Bucket Sort)
  10. 基数排序(Radix Sort)

奈何本人技术不太行,对于树和堆的理解不够透彻,所以涉及到这两种数据结构的排序算法可能要以后再补充


二、排序算法

文章使用 Java语言 进行演示,使用 int数据 类型作为示范,操作的数据结构均以 数组 为准,排序的结果为 从小到大 排列,同时提供随机初始化数据的方法

相关的全局变量和初始化数据方法如下

    public static int number;//用例数据量
    public static int[] nums;//用例数组
    
    /**
     * 用例随机初始化
     * @param number 用例数据量
     * @param start  用例起始范围
     * @param end    用例结束范围
     */
    public static void initNums(int number, int start, int end) {
        nums = new int[number];
        for (int i = 0; i < nums.length; i++) {
            nums[i] = (int) (Math.random() * (end - start + 1) + start);
        }
    }

1.冒泡排序

  冒泡排序是一种简单直观的排序算法,它通过依次比较相邻的元素,并在必要时交换位置,使得每一轮循环后最大(或最小)的元素浮到序列的末尾。冒泡排序的过程可以描述如下:

  1. 从列表的第一个元素开始,依次比较相邻的两个元素。如果前一个元素大于(或小于)后一个元素,则交换它们的位置,使较大(或较小)的元素“冒泡”到后面
  2. 继续对剩余的元素进行相邻比较和交换操作,直到将最大(或最小)的元素移动到列表的最后位置
  3. 对除去最后一个元素的剩余列表重复上述步骤,每次循环将会确定一个最大(或最小)的元素到达正确的位置
  4. 重复上述步骤,直到整个列表排序完成

冒泡排序

    /**
     * 冒泡排序:从左到右逐个比较相邻的元素,并进行交换,每一轮将最大的元素移到最右侧
     */
    public static void bubbleSort() {
        int[] bubbleSortNums = nums.clone();
        for (int i = 1; i < bubbleSortNums.length; i++) {
            for (int j = 0; j < bubbleSortNums.length - i; j++) {
                if (bubbleSortNums[j] > bubbleSortNums[j + 1]) {//已经确保两个数不相同,所以异或不会丢失数据
                    bubbleSortNums[j] ^= bubbleSortNums[j + 1];
                    bubbleSortNums[j + 1] ^= bubbleSortNums[j];
                    bubbleSortNums[j] ^= bubbleSortNums[j + 1];
                }
            }
        }
        System.out.print("冒泡排序: ");
        System.out.println(Arrays.toString(bubbleSortNums));
    }

冒泡排序的时间复杂度为O(N2),其中N为待排序元素的数量


2.插入排序

  插入排序是一种简单直观的排序算法,它的工作原理类似于整理扑克牌的过程。插入排序的基本思想是将待排序的元素逐个插入到已经排序的序列中的正确位置,从而逐步构建有序序列。下面是插入排序的步骤:

  1. 将列表的第一个元素视为已排序序列
  2. 从第二个元素开始,逐个将元素插入到已排序序列的正确位置。插入时,将当前元素与已排序序列中的元素从后向前逐个比较,直到找到合适的位置插入
  3. 重复上述步骤,直到将所有元素插入到正确的位置。

插入排序

    /**
     * 插入排序:逐个将元素插入到已排序的序列中的正确位置,构建最终有序序列
     */
    public static void insertSort() {
        int[] insertSortNums = nums.clone();
        int temp = 0;//记录待插入的值
        int index = 0;//记录插入的位置
        boolean isFlag;
        for (int i = 1; i < insertSortNums.length; i++) {
            isFlag = false;
            for (int j = 0; j < i; j++) {
                if (insertSortNums[i] < insertSortNums[j]) {
                    index = j;
                    temp = insertSortNums[i];
                    isFlag = true;
                    break;
                }
            }
            if (isFlag) {//当需要向前插入的时候才执行,否则不用移动
                System.arraycopy(insertSortNums, index, insertSortNums, index + 1, i - index);
//                for (int j = i; j > index; j--) {
//                    insertSortNums[j] = insertSortNums[j - 1];
//                }
                insertSortNums[index] = temp;
            }
        }
        System.out.print("插入排序: ");
        System.out.println(Arrays.toString(insertSortNums));
    }

插入排序的时间复杂度为O(N2),其中N为待排序元素的数量


3.选择排序

  选择排序是一种简单直观的排序算法,其基本思想是每一次从待排序的元素中选择最小(或最大)的元素,放置在已排序序列的末尾,从而逐步构建有序序列。选择排序的步骤如下:

  1. 遍历待排序序列,将第一个元素标记为当前最小(或最大)元素
  2. 从剩余的未排序元素中依次找到最小(或最大)的元素,与当前最小(或最大)元素进行比较
  3. 如果找到比当前最小(或最大)元素更小(或更大)的元素,则更新当前最小(或最大)元素的位置
  4. 继续遍历剩余的未排序元素,重复上述步骤,直到将所有元素排序完成
  5. 重复上述过程,直到所有元素都被排序

选择排序

    /**
     * 选择排序:每一轮从未排序的部分选择最小(或最大)的元素,放到已排序部分的末尾
     */
    public static void selectSort() {
        int[] selectionSortNums = nums.clone();
        for (int i = 0; i < selectionSortNums.length - 1; i++) {//计数
            int maxNum = 0;//记录极大值的索引
            for (int j = 0; j < selectionSortNums.length - i; j++) {
                if (selectionSortNums[maxNum] < selectionSortNums[j]) {
                    maxNum = j;
                }
            }
            //下面的if是用异或交换元素的重点,防止置0
            if (maxNum != selectionSortNums.length - i - 1) {//如果已经在对应位置就不需要移动,否则会导致异或同一个变量置0
                selectionSortNums[maxNum] ^= selectionSortNums[selectionSortNums.length - i - 1];
                selectionSortNums[selectionSortNums.length - i - 1] ^= selectionSortNums[maxNum];
                selectionSortNums[maxNum] ^= selectionSortNums[selectionSortNums.length - i - 1];
            }
        }
        System.out.print("选择排序: ");
        System.out.println(Arrays.toString(selectionSortNums));
    }

选择排序的时间复杂度为O(N2),其中N为待排序元素的数量


4.快速排序

  快速排序是一种高效的排序算法,它采用分治法的思想。快速排序的基本思想是选择一个基准元素,将待排序序列划分为左右两个子序列,其中左边子序列的元素都小于等于基准元素,右边子序列的元素都大于等于基准元素,然后递归地对左右子序列进行排序,最终得到有序序列。快速排序的步骤如下:

  1. 选择一个基准元素(通常是列表的第一个或最后一个元素)
  2. 遍历整个序列,将小于等于基准元素的元素放到左边,大于等于基准元素的元素放到右边,形成两个子序列
  3. 递归地对左右子序列进行快速排序
  4. 将左子序列、基准元素、右子序列按照顺序连接起来,得到最终的有序序列

快速排序(双指针法)动画演示


快速排序(双指针法)动画演示

    /**
     * 快速排序:选择一个基准元素,将数组分为小于基准值和大于基准值的两部分,递归地对这两部分进行排序(默认首元素为基准)
     */
    public static void quickSort() {
        int[] quickSortNums = nums.clone();
        quick(quickSortNums, 0, quickSortNums.length - 1);
        System.out.print("快速排序: ");
        System.out.println(Arrays.toString(quickSortNums));
    }

    /**
     * 快速排序:选择一个基准元素,将数组分为小于基准值和大于基准值的两部分,递归地对这两部分进行排序(默认首元素为基准)
     * @param quickSortNums 待排序数组
     * @param start 左起点
     * @param end 右起点
     */
    public static void quick(int[] quickSortNums, int start, int end) {
        if (start < end) {//直到序列内只有一个元素时,无需排序,结束递归
            int left = start;
            int right = end;
            int pivotIndex = start;//基准元素的索引值(选择第一个元素作为基准元素)
            //寻找基轴位置
            while (left < right) {
                //右侧扫描
                while (left < right && quickSortNums[right] >= quickSortNums[pivotIndex]) {//找到第一个小于基准的元素
                    right--;
                }//和基轴交换位置
                if (left < right) {//保证小于基准的元素在右侧
                    quickSortNums[right] ^= quickSortNums[pivotIndex];
                    quickSortNums[pivotIndex] ^= quickSortNums[right];
                    quickSortNums[right] ^= quickSortNums[pivotIndex];
                    pivotIndex = right;
                }
                //左侧扫描
                while (left < right && quickSortNums[left] <= quickSortNums[pivotIndex]) {//找到第一个大于基准的元素
                    left++;
                }//和基轴交换位置
                if (left < right) {//保证大于基准的元素在左侧
                    quickSortNums[left] ^= quickSortNums[pivotIndex];
                    quickSortNums[pivotIndex] ^= quickSortNums[left];
                    quickSortNums[left] ^= quickSortNums[pivotIndex];
                    pivotIndex = left;
                }
            }
            //左右子序列递归排序
            quick(quickSortNums, start, pivotIndex - 1);
            quick(quickSortNums, pivotIndex + 1, end);
        }
    }

快速排序的时间复杂度为O(NlogN),其中N为待排序元素的数量


5.归并排序

  归并排序是一种高效的排序算法,它采用分治法的思想。归并排序的基本思想是将待排序序列分成两个较小的子序列,递归地对子序列进行排序,然后将两个有序子序列合并成一个有序序列。以下是归并排序的算法实现步骤:

  1. 分解:将待排序序列递归地分解为两个较小的子序列,直到每个子序列只剩下一个元素或为空
  2. 合并:将两个有序子序列合并成一个有序序列。比较两个子序列的首个元素,将较小的元素放入临时的辅助数组中,并将相应子序列的指针向后移动,重复此过程,直到两个子序列中的元素全部放入辅助数组中
  3. 将辅助数组中的有序序列复制回原始序列的对应位置
  4. 递归地对两个子序列重复上述步骤,直到整个序列排序完成

归并排序

    /**
     * 归并排序:将数组递归地分成两半,对每个子数组进行排序,然后将两个有序子数组合并成一个有序数组
     */
    public static void mergeSort() {
        int[] mergeSortNums = nums.clone();
        merge(mergeSortNums, 0, mergeSortNums.length - 1);
        System.out.print("归并排序: ");
        System.out.println(Arrays.toString(mergeSortNums));
    }

    /**
     * 归并排序:将数组递归地分成两半,对每个子数组进行排序,然后将两个有序子数组合并成一个有序数组
     * @param mergeSortNums 子序列
     * @param start 子序列起点
     * @param end 子序列终点
     */
    public static void merge(int[] mergeSortNums, int start, int end) {
        if (start < end) {
            int middle = (end - start) / 2 + start;
            merge(mergeSortNums, start, middle);
            merge(mergeSortNums, middle + 1, end);
            //合并两个子序列,暂存到临时数组
            int num = start;
            int i = start;
            int j = middle + 1;
            int[] temp = new int[mergeSortNums.length];
            while (i <= middle && j <= end) {
                if (mergeSortNums[i] <= mergeSortNums[j]) {
                    temp[num++] = mergeSortNums[i++];
                } else {
                    temp[num++] = mergeSortNums[j++];
                }
            }
            while (i <= middle) {
                temp[num++] = mergeSortNums[i++];
            }
            while (j <= end) {
                temp[num++] = mergeSortNums[j++];
            }
            //拷贝回初始数组
            System.arraycopy(temp, start, mergeSortNums, start, end - start + 1);
        }
    }

归并排序的时间复杂度为O(NlogN),其中N为待排序元素的数量


6.计数排序

  计数排序是一种非比较的排序算法,它通过统计待排序序列中每个元素出现的次数,进而确定每个元素在有序序列中的位置。计数排序适用于待排序序列中的元素都是非负整数,并且元素的范围相对较小的情况。计数排序的步骤如下:

  1. 找出待排序序列中的最大元素,并确定计数数组的大小。计数数组的大小为最大元素值加1
  2. 统计待排序序列中每个元素出现的次数,并将统计结果存储在计数数组中。计数数组的下标表示元素的值,数组中存储的值表示该元素出现的次数
  3. 对计数数组进行顺序求和操作。将计数数组中的每个元素与前一个元素相加,得到每个元素在有序序列中的最后位置的索引
  4. 创建一个与待排序序列大小相同的辅助数组
  5. 从后往前遍历待排序序列,根据元素的值找到其在计数数组中对应的索引,将元素放入辅助数组中的正确位置
  6. 将辅助数组中的元素复制回原始序列,完成排序。

计数排序

    /**
     * 计数排序:对每个输入元素进行计数,然后根据计数值的顺序重构有序数组
     * @param start 数据左起始范围
     * @param end 数据右起始范围
     */
    public static void countSort(int start, int end) {
        int[] countSortNums = nums.clone();
        int[][] numCount = new int[Math.abs(start) + Math.abs(end) + 1][2];//计数
        int temp = start;
        for (int i = 0; i < numCount.length; i++) {
            numCount[i][0] = temp++;
        }
        for (int i = 0; i < countSortNums.length; i++) {
            numCount[countSortNums[i] + Math.abs(start)][1]++;
        }
        int index = 0;
        int indexNum = 0;
        for (int i = 0; i < numCount.length; i++) {
            if (numCount[i][1] != 0 && indexNum != 0) {
                numCount[i][1] += numCount[index][1];
                index = i;
            } else if (numCount[i][1] != 0 && indexNum == 0) {
                indexNum++;
                index = i;
            }
        }//计算排序位置
        int left = 0;
        int right = -1;
        for (int j = 0; j < numCount.length; j++) {
            if (numCount[j][1] != 0) {
                right = numCount[j][1];
                for (int i = left; i < right; i++) {
                    countSortNums[i] = numCount[j][0];
                }
                left = right;
            }
        }
        System.out.print("计数排序: ");
        System.out.println(Arrays.toString(countSortNums));
    }

三、完整源码

package Yskysoar;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author Yskysoar
 * @createTime 2023-07-12 19:29
 * @description 排序算法
 * 1.所有测试对象为数组、链表或者树,默认为数组
 * 2.提供用例随机初始化方法
 * 3.排序结果从小到大排列
 */
public class SortAlgorithm {
    public static int number;//用例数据量
    public static int[] nums;//用例数组

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入数据量,数据起点,数据终点:");
        number = scanner.nextInt();
        int start = scanner.nextInt();
        int end = scanner.nextInt();
//        nums = new int[] {3, 8, 10, 5, 10, 10, 3, 4, 2, 9};
        initNums(number, start, end);
        System.out.print("初始数据: ");
        System.out.println(Arrays.toString(nums));
        //冒泡排序
        bubbleSort();
        //选择排序
        selectSort();
        //插入排序
        insertSort();
        //快速排序
        quickSort();
        //归并排序
        mergeSort();
        //计数排序
        countSort(start, end);
    }

    /**
     * 用例随机初始化
     * @param number 用例数据量
     * @param start  用例起始范围
     * @param end    用例结束范围
     */
    public static void initNums(int number, int start, int end) {
        nums = new int[number];
        for (int i = 0; i < nums.length; i++) {
            nums[i] = (int) (Math.random() * (end - start + 1) + start);
        }
    }

    /**
     * 冒泡排序:从左到右逐个比较相邻的元素,并进行交换,每一轮将最大的元素移到最右侧
     */
    public static void bubbleSort() {
        int[] bubbleSortNums = nums.clone();
        for (int i = 1; i < bubbleSortNums.length; i++) {
            for (int j = 0; j < bubbleSortNums.length - i; j++) {
                if (bubbleSortNums[j] > bubbleSortNums[j + 1]) {//已经确保两个数不相同,所以异或不会丢失数据
                    bubbleSortNums[j] ^= bubbleSortNums[j + 1];
                    bubbleSortNums[j + 1] ^= bubbleSortNums[j];
                    bubbleSortNums[j] ^= bubbleSortNums[j + 1];
                }
            }
        }
        System.out.print("冒泡排序: ");
        System.out.println(Arrays.toString(bubbleSortNums));
    }

    /**
     * 选择排序:每一轮从未排序的部分选择最小(或最大)的元素,放到已排序部分的末尾
     */
    public static void selectSort() {
        int[] selectionSortNums = nums.clone();
        for (int i = 0; i < selectionSortNums.length - 1; i++) {//计数
            int maxNum = 0;//记录极大值的索引
            for (int j = 0; j < selectionSortNums.length - i; j++) {
                if (selectionSortNums[maxNum] < selectionSortNums[j]) {
                    maxNum = j;
                }
            }
            //下面的if是用异或交换元素的重点,防止置0
            if (maxNum != selectionSortNums.length - i - 1) {//如果已经在对应位置就不需要移动,否则会导致异或同一个变量置0
                selectionSortNums[maxNum] ^= selectionSortNums[selectionSortNums.length - i - 1];
                selectionSortNums[selectionSortNums.length - i - 1] ^= selectionSortNums[maxNum];
                selectionSortNums[maxNum] ^= selectionSortNums[selectionSortNums.length - i - 1];
            }
        }
        System.out.print("选择排序: ");
        System.out.println(Arrays.toString(selectionSortNums));
    }

    /**
     * 插入排序:逐个将元素插入到已排序的序列中的正确位置,构建最终有序序列
     */
    public static void insertSort() {
        int[] insertSortNums = nums.clone();
        int temp = 0;//记录待插入的值
        int index = 0;//记录插入的位置
        boolean isFlag;
        for (int i = 1; i < insertSortNums.length; i++) {
            isFlag = false;
            for (int j = 0; j < i; j++) {
                if (insertSortNums[i] < insertSortNums[j]) {
                    index = j;
                    temp = insertSortNums[i];
                    isFlag = true;
                    break;
                }
            }
            if (isFlag) {//当需要向前插入的时候才执行,否则不用移动
                /*
                public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
                src:源数组
                srcPos:源数组要复制的起始位置
                dest:目的数组
                destPos:目的数组放置的起始位置
                length:复制的长度
                 */
                System.arraycopy(insertSortNums, index, insertSortNums, index + 1, i - index);
//                for (int j = i; j > index; j--) {
//                    insertSortNums[j] = insertSortNums[j - 1];
//                }
                insertSortNums[index] = temp;
            }
        }
        System.out.print("插入排序: ");
        System.out.println(Arrays.toString(insertSortNums));
    }

    /**
     * 快速排序:选择一个基准元素,将数组分为小于基准值和大于基准值的两部分,递归地对这两部分进行排序(默认首元素为基准)
     */
    public static void quickSort() {
        int[] quickSortNums = nums.clone();
        quick(quickSortNums, 0, quickSortNums.length - 1);
        System.out.print("快速排序: ");
        System.out.println(Arrays.toString(quickSortNums));
    }

    /**
     * 快速排序:选择一个基准元素,将数组分为小于基准值和大于基准值的两部分,递归地对这两部分进行排序(默认首元素为基准)
     * @param quickSortNums 待排序数组
     * @param start 左起点
     * @param end 右起点
     */
    public static void quick(int[] quickSortNums, int start, int end) {
        if (start < end) {//直到序列内只有一个元素时,无需排序,结束递归
            int left = start;
            int right = end;
            int pivotIndex = start;//基准元素的索引值(选择第一个元素作为基准元素)
            //寻找基轴位置
            while (left < right) {
                //右侧扫描
                while (left < right && quickSortNums[right] >= quickSortNums[pivotIndex]) {//找到第一个小于基准的元素
                    right--;
                }//和基轴交换位置
                if (left < right) {//保证小于基准的元素在右侧
                    quickSortNums[right] ^= quickSortNums[pivotIndex];
                    quickSortNums[pivotIndex] ^= quickSortNums[right];
                    quickSortNums[right] ^= quickSortNums[pivotIndex];
                    pivotIndex = right;
                }
                //左侧扫描
                while (left < right && quickSortNums[left] <= quickSortNums[pivotIndex]) {//找到第一个大于基准的元素
                    left++;
                }//和基轴交换位置
                if (left < right) {//保证大于基准的元素在左侧
                    quickSortNums[left] ^= quickSortNums[pivotIndex];
                    quickSortNums[pivotIndex] ^= quickSortNums[left];
                    quickSortNums[left] ^= quickSortNums[pivotIndex];
                    pivotIndex = left;
                }
            }
            //左右子序列递归排序
            quick(quickSortNums, start, pivotIndex - 1);
            quick(quickSortNums, pivotIndex + 1, end);
        }
    }

    /**
     * 归并排序:将数组递归地分成两半,对每个子数组进行排序,然后将两个有序子数组合并成一个有序数组
     */
    public static void mergeSort() {
        int[] mergeSortNums = nums.clone();
        merge(mergeSortNums, 0, mergeSortNums.length - 1);
        System.out.print("归并排序: ");
        System.out.println(Arrays.toString(mergeSortNums));
    }

    /**
     * 归并排序:将数组递归地分成两半,对每个子数组进行排序,然后将两个有序子数组合并成一个有序数组
     * @param mergeSortNums 子序列
     * @param start 子序列起点
     * @param end 子序列终点
     */
    public static void merge(int[] mergeSortNums, int start, int end) {
        if (start < end) {
            int middle = (end - start) / 2 + start;
            merge(mergeSortNums, start, middle);
            merge(mergeSortNums, middle + 1, end);
            //合并两个子序列,暂存到临时数组
            int num = start;
            int i = start;
            int j = middle + 1;
            int[] temp = new int[mergeSortNums.length];
            while (i <= middle && j <= end) {
                if (mergeSortNums[i] <= mergeSortNums[j]) {
                    temp[num++] = mergeSortNums[i++];
                } else {
                    temp[num++] = mergeSortNums[j++];
                }
            }
            while (i <= middle) {
                temp[num++] = mergeSortNums[i++];
            }
            while (j <= end) {
                temp[num++] = mergeSortNums[j++];
            }
            //拷贝回初始数组
            System.arraycopy(temp, start, mergeSortNums, start, end - start + 1);
        }
    }

    /**
     * 计数排序:对每个输入元素进行计数,然后根据计数值的顺序重构有序数组
     * @param start 数据左起始范围
     * @param end 数据右起始范围
     */
    public static void countSort(int start, int end) {
        int[] countSortNums = nums.clone();
        int[][] numCount = new int[Math.abs(start) + Math.abs(end) + 1][2];//计数
        int temp = start;
        for (int i = 0; i < numCount.length; i++) {
            numCount[i][0] = temp++;
        }
        for (int i = 0; i < countSortNums.length; i++) {
            numCount[countSortNums[i] + Math.abs(start)][1]++;
        }
        int index = 0;
        int indexNum = 0;
        for (int i = 0; i < numCount.length; i++) {
            if (numCount[i][1] != 0 && indexNum != 0) {
                numCount[i][1] += numCount[index][1];
                index = i;
            } else if (numCount[i][1] != 0 && indexNum == 0) {
                indexNum++;
                index = i;
            }
        }//计算排序位置
        int left = 0;
        int right = -1;
        for (int j = 0; j < numCount.length; j++) {
            if (numCount[j][1] != 0) {
                right = numCount[j][1];
                for (int i = left; i < right; i++) {
                    countSortNums[i] = numCount[j][0];
                }
                left = right;
            }
        }
        System.out.print("计数排序: ");
        System.out.println(Arrays.toString(countSortNums));
    }
}

本人技术水平一般,各位大佬如果发现我的不足之处或者有好的建议可以指出,谢谢大家


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

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

相关文章

代码随想录第三十九天||● 62.不同路径 ● 63. 不同路径 II

● 62.不同路径 这道题注意&#xff1a;初始化不仅是可以初始化一个值&#xff0c;也可以初始化整个一行或者一列值 这道题递推公式好想&#xff0c;就是初始化不太好想 机器人从(0 , 0) 位置出发&#xff0c;到(m - 1, n - 1)终点。 按照动规五部曲来分析&#xff1a; 确…

用 pesq 给 torchaudio 读取的音频数据打分

用torchaudio读取的音频文件&#xff0c;在输入pesq之前需要进行格式处理与转换。 import torchaudio from pesq import pesq# 读取音频文件 audio_clean, src torchaudio.load(./audio/NOIZEUS/clean/sp01.wav) audio_0dB, sr0 torchaudio.load(./audio/NOIZEUS/bable/0dB/…

算法:动态规划

目录 &#x1f349;什么是动态规划&#xff1f; 1&#xff09;题目解析&#xff0c;&#xff08;我们以第N个泰波那契数来进行举例&#xff09; 2&#xff09;解读算法原理 &#x1f349;第N个泰波那契数的代码编写 &#x1f349;空间优化 &#x1f349;什么是动态规划&am…

全国青少年信息素养大赛参赛练习题2

海龟画图: 漂亮的螺旋线 import turtle as tt.bgcolor("black") n=6 colors = [red, green, blue, yellow,orange,purple]for x in range(160):t.pencolor(colors[x%6])t.forward(x*5/n+x)t.left(360/n+1)t.width(x*n/200) t.up() t.left(-90) t.forward(50) t.d…

什么是番茄工作法?

基本概念 番茄工作法是由弗朗西斯科西里洛于1992年创立的一种相对于GTD更微观的时间管理方法&#xff0c;旨在帮助使用者尽可能保持专注以及创造力&#xff0c;从而更快地完成工作并减少心理疲劳。 使用番茄工作法&#xff0c;首先要选择一个待完成的任务&#xff0c;然后将番茄…

5.2 Python高级特性之---切片迭代

一、 切片 一般用于提取指定区间内的内容&#xff0c;常用于&#xff1a;str、list、tuple等类型的的局部变量&#xff0c;如下为具体案例1、 【列表切片】 res_list [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]1&#xff09; 无步长: …

Redis的数据淘汰策略了解吗?

面试官&#xff1a;Redis数据淘汰策略了解吗&#xff1f; 我&#xff1a;知道。嗯~~ 当Redis中的内存不够用时&#xff0c;此时再向Redis中添加新的key&#xff0c;Redis就会按照某种规则将内存中的数据删除掉。这种数据的删除规则被称为内存的淘汰策略。 面试官&#xff1a;…

【机器学习】吴恩达课程1-Introduction

一、机器学习 1. 定义 计算机程序从经验E中学习&#xff0c;解决某一任务T&#xff0c;进行某一性能P&#xff0c;通过P测定在T上的表现因经验E而提高。 2. 例子 跳棋程序 E&#xff1a;程序自身下的上万盘棋局 T&#xff1a;下跳棋 P&#xff1a;与新对手下跳棋时赢的概…

深度强化学习经验回放(Experience Replay Buffer)的三点高性能修改建议:随机采样、减少保存的数据量、简化计算等

高性能的 ReplayBuffer 应该满足以下三点: 随机采样 random sample 的速度要快,尽可能加快读取速度(最为重要)减少保存的数据量,增加吞吐效率(对分布式而言重要)保存能简化计算的变量(对特定算法而言重要)为了达成以上要求,我建议做出以下修改: 把 Replay Buffer 的…

【从零到Offer】反射那些事

什么是反射&#xff1f; ​ 反射简单来说&#xff0c;就是在代码运行期间&#xff0c;通过动态指定任意一个类&#xff0c;从而构建对象&#xff0c;并了解该类的成员变量和方法&#xff0c;甚至可以调用任意一个对象的属性和方法。以String对象为例子&#xff0c;传统构造方式…

Go语言开发者的Apache Arrow使用指南:数据操作

在前面的Arrow系列文章中&#xff0c;我们介绍了Arrow的基础数据类型[1]以及高级数据类型[2]&#xff0c;这让我们具备了在内存中建立起一个immutable数据集的能力。但这并非我们的目标&#xff0c;我们最终是要对建立起来的数据集进行查询和分析等操作(manipulation)的。 在这…

RecycleView闪屏问题(java和ktolin解决)

问题案例&#xff1a;图库搜索界面点击空格&#xff0c;图片会闪烁两次显示 复现概率 通过布局看是通过RecycleView加载的&#xff0c;通过打印log并无异常闪烁是 notifyDataSetChange 造成的。由于适配器不知道整个数据集中的哪些内容已经存在&#xff0c;在重新匹配 ViewHol…

vscode remote-ssh配置

使用vscode的插件remote-ssh进行linux的远程控制。 在vscode上安装完remote-ssh插件后&#xff0c;还需要安装openssh-client。 openssh-client安装 先win R打开cmd&#xff0c;输入ssh&#xff0c;查看是否已经安装了。 如果没有安装&#xff0c;用管理员权限打开powershe…

LabVIEW将彩色图像转换到灰度图像

LabVIEW将彩色图像转换到灰度图像 在LabVIEW中使用许多图像处理工具的必要步骤之一是将其从彩色转换为单色。介绍一个开发的应用程序&#xff0c;用于基于LabVIEW软件环境&#xff0c;在所有支持的色彩空间&#xff08;RGB、HSI、HSV和HSL&#xff09;中自动将彩色图像转换为灰…

Shi-Tomas角点检测、亚像素级别角点位置优化、ORB特征点、特征点匹配、RANSAC优化特征点匹配、相机模型与投影

目录 1、Shi-Tomas角点检测 2、亚像素级别角点位置优化 3、ORB特征点 4、特征点匹配 5、RANSAC优化特征点匹配 6、相机模型与投影 1、Shi-Tomas角点检测 //Shi-Tomas角点检测 int test1() {Mat img imread("F:/testMap/lena.png");if (!img.data){cout <<…

Python结巴中文分词笔记

&#x1f4da; jieba库基本介绍 &#x1f310; jieba库概述 Jieba是一个流行的中文分词库&#xff0c;它能够将中文文本切分成词语&#xff0c;并对每个词语进行词性标注。中文分词是自然语言处理的重要步骤之一&#xff0c;它对于文本挖掘、信息检索、情感分析等任务具有重要…

2023年Java最新面试题

由【后端面试题宝典】提供 和 equals 的区别是什么&#xff1f; 对于基本类型&#xff0c;比较的是值&#xff1b;对于引用类型&#xff0c;比较的是地址&#xff1b;equals不能用于基本类型的比较&#xff1b;如果没有重写equals&#xff0c;equals就相当于&#xff1b;如果重…

带记忆的Transformer模块

MEMORIZING TRANSFORMERS 返回论文和资料目录 论文地址 1.导读 谷歌去年做的一个工作。内容很简单&#xff0c;在Transformer模块中加入了一层记忆层&#xff0c;结果表明这个方法可以帮助模型提高在NLP任务上的表现&#xff1a;generic webtext (C4), math papers (arXiv),…

C# IEnumerator 用法

一、概述 IEnumerator 是所有非泛型枚举器的基接口。 其泛型等效项是 System.Collections.Generic.IEnumerator<T> 接口。 C# 语言的 foreach 语句&#xff08;在 Visual Basic 中为 for each&#xff09;隐藏了枚举数的复杂性。 因此&#xff0c;建议使用 foreach 而不…