常见的排序算法整理

1.冒泡排序

1.1 冒泡排序普通版

每次冒泡过程都是从数列的第一个元素开始,然后依次和剩余的元素进行比较,若小于相邻元素,则交换两者位置,同时将较大元素作为下一个比较的基准元素,继续将该元素与其相邻的元素进行比较,直到数列的最后一个元素 .(最后的元素最大,也是最先固定)

import java.util.Arrays;

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = new int[]{9, 2, 1, 0, 5, 3, 6, 4, 8, 7};

        System.out.println("排序前:" + Arrays.toString(arr));

        sort(arr);

        System.out.println("排序后:" + Arrays.toString(arr));

    }

    // 冒泡排序方法
    public static void sort(int[] arr) {
        // 第一层for循环,用来控制冒泡的次数
        for (int i = 1; i < arr.length; i++) {
            // 第二层for循环,用来控制冒泡一层层到最后
            for (int j = 0; j < arr.length - 1; j++) {
                // 如果前一个数比后一个数大,两者调换,意味着泡泡向上走了一层
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j]; // 临时变量temp用来交换两个数值
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

运行结果:

排序前:[9, 2, 1, 0, 5, 3, 6, 4, 8, 7]

排序后:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

1.2 冒泡排序升级版

在这个版本中,改动了两点 . 第一点是加入了一个布尔值,判断第二层循环中的调换有没有执行,如果没有进行两两调换,说明后面都已经排好序了,已经不需要再循环了,直接跳出循环,排序结束 ; 第二点是第二层循环不再循环到arr.length - 1,因为外面的i循环递增一次,说明数组最后就多了一个排好序的大泡泡.第二层循环也就不需要到最末尾一位了,可以提前结束循环

/**

  • 升级版冒泡排序:

  • 加入一个布尔变量,如果内循环没有交换值,说明已经排序完成,提前终止

*/

import java.util.Arrays;

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = new int[]{9, 2, 1, 0, 5, 3, 6, 4, 8, 7};
        
        System.out.println("排序前:" + Arrays.toString(arr));
        
        plusSort(arr);
        
        System.out.println("排序后:" + Arrays.toString(arr));  
    }
    
    // 升级版冒泡排序方法
    public static void plusSort(int[] arr) {
        if (arr != null && arr.length > 1) {
            for (int i = 0; i < arr.length - 1; i++) {
                // 初始化一个布尔值,用于标记此次循环内是否进行了交换操作
                boolean flag = true;
                
                for (int j = 0; j < arr.length - i - 1; j++) {
                    if (arr[j] > arr[j + 1]) {
                        // 交换arr[j]与arr[j+1]的值
                        int temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                        
                        // 改变flag的值,表示进行了交换操作
                        flag = false;
                    }
                }
                
                // 如果flag为true,表示在此次循环中没有进行交换操作,即已经完成了排序,提前终止外层循环
                if (flag) {
                    break;
                }
            }
        }
    }
}

运行结果:

排序前:[9, 2, 1, 0, 5, 3, 6, 4, 8, 7]

排序后:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

2.选择排序

选择排序也是一种简单直观的排序算法,实现原理比较直观易懂:首先在未排序数列中找到最小元素,然后将其与数列的首部元素进行交换,然后,在剩余未排序元素中继续找出最小元素,将其与已排序数列的末尾位置元素交换。以此类推,直至所有元素都排序完毕

/**

  • 选择排序:

  • 每一次从待排序的数据元素中选出最小(或最大)的一个元素,

  • 存放在序列的起始位置,直到全部待排序的数据元素排完。

*/

import java.util.Arrays;

public class SelectSort {
    public static void main(String[] args) {
        int[] arr = new int[] {3, 4, 5, 7, 1, 2, 0, 9, 3, 6, 8}; // 待排序的数组

        System.out.println("排序前:" + Arrays.toString(arr)); // 输出排序前的数组

        selectSort(arr); // 调用选择排序方法

        System.out.println("排序后:" + Arrays.toString(arr)); // 输出排序后的数组
    }

    // 选择排序方法
    public static void selectSort(int[] arr) {
        // 外层循环控制当前需要进行比较的元素索引位置
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i; // 设定当前循环的起始位置为最小值的位置

            // 内层循环寻找未排序部分中的最小值的索引
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[minIndex] > arr[j]) {
                    minIndex = j; // 如果当前位置的值比起始位置的值小,则更新最小值的索引
                }
            }

            // 如果找到最小值的索引与当前循环位置不同,则交换两个位置的值,将最小值交换至当前位置
            if (i != minIndex) {
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
    }
}

运行结果:

排序前:[3, 4, 5, 7, 1, 2, 0, 9, 3, 6, 8]

排序后:[0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9]

3.插入排序

一次插入排序的操作过程:将待插元素,依次与已排序好的子数列元素从后到前进行比较,如果当前元素值比待插元素值大,则将移位到与其相邻的后一个位置,否则直接将待插元素插入当前元素相邻的后一位置,因为说明已经找到插入点的最终位置(类似于打牌)

/**

  • 插入排序:

  • 从第一个元素开始,该元素可以认为已经被排序

  • 取出下一个元素,在已经排序的元素序列中从后向前扫描

  • 如果该元素(已排序)大于新元素,将该元素移到下一位置

  • 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置

  • 将新元素插入到该位置后

  • 重复上面步骤

*/

import java.util.Arrays;

public class InsertSort {
    public static void main(String[] args) {
        int[] arr = new int[] {5, 3, 2, 8, 4, 9, 1, 0, 7, 6}; // 待排序的数组

        System.out.println("排序前:" + Arrays.toString(arr)); // 输出排序前的数组

        insertSort(arr); // 调用插入排序方法

        System.out.println("排序后:" + Arrays.toString(arr)); // 输出排序后的数组
    }

    // 插入排序方法
    public static void insertSort(int[] arr) {
        // 外层循环控制插入的元素索引位置
        for (int i = 1; i < arr.length; i++) {
            int temp = arr[i]; // 保存当前需要插入的元素值
            int j;

            // 内层循环比较并将元素插入到正确的位置
            for (j = i - 1; j >= 0 && temp < arr[j]; j--) {
                arr[j + 1] = arr[j]; // 将元素往后移动
            }

            arr[j + 1] = temp; // 将当前元素插入到正确位置
        }
    }
}

运行结果:

排序前:[5, 3, 2, 8, 4, 9, 1, 0, 7, 6]

排序后:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

4.快速排序

快速排序算法利用的是一趟快速排序,基本内容是选择一个数作为准基数,然后利用这个准基数将遗传数据分为两个部分,第一部分比这个准基数小,都放在准基数的左边,第二部分都比这个准基数大,放在准基数的右边.

import java.util.Arrays;

/**

  • 快速排序:

  • 快速排序算法利用的是一趟快速排序,基本内容是选择一个数作为准基数,

  • 然后利用这个准基数将遗传数据分为两个部分,第一部分比这个准基数小,

  • 都放在准基数的左边,第二部分都比这个准基数大,放在准基数的右边.

*/

public class QuickSort {
    public static void main(String[] args) {
        int[] arr = new int[] {5, 3, 2, 8, 4, 9, 1, 0, 7, 6}; // 待排序的数组

        System.out.println("排序前:" + Arrays.toString(arr)); // 输出排序前的数组

        quickSort(arr, 0, arr.length - 1); // 调用快速排序方法

        System.out.println("排序后:" + Arrays.toString(arr)); // 输出排序后的数组
    }

    /**
     * 快速排序方法
     * @param arr 待排序的数组
     * @param begin 排序起始位置
     * @param end 排序结束位置
     */
    public static void quickSort(int[] arr, int begin, int end) {
        // 递归终止条件:起始位置大于等于结束位置
        if (begin >= end) {
            return;
        }

        int pivot = arr[begin]; // 选择基准元素,默认以第一个元素为基准
        int left = begin + 1; // 左边起始位置
        int right = end; // 右边结束位置

        while (left <= right) {
            /**
             * 在左边找到第一个大于基准元素的位置
             * 注意:这里要先判断left <= right,否则会导致索引越界
             */
            while (left <= right && arr[left] <= pivot) {
                left++;
            }

            /**
             * 在右边找到第一个小于基准元素的位置
             * 注意:这里要先判断left <= right,否则会导致索引越界
             */
            while (left <= right && arr[right] >= pivot) {
                right--;
            }

            // 如果左指针仍在右指针左边,则交换左、右指针所指的元素
            if (left < right) {
                swap(arr, left, right);
            }
        }

        // 将基准元素交换到正确的位置,即左指针所在位置
        swap(arr, begin, right);

        // 对左边部分进行快速排序
        quickSort(arr, begin, right - 1);

        // 对右边部分进行快速排序
        quickSort(arr, right + 1, end);
    }

    /**
     * 交换数组中两个元素的位置
     * @param arr 数组
     * @param i 第一个元素的索引
     * @param j 第二个元素的索引
     */
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

运行结果:

排序前:[5, 3, 2, 8, 4, 9, 1, 0, 7, 6]

排序后:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

5.归并排序

归并排序,简单的说把一串数,从中平等分为两份,再把两份再细分,直到不能细分为止,这就是分而治之的分的步骤. 再从最小的单元,两两合并,合并的规则是将其按从小到大的顺序放到一个临时数组中,再把这个临时数组替换原数组相应位置

import java.util.Arrays;

/**

  • 归并排序:

  • 归并操作的工作原理如下:

  • 第一步:申请空间,使其大小为两个已经 排序序列之和,该空间用来存放合并后的序列

  • 第二步:设定两个 指针,最初位置分别为两个已经排序序列的起始位置

  • 第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置重复步骤3直到某一指针超出序列尾

  • 将另一序列剩下的所有元素直接复制到合并序列尾

*

*/

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = new int[] {5, 3, 2, 8, 4, 9, 1, 0, 7, 6}; // 待排序的数组

        System.out.println("排序前:" + Arrays.toString(arr)); // 输出排序前的数组

        mergeSort(arr, 0, arr.length - 1); // 调用归并排序方法

        System.out.println("排序后:" + Arrays.toString(arr)); // 输出排序后的数组
    }

    /**
     * 归并排序方法
     * @param a 待排序的数组
     * @param s 排序起始位置
     * @param e 排序结束位置
     */
    public static void mergeSort(int[] a, int s, int e) {
        if (s < e) {
            int m = (s + e) / 2; // 找到数组的中间位置

            mergeSort(a, s, m); // 递归调用对左边部分进行归并排序
            mergeSort(a, m + 1, e); // 递归调用对右边部分进行归并排序

            merge(a, s, m, e); // 合并左右两个有序数组
        }
    }

    /**
     * 合并左右两个有序数组
     * @param a 原始数组
     * @param s 左数组起始位置
     * @param m 左数组结束位置
     * @param e 右数组结束位置
     */
    private static void merge(int[] a, int s, int m, int e) {
        int[] temp = new int[e - s + 1]; // 临时数组用来存放合并后的结果

        int l = s; // 左数组的起始位置
        int r = m + 1; // 右数组的起始位置
        int i = 0; // 临时数组的索引

        // 比较左右两个数组中的元素,将较小的元素放入临时数组中
        while (l <= m && r <= e) {
            if (a[l] < a[r]) {
                temp[i++] = a[l++];
            } else {
                temp[i++] = a[r++];
            }
        }

        // 将左数组中剩余的元素放入临时数组中
        while (l <= m) {
            temp[i++] = a[l++];
        }

        // 将右数组中剩余的元素放入临时数组中
        while (r <= e) {
            temp[i++] = a[r++];
        }

        // 将临时数组中的元素覆盖原始数组中的元素,完成排序
        for (int n = 0; n < temp.length; n++) {
            a[s + n] = temp[n];
        }
    }
}

运行结果:

排序前:[5, 3, 2, 8, 4, 9, 1, 0, 7, 6]

排序后:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

6.希尔排序

当数组规模较大时,插入排序的效率较低。希尔排序(Shell Sort)是一种插入排序的改进算法,通过将相隔一定间隔的元素进行分组,对每个分组进行插入排序,逐步缩小间隔,最终完成排序。

具体步骤如下:

1. 首先,选定一个初始的间隔值(称为步长),通常将数组长度的一半作为初始值。
2. 根据选定的步长,将数组分成若干个分组。
3. 对每个分组进行插入排序,即将每个分组中的元素按照插入排序的方式进行排序。
4. 缩小步长,继续第2和第3步操作,直到步长为1。
5. 当步长为1时,进行最后一次插入排序,此时数组已经基本有序,插入排序的效率会很高。

希尔排序的关键在于选定合适的步长和分组方式。常用的步长序列有希尔原始提出的递减系列(n/2, n/4, n/8...),以及Hibbard系列(2^k - 1, 2^(k-1) - 1...),Sedgewick系列等。

希尔排序的时间复杂度与步长序列的选取有关,最好的情况下为O(n^(3/2)),平均情况下为O(nlogn)。希尔排序是一种不稳定的排序算法,即相同元素的相对顺序在排序后可能发生变化。

希尔排序相对于插入排序来说,虽然没有改变算法的基本思想,但通过拆分成多个子序列进行插入排序,大大提高了排序的效率。

import java.util.Arrays;

public class ShellSort {
    public static void main(String[] args) {
        int[] arr = new int[] {5, 3, 2, 8, 4, 9, 1, 0, 7, 6}; // 待排序的数组

        System.out.println("排序前:" + Arrays.toString(arr)); // 输出排序前的数组

        shellSort(arr); // 调用希尔排序方法

        System.out.println("排序后:" + Arrays.toString(arr)); // 输出排序后的数组
    }

    /**
     * 希尔排序方法
     * @param arr 待排序的数组
     */
    public static void shellSort(int[] arr) {
        int gap = arr.length / 2; // 初始步长

        int k = 1; // 记录排序轮数

        // 根据步长进行分组,对每个分组进行插入排序
        while (gap > 0) {
            // 对每个分组进行插入排序
            for (int i = gap; i < arr.length; i++) {
                // 对当前分组的元素进行插入排序
                for (int j = i - gap; j >= 0; j -= gap) {
                    if (arr[j] > arr[j + gap]) {
                        // 如果前一个元素大于后一个元素,则进行交换
                        int temp = arr[j];
                        arr[j] = arr[j + gap];
                        arr[j + gap] = temp;
                    }
                }
            }

            System.out.println("第" + k++ + "轮排序结果:" + Arrays.toString(arr));

            gap /= 2; // 缩小步长
        }
    }
}

运行结果:

排序前:[5, 3, 2, 8, 4, 9, 1, 0, 7, 6]

[5, 1, 0, 7, 4, 9, 3, 2, 8, 6]

[0, 1, 3, 2, 4, 6, 5, 7, 8, 9]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

排序后:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

7.基数排序

基数排序(Radix Sort)是一种非比较性的稳定排序算法,它将整数按照每个位上的数字进行排序,可以根据位数进行排序,依次按个位、十位、百位...从低位到高位进行排序。基数排序适用于排序非负整数或具有相同位数的正整数序列。

具体步骤如下:

1. 找到数组中的最大值,并确定最大值的位数,作为排序的轮数。
2. 从个位开始,根据当前位上的数字将元素分配到对应的桶中。
3. 按照分配的顺序重新排列数组。
4. 继续处理十位、百位...直到处理完最高位,完成排序。

基数排序要求具备一定的稳定性,即在同一位上相同数字的先后顺序不发生改变。

以下是带有详细注释的基数排序的Java代码示例:```java

 

import java.util.*;

public class RadixSort {
    public static void radixSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }

        // 获取数组中的最大值
        int max = Arrays.stream(arr).max().getAsInt();
        
        // 计算最大值的位数,决定排序的轮数
        int exp = 1;
        while (max / exp > 0) {
            countingSort(arr, exp);
            exp *= 10;
        }
    }

    // 对数组按照某一位上的值进行计数排序
    private static void countingSort(int[] arr, int exp) {
        int n = arr.length;
        int[] output = new int[n];
        int[] count = new int[10];

        // 统计该位上每个数字的出现次数
        for (int num : arr) {
            count[(num / exp) % 10]++;
        }

        // 将计数数组转换为位置索引数组
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }

        // 按照该位上的值将元素放入output数组中
        for (int i = n - 1; i >= 0; i--) {
            output[count[(arr[i] / exp) % 10] - 1] = arr[i];
            count[(arr[i] / exp) % 10]--;
        }

        // 将排序好的数组赋值给原数组
        System.arraycopy(output, 0, arr, 0, n);
    }

    public static void main(String[] args) {
        int[] arr = {170, 45, 75, 90, 802, 24, 2, 66};
        System.out.println("排序前:" + Arrays.toString(arr));

        radixSort(arr);

        System.out.println("排序后:" + Arrays.toString(arr));
    }
}

这段代码实现了带有详细注释的基数排序算法。在基数排序过程中,首先找到数组中的最大值,然后逐个按位进行计数排序。最后,将排序好的数组赋值给原数组。基数排序的时间复杂度为O(d*(n+b)),其中d为最大值的位数,n为数组长度,b为基数(这里是10)。基数排序是一种稳定的排序算法,适用于整数排序。

运行结果:

排序前:[5, 3, 2, 8, 4, 9, 1, 0, 7, 6]

排序后:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

8.堆排序

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点

堆排序(Heap Sort)是一种基于完全二叉树数据结构——堆的排序算法,它利用堆的性质进行排序。堆排序首先将待排序的元素构建成一个最大堆(或最小堆),然后将堆顶元素与堆尾元素交换,调整剩余元素重新构建堆,重复这个过程直到所有元素都有序。堆排序的时间复杂度为O(nlogn),具有原址排序的特点,是不稳定排序算法。

具体步骤如下:

1. 构建最大堆(大顶堆):从最后一个非叶子节点开始,向上逐个调整节点,保证父节点的值大于等于子节点的值。
2. 调整堆:交换堆顶元素与最后一个元素,然后将剩余元素重新构建最大堆。
3. 重复步骤2,直到所有元素有序。
4. 如果要实现升序排序,则采用大顶堆;如果要实现降序排序,则采用小顶堆。

以下是带有详细注释的堆排序的Java代码示例:```java

public class HeapSort {
    public static void heapSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }

        int n = arr.length;

        // 构建最大堆
        for (int i = n / 2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }

        // 调整堆结构,交换堆顶元素与末尾元素
        for (int i = n - 1; i >= 0; i--) {
            // 交换堆顶元素和末尾元素
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;

            // 调整堆
            heapify(arr, i, 0);
        }
    }

    // 调整堆
    private static void heapify(int[] arr, int n, int i) {
        int largest = i; // 最大元素的下标
        int left = 2 * i + 1; // 左子节点下标
        int right = 2 * i + 2; // 右子节点下标

        // 左子节点大于根节点
        if (left < n && arr[left] > arr[largest]) {
            largest = left;
        }

        // 右子节点大于根节点
        if (right < n && arr[right] > arr[largest]) {
            largest = right;
        }

        // 如果最大元素不是根节点,交换根节点和最大元素
        if (largest != i) {
            int temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;

            // 继续调整堆
            heapify(arr, n, largest);
        }
    }

    public static void main(String[] args) {
        int[] arr = {12, 11, 13, 5, 6, 7};
        System.out.println("排序前:" + Arrays.toString(arr));

        heapSort(arr);

        System.out.println("排序后:" + Arrays.toString(arr));
    }
}


```

这段代码实现了带有详细注释的堆排序算法。在堆排序过程中,首先构建最大堆,然后将堆顶元素与末尾元素交换,调整剩余元素重新构建最大堆。重复这个过程直到所有元素有序。堆排序的时间复杂度为O(nlogn),是一种高效的排序算法。

运行结果

排序前:[5, 3, 2, 8, 4, 9, 1, 0, 7, 6]

排序后:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

各种算法的比较

归并排序空间复杂度是O(n)

速度: 快速排序>>归并排序>>>>>插入排序>>选择排序>>冒泡排序

并且可以看到,选择排序,冒泡排序在数据量越来越大的情况下,耗时已经呈指数型上涨,而不是倍数上涨

(1)若n较小(如n≤50),可采用直接插入或直接选择排序。

当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜。

(2)若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜;

(3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。

快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;

堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。

若要求排序稳定,则可选用归并排序。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能_CPU安装运行ChatGLM大模型_安装清华开源人工智能AI大模型ChatGlm-6B_004---人工智能工作笔记0099

上一节003节我们安装到最后,本来大模型都可以回答问题了,结果, 5分钟后给出提示,需要GPU,我去..继续看官网,如何配置CPU运行 没办法继续看: https://github.com/THUDM/ChatGLM-6B 这里是官网可以看到 需要gcc的版本是11.3.0,这里我们先没有去安装,直接试试再说 yum instal…

在UE5中使用OverlayMaterial制作多材质效果

UE5.1中新增了OverlayMaterial&#xff0c;可以让物体套用2个材质球效果&#xff0c;如A材质球为正常材质内容&#xff0c;B材质球为菲涅尔&#xff0c;或是B材质球是法线外拓描边等&#xff0c;该功能类似Unity的多pass效果&#xff0c;方便了日常使用。 下面就讲将怎么用Ove…

手把手教你如何搭建性能测试环境

前言 在进行性能则试前&#xff0c;需要完成性能测试的搭建工作&#xff0c;一般包括硬件环境、软件环境及网络环境&#xff0c;可以要求配置和开发工程师协助完成&#xff0c;但是作为一个优秀性能测试工程师&#xff0c;这也是你的必备技能之一。 性能测试环境与功能测试环…

4款文案神器,为你写作高质量文案

4款文案神器&#xff0c;为你写作高质量文案!在当今信息爆炸的时代&#xff0c;写作成为了一项重要的技能&#xff0c;无论是在工作中、学习中还是生活中&#xff0c;我们都需要用文字来传达信息、表达想法。然而&#xff0c;要写出高质量的文案并非易事&#xff0c;需要不断地…

开源软件的影响力及未来发展趋势

开源软件的影响力 在当今数字化时代&#xff0c;开源软件已经成为技术创新、商业模式和安全风险等方面不可或缺的一部分。本文将从开源软件如何推动技术创新、开源软件的商业模式、开源软件的安全风险、开源软件的未来发展趋势以及开源软件在各行业的应用案例几个方面进行深入…

如何利用Shopee卖家中心资源和策略进行有效选品?

在Shopee卖家中心进行选品是提高产品市场竞争力和销售业绩的关键环节。为了帮助卖家更好地利用Shopee提供的资源和策略进行选品&#xff0c;以下是一些实用建议&#xff1a; 先给大家推荐一款shopee知虾数据运营工具知虾免费体验地址&#xff08;复制浏览器打开&#xff09;&a…

【力扣hot100】刷题笔记Day7

前言 身边同学已经陆陆续续回来啦&#xff0c;舍友都开始投简历了&#xff0c;我也要加油啦&#xff01;刷完hot100就投&#xff01; 73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09; 标记数组&#xff1a;空间复杂度O(mn) class Solution:def setZeroes(self, matrix:…

第十七届“挑战杯”广东大学生课外学术科技作品比赛感想

博主曾在2023年参加了第十七届“挑战杯”广东大学生课外学术科技作品比赛&#xff0c;也就是人们俗称的大挑&#xff0c;在团队赛里面含金量应该是排在第一档的了&#xff0c;当初我们有幸作为学校唯一一支科技创新B类进入到线下答辩&#xff0c;线下答辩就是区分银奖和金奖和特…

设计模式-创建型模式-抽象工厂模式

抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;&#xff1a;提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无须指定它们具体的类。抽象工厂模式又称为Kit模式&#xff0c;它是一种对象创建型模式。 由于工厂方法模式中的每个工厂只生产一类产品&…

MySQL锁相关总结|悲观锁、乐观锁、读锁、写锁、表锁、行锁、页面锁、间隙锁、临键锁

MySQL锁总体结构 MySQL 的锁上可以分成三类:总体、类型、粒度。 总体上分成两种:乐观锁和悲观锁类型上也是两种:读锁和写锁锁的粒度上可以分成五种:表锁,行锁,页面锁,间隙锁,临键锁下面我们就来详细讲一下这些锁 1. 悲观锁 悲观锁对于数据库中数据的读写持悲观态度,即…

阿里同学聊测试开发与测试平台

在一线大厂&#xff0c;没有测试这个岗位&#xff0c;只有测开这个岗位&#xff0c;即使是做业务测试&#xff0c;那么你的title也是测开。 所以想聊一聊测开的看法&#xff0c;但不代表这是正确的看法&#xff0c;仅供参考。 没来阿里之前我对测开的看法 一直以为专职做自动…

信钰证券:特斯拉掉队,英伟达冲锋!

截至当地时间2月16日收盘&#xff0c;美股三大指数上周累跌&#xff0c;结束五周连涨。其中&#xff0c;道指累计下跌0.11%&#xff0c;标普500指数周内跌幅为0.42%&#xff0c;以科技股为主的纳指则累跌1.34%。美股“科技七巨头”上周多数累跌&#xff0c;谷歌跌超5%&#xff…

【Node.js】介绍、下载及安装

一、什么是 Node.js Node.js 是一个独立的 JavaScript 运行环境&#xff0c;能独立执行 JS 代码&#xff0c;因为这个特点&#xff0c;它可以用来编写服务器后端的应用程序 前端工程化&#xff1a;开发项目直到上线&#xff0c;过程中集成的所有工具和技术 Node.js 是前端工程…

基于python-socket构建任务服务器(基于socket发送指令创建、停止任务)

在实现ia业务服务器时需要构建一个python-socket客户端&#xff0c;1、要求能与服务器保持心跳连接&#xff0c;每10秒钟发送一次心跳信号&#xff1b;2、要求能根据socket服务器发送的指令创建或终止一个定时任务。 为此以3个类实现该功能&#xff0c;分别为socket通信类&…

ONLYOFFICE编辑器升级大揭秘:v8.0版新特性实测与评价

ONLYOFFICE编辑器升级大揭秘&#xff1a;v8.0版新特性实测与评价 一个人简介二前言三操作步骤创建房间我的文档 四开发人员工具应用程序接口Javascript开发工具包插件SDK网络钩子 五测评总结六体验地址 一个人简介 &#x1f3d8;️&#x1f3d8;️个人主页&#xff1a;以山河作…

阿里云OSS对象存储使用教程

一.OSS介绍 阿里云对象存储 OSS&#xff08;Object Storage Service&#xff09;是一款海量、安全、低成本、高可靠的云存储服务&#xff0c;提供最高可达 99.995 % 的服务可用性。多种存储类型供选择&#xff0c;全面优化存储成本。 官网地址:https://www.aliyun.com/product/…

【Unity】双击C#脚本文件以单个文件打开(Visual Studio)、父类找不到、引用找不到、无法跳转等问题

问题&#xff1a;新安装一个Unity后&#xff0c;突然发现在工程里双击C#脚本&#xff0c;会一个一个打开&#xff0c;虽然也是用VS软件打开了&#xff0c;但是它无法被正确识别为Unity工程的C#脚本&#xff0c;也就是说所有命名空间无效&#xff0c;因为没关联上整个工程的解决…

STM32使用软件SPI协议操作TFT18彩屏

时间记录&#xff1a;2024/2/20 一、SPI协议介绍 &#xff08;1&#xff09;SPI设备通过4根线进行通信&#xff0c;CS片选线&#xff0c;选择从设备&#xff0c;SCK时钟线&#xff0c;由主设备产生时钟&#xff0c;主机MOSI线连从机MISO线&#xff0c;由主机向从机发送信息&am…

单片机03--按键--寄存器版

GPIO端口相关寄存器&#xff08;STM32F40x芯片&#xff09; 目标&#xff1a; 开关KEY1控制开灯。 分析&#xff1a; KEY1---PA0--->输入---->浮空输入/下拉输入 KEY1不导通时&#xff0c;PA0输入为低电平&#xff0c;KEY1导通时&#xff0c;PA0输入为高电平。 实现…

vitis安装及遇到的问题

ubuntu不能上网安装不了 我开始遇到&#xff1a;win 和 ubuntu可以互ping, 但是无法上网 1. 试一下&#xff1a;这里改成禁用 disable 2. 试一下这个 ping 8.8.8.8和ping www.baidu.com都OK&#xff0c;但是打不开网页-CSDN博客 安装过程&#xff1a; 安装文件&#xff1a;F…