Java->排序

news2024/11/25 2:20:05

目录

一、排序

1.概念

2.常见的排序算法

二、常见排序算法的实现 

1.插入排序

1.1直接插入排序

1.2希尔排序(缩小增量法)

1.3直接插入排序和希尔排序的耗时比较 

2.选择排序

2.1直接选择排序

2.2堆排序

2.3直接选择排序与堆排序的耗时比较

3.交换排序

3.1冒泡排序

3.2快速排序

1. Hoare版

2. 挖坑法

3. 前后指针

3.2.1快速排序的优化

1.三数取中法选key

2. 递归到小的子区间时,可以考虑使用插入排序

3.2.2非递归的快速排序

4.归并排序

1.归并排序 

2.非递归的归并排序 

3.海量数据的排序问题

5.排序算法复杂度及稳定性分析

​编辑

三、其他非基于比较排序

1.计数排序

2.基数排序

3.桶排序

4.比较

5.排序

一、排序

1.概念

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

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

 内部排序:数据元素全部放在内存中的排序

外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求在内外存之间移动数据的排序

2.常见的排序算法

二、常见排序算法的实现 

1.插入排序

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

1.1直接插入排序

    public static void insertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            int j = i - 1;
            int tmp = array[i];
            for (; j >= 0; j--) {
                if(array[j] > tmp) {
//if(arr[j] >= tmp)
//变为不稳定的排序
                    array[j+1] = array[j];
                }else {
//                    array[j+1] = tmp;
                    break;
                }
            }
            array[j+1] = tmp;
        }
    }

直接插入排序的特性总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1),它是一种稳定的排序算法
4. 稳定性:稳定

如果一个排序     本身就是稳定的排序        那么它就可以被实现为不稳定的排序,

但是一个排序     本身就是不稳定的排序    那么它不可能被实现为稳定的排序

1.2希尔排序(缩小增量法)

先选定一个整数,把待排序文件分为整数个组,再进行每个组内的排序

跳跃式分组: 

    public static void shellSort(int[] array) {
        int gap = array.length;
        while(gap > 1) {
            gap /= 2;
            shell(array,gap);
        }
    }

    private static void shell(int[] array, int gap) {
        for (int i = gap; i < array.length; i++) {
            int j = i - gap;
            int tmp = array[i];
            for (; j >= 0; j -= gap) {
                if(array[j] > tmp) {
                    array[j+gap] = array[j];
                }else {
                    break;
                }
            }
            array[j+gap] = tmp;
        }
    }

 希尔排序的特性总结:
1. 希尔排序是对直接插入排序的优化。
2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。
3. 希尔排序的时间复杂度不固定:O(N^1.3)....O(N^1.5)
4. 空间复杂度:O(1)  ,不稳定

1.3直接插入排序和希尔排序的耗时比较 

import java.util.Arrays;
import java.util.Random;

public class Text {
    public static void readyDataOrder(int[] array) {
        Random random = new Random();
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(100000);
        }
    }

    public static void InsertOrder(int[] array) {
        array = Arrays.copyOf(array,array.length);
        long start = System.currentTimeMillis();
        Sort.insertSort(array);
        long end = System.currentTimeMillis();
        System.out.println("插入排序耗时参考:" + (end - start));
    }

    public static void ShellOrder(int[] array) {
        long start = System.currentTimeMillis();
        Sort.shellSort(array);
        long end = System.currentTimeMillis();
        System.out.println("希尔排序耗时参考:" + (end - start));
    }

    public static void main(String[] args) {
        int[] array = new int[100000];
        readyDataOrder(array);

        InsertOrder(array);

        ShellOrder(array);
    }
}
//插入排序耗时参考:1884
//希尔排序耗时参考:22

2.选择排序

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完

2.1直接选择排序

    public static void selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i + 1; j < array.length; j++) {
                if (array[j] < array[minIndex]) {
                    minIndex = j;
                }
            }
            swap(array,i,minIndex);
        }
    }

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

直接选择排序的特性总结:
1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:不稳定


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

    public static void select2Sort(int[] array) {
        int left = 0;
        int right = array.length - 1;
        while(left<right) {
            int minIndex = left;
            int maxIndex = left;
            for (int i = left + 1; i <= right; i++) {
                if(array[i] < array[minIndex]) {
                    minIndex = i;
                }
                if(array[i] > array[maxIndex]) {
                    maxIndex = i;
                }
            }
            swap(array,left,minIndex);
            //第一个数据是最大值
            if(maxIndex == left) {
                maxIndex = minIndex;
            }
            swap(array,right,maxIndex);
            left++;
            right--;
        }
    }
//复杂度不变

2.2堆排序

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

    public static void heapSort(int[] array) {
        createHeap(array);
        int end = array.length - 1;
        while(end > 0) {
            swap(array,0,end);
            siftDown(array,0,end);
            end--;
        }
    }

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

    public static void createHeap(int[] array) {
        for (int parent = (array.length - 1 - 1) / 2; parent >= 0; parent--) {
            siftDown(array,parent,array.length);
        }
    }

    private static void siftDown(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 = parent * 2 + 1;
            }else {
                break;
            }
        }
    }

堆排序的特性总结:
1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(1)
4. 稳定性:不稳定

2.3直接选择排序与堆排序的耗时比较

public class Text {
    public static void main(String[] args) {
        int[] array = new int[100000];
        readyDataOrder(array);
        InsertOrder(array);
        ShellOrder(array);
        selectOrder(array);
        select2Order(array);
        heaptOrder(array);
    }

    public static void readyDataOrder(int[] array) {
        Random random = new Random();
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(100000);
        }
    }

    public static void InsertOrder(int[] array) {
        array = Arrays.copyOf(array,array.length);
        long start = System.currentTimeMillis();
        Sort.insertSort(array);
        long end = System.currentTimeMillis();
        System.out.println("插入排序耗时参考:" + (end - start));
    }

    public static void ShellOrder(int[] array) {
        array = Arrays.copyOf(array,array.length);
        long start = System.currentTimeMillis();
        Sort.shellSort(array);
        long end = System.currentTimeMillis();
        System.out.println("希尔排序耗时参考:" + (end - start));
    }

    public static void selectOrder(int[] array) {
        array = Arrays.copyOf(array,array.length);
        long start = System.currentTimeMillis();
        Sort.selectSort(array);
        long end = System.currentTimeMillis();
        System.out.println("选择排序耗时参考:" + (end - start));
    }

    public static void select2Order(int[] array) {
        array = Arrays.copyOf(array,array.length);
        long start = System.currentTimeMillis();
        Sort.select2Sort(array);
        long end = System.currentTimeMillis();
        System.out.println("选择排序2耗时参考:" + (end - start));
    }

    public static void heaptOrder(int[] array) {
        array = Arrays.copyOf(array,array.length);
        long start = System.currentTimeMillis();
        Sort.heapSort(array);
        long end = System.currentTimeMillis();
        System.out.println("堆排序耗时参考:" + (end - start));
    }
}
//插入排序耗时参考:2098
//希尔排序耗时参考:25
//选择排序耗时参考:4093
//选择排序2耗时参考:2929
//堆排序耗时参考:16

3.交换排序

所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

3.1冒泡排序

    public static void bubbleSort(int[] array) {
        //i是趟数
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = 0; j < array.length - 1 - i; j++) {
                if(array[j] > array[j+1]) {
                    swap(array,j,j+1);
                }
            }
        }
    }

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

冒泡排序的特性总结:
1. 冒泡排序是一种非常容易理解的排序
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:稳定

优化:

    public static void bubbleSort(int[] array) {
        //i是趟数
        for (int i = 0; i < array.length - 1; i++) {
            boolean flg = true;
            for (int j = 0; j < array.length - 1 - i; j++) {
                if(array[j] > array[j+1]) {
                    swap(array,j,j+1);
                    flg = false;
                }
            }
            if(flg) {
                break;
            }
        }
    }

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

3.2快速排序

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止

1. Hoare版
    public static void quickSort(int[] array) {
        quick(array,0,array.length - 1);
    }

    private static void quick(int[] array, int left, int right) {
        if(left > right) return;
        int par = partition(array,left,right);
        quick(array,left,par-1);
        quick(array,par+1,right);
    }

    private static int partition(int[] array, int start, int end) {
        int i = start;
        int pivot = array[start];
        while(start < end) {
//先end后start
            while(start < end && array[end] >= pivot) {
                end--;
            }
            while(start < end && array[start] <= pivot) {
                start++;
            }
            swap(array,start,end);
        }
        swap(array,i,start);
        return start;
    }

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

快速排序的特性总结:
1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
2. 时间复杂度:O(N*logN)     如果的是1 2 3 4 5 或 5 4 3 2 1…… 单分支的树时间复杂度为O(N^2),但一般不说快排时间复杂度为O(N^2),
3. 空间复杂度:O(logN)   单分支的树空间复杂度为O(N)
4. 稳定性:不稳定

 
//插入排序耗时参考:1983
//希尔排序耗时参考:19
//选择排序耗时参考:3844
//选择排序2耗时参考:2977
//堆排序耗时参考:14
//冒泡排序耗时参考:20525
//快速排序耗时参考:11
2. 挖坑法
    public static void quickSort(int[] array) {
        quick(array,0,array.length - 1);
    }

    private static void quick(int[] array, int left, int right) {
        if(left > right) return;
        int par = partition(array,left,right);
        quick(array,left,par-1);
        quick(array,par+1,right);
    }  

    private static int partition(int[] array,int start,int end) {
        int pivot = array[start];
        while(start < end) {
            while(start < end && array[end] >= pivot) {
                end--;
            }
            array[start] = array[end];
            while(start < end && array[start] <= pivot) {
                start++;
            }
            array[end] = array[start];
        }
        array[start] = pivot;
        return start;
    }
3. 前后指针
    public static void quickSort(int[] array) {
        quick(array,0,array.length - 1);
    }

    private static void quick(int[] array, int left, int right) {
        if(left > right) return;
        int par = partition(array,left,right);
        quick(array,left,par-1);
        quick(array,par+1,right);
    }
    
    private static int partition(int[] array,int start,int end) {
        int prev = start;
        int cur = start + 1;
        while(cur <= end) {
            if(array[cur] < array[start] && array[++prev] != array[cur]) {
                swap(array,cur,prev);
            }
            cur++;
        }
        swap(array,prev,start);
        return prev;
    }

    private static void swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
3.2.1快速排序的优化
1.三数取中法选key
    private static void quick(int[] array, int left, int right) {
        if(left > right) return;
        int index = midThreeNum(array,left,right);
        swap(array,index,left);
        int par = partition(array,left,right);
        quick(array,left,par-1);
        quick(array,par+1,right);
    }

    //三数取中法选key
    public static int midThreeNum(int[] array, int start, int end) {
        int mid = (start + end) / 2;
        if(array[start] < array[end]) {
            if(array[mid] < array[start]){
                return start;
            }else if(array[mid] > array[end]) {
                return end;
            }else {
                return mid;
            }
        }else {
            if(array[mid] > array[start]){
                return start;
            }else if(array[mid] < array[end]) {
                return end;
            }else {
                return mid;
            }
        }
    }
2. 递归到小的子区间时,可以考虑使用插入排序
    public static void quickSort(int[] array) {
        quick(array,0,array.length - 1);
    }

    private static void quick(int[] array, int left, int right) {
        if(left > right) return;
        if(right - left + 1 == 7) {
            insertSort2(array,left,right);
        }
        int index = midThreeNum(array,left,right);
        swap(array,index,left);
        int par = partition(array,left,right);
        quick(array,left,par-1);
        quick(array,par+1,right);
    }

    //三数取中法选key
    public static int midThreeNum(int[] array, int start, int end) {
        int mid = (start + end) / 2;
        if(array[start] < array[end]) {
            if(array[mid] < array[start]){
                return start;
            }else if(array[mid] > array[end]) {
                return end;
            }else {
                return mid;
            }
        }else {
            if(array[mid] > array[start]){
                return start;
            }else if(array[mid] < array[end]) {
                return end;
            }else {
                return mid;
            }
        }
    }

    //递归到小的子区间时,可以考虑使用插入排序
    private static void insertSort2(int[] array ,int start,int end) {
        for (int i = start + 1; i <= end; i++) {
            int j = i - 1;
            int tmp = array[i];
            for (; j >= start; j--) {
                if (array[j] > tmp) {
                    array[j + 1] = array[j];
                } else {
//                    array[j+1] = tmp;
                    break;
                }
            }
            array[j + 1] = tmp;
        }
    }

    private static int partition(int[] array, int start, int end) {
        int i = start;
        int pivot = array[start];
        while(start < end) {
            while(start < end && array[end] >= pivot) {
                end--;
            }
            while(start < end && array[start] <= pivot) {
                start++;
            }
            swap(array,start,end);
        }
        swap(array,i,start);
        return start;
    }
3.2.2非递归的快速排序
    public static void quickSort2(int[] array) {
        int left = 0;
        int right = array.length - 1;
        int par = partition(array,left,right);
        Stack<Integer> stack = new Stack<>();
        if(par > left + 1) {
            stack.push(left);
            stack.push(par - 1);
        }
        if(par < right - 1) {
            stack.push(par + 1);
            stack.push(right);
        }
        while(!stack.isEmpty()) {
            right = stack.pop();
            left = stack.pop();
            par = partition(array,left,right);
            if(par > left + 1) {
                stack.push(left);
                stack.push(par - 1);
            }
            if(par < right - 1) {
                stack.push(par + 1);
                stack.push(right);
            }
        }
    }

    private static int partition(int[] array, int start, int end) {
        int i = start;
        int pivot = array[start];
        while(start < end) {
            while(start < end && array[end] >= pivot) {
                end--;
            }
            while(start < end && array[start] <= pivot) {
                start++;
            }
            swap(array,start,end);
        }
        swap(array,i,start);
        return start;
    }

4.归并排序

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并

1.归并排序 

    public static void mergeSort(int[] array) {
        mergeSortFunc(array,0,array.length - 1);
    }

    private static void mergeSortFunc(int[] array,int left,int right) {
        if(left == right) return;
        int mid =(left + right) / 2;
        //分解
        mergeSortFunc(array,left,mid);
        mergeSortFunc(array,mid+1,right);
        //合并
        merge(array,left,right,mid);
    }

    private static void merge(int[] array, int left, int right, int mid) {
        int s1 = left;
        int e1 = mid;
        int s2 = mid + 1;
        int e2 = right;
        int[] tmpArr = new int[right - left + 1];
        int k = 0;
        while(s1<=e1 && s2<=e2) {
            if(array[s1] < array[s2]) {
                tmpArr[k++] = array[s1++];
            }else {
                tmpArr[k++] = array[s2++];
            }
        }
        while(s1<=e1) {
            tmpArr[k++] = array[s1++];
        }
        while(s2<=e2) {
            tmpArr[k++] = array[s2++];
        }
        for (int i = 0; i < tmpArr.length; i++) {
            array[i+left] = tmpArr[i];
        }
    }

归并排序的特性总结:
1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(N)
4. 稳定性:稳定

//插入排序耗时参考:2301
//希尔排序耗时参考:25
//选择排序耗时参考:4710
//选择排序2耗时参考:3635
//堆排序耗时参考:25
//冒泡排序耗时参考:23906
//快速排序耗时参考:40
//归并排序耗时参考:42

2.非递归的归并排序 


    public static void mergeSort(int[] array) {
        int gap = 1;
        while (gap < array.length) {
            for (int i = 0; i < array.length; i += 2*gap) {
                int left = i;
                int mid = left + gap - 1;
                int right = mid + gap;
                if (mid >= array.length) {
                    mid = array.length - 1;
                }
                if (right >= array.length) {
                    right = array.length - 1;
                }
                merge(array, left, right, mid);
            }
            gap *= 2;
        }
    }

    private static void merge(int[] array, int left, int right, int mid) {
        int s1 = left;
        int e1 = mid;
        int s2 = mid + 1;
        int e2 = right;
        int[] tmpArr = new int[right - left + 1];
        int k = 0;
        while (s1 <= e1 && s2 <= e2) {
            if (array[s1] < array[s2]) {
                tmpArr[k++] = array[s1++];
            } else {
                tmpArr[k++] = array[s2++];
            }
        }
        while (s1 <= e1) {
            tmpArr[k++] = array[s1++];
        }
        while (s2 <= e2) {
            tmpArr[k++] = array[s2++];
        }
        for (int i = 0; i < tmpArr.length; i++) {
            array[i + left] = tmpArr[i];
        }
    }

3.海量数据的排序问题

外部排序:排序过程需要在磁盘等外部存储进行的排序
前提:内存只有 1G,需要排序的数据有 100G
因为内存中因为无法把所有数据全部放下,所以需要外部排序,而归并排序是最常用的外部排序
1. 先把文件切分成 200 份,每个 512 M
2. 分别对 512 M 排序,因为内存已经可以放的下,所以任意排序方式都可以
3. 进行 2路归并,同时对 200 份有序文件做归并过程,最终结果就有序了

5.排序算法复杂度及稳定性分析

排序方法最好平均最坏空间复杂度稳定性
冒泡排序O(n)O(n^2)O(n^2)O(1)稳定
插入排序O(n)O(n^2)O(n^2)O(1)稳定
选择排序O(n^2)O(n^2)O(n^2)O(1)不稳定
希尔排序O(n)O(n^1.3)O(n^2)O(1)不稳定
堆排序O(n * log(n))O(n * log(n))O(n * log(n))O(1)不稳定
快速排序O(n * log(n))O(n * log(n))O(n^2)O(log(n)) ~ O(n)不稳定
归并排序O(n * log(n))O(n * log(n))O(n * log(n))O(n)稳定

三、其他非基于比较排序

1.计数排序

计数排序的场景一定是数据集中在某各范围中

步骤:

1. 统计相同元素出现次数
2. 根据统计的结果将序列回收到原来的序列中

    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];
            }
        }
        int len = max - min + 1;
        int[] count = new int[len];
        //2.遍历原来的数组 存放元素到计数数组中
//O(N)
        for (int i = 0; i < array.length; i++) {
            int index = array[i] - min;
            count[index]++;
        }
        //3.遍历计数数组
//O(范围)
        int arrIndex = 0;
        for (int i = 0; i < count.length; i++) {
            while(count[i]!=0) {
                array[arrIndex] = i + min;
                arrIndex++;
                count[i]--;
            }
        }

时间复杂度:O(范围 + N )

空间复杂度:O(范围)

稳定性:稳定

2.基数排序

动态图

队列,桶

3.桶排序

划分多个范围相同的区间,每个子区间自排序,最后合并

    public static void bucketSort(int[] array){

        // 计算最大值与最小值
        int max = array[0];
        int min = array[0];
        for(int i = 1; i < array.length; i++){
            if(array[i] < min) {
                min = array[i];
            }
            if(array[i] > max) {
                max = array[i];
            }
        }

        // 计算桶的数量
        int bucketNum = (max - min) / array.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 < array.length; i++){
            int num = (array[i] - min) / (array.length);
            bucketArr.get(num).add(array[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++){
                array[index++] = bucketArr.get(i).get(j);
            }
        }
    }

4.比较

  • 基数排序:根据键值的每位数字来分配桶;
  • 计数排序:每个桶只存储单一键值;
  • 桶排序:每个桶存储一定范围的数值;

5.排序

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

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

相关文章

你知道C++多少——继承

&#x1f308;个人主页&#xff1a;小新_- &#x1f388;个人座右铭&#xff1a;“成功者不是从不失败的人&#xff0c;而是从不放弃的人&#xff01;”&#x1f388; &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f3c6;所属专栏&#xff1…

蓝桥杯模块三:蜂鸣器和继电器的基本控制

模块训练题目&#xff1a; 一、蜂鸣器电路图 1.电路图 2.电路分析 138译码器控制Y5,Y5控制Y5C&#xff0c;Y5C低电平控制芯片开启P0口控制ULN2003继而控制蜂鸣器端口和继电器端口 二、程序代码 1.138译码器控制端口函数 建立初始化函数选择锁存器 2.实现题目功能 在LED代…

24-10-13-读书笔记(二十五)-《一只特立独行的猪》([中] 王小波)用一生来学习艺术

文章目录 《一只特立独行的猪》&#xff08;[中] 王小波&#xff09;目录阅读笔记记录总结 《一只特立独行的猪》&#xff08;[中] 王小波&#xff09; 十月第五篇&#xff0c;放慢脚步&#xff0c;秋季快要过去了&#xff0c;要步入冬季了&#xff0c;心中也是有些跌宕起伏&am…

Guitar Pro怎么制作伴奏谱,吉他谱制作软件guitar pro教程

在诸多教学吉他谱制作软件中Guitar Pro是一款非常优秀的软件&#xff0c;它是专为吉他和其他弦乐器设计&#xff0c;且能提供乐谱编辑、音轨录制和播放、和弦与音阶库等功能的强大软件。Guitar Pro不仅具有强大的乐谱编辑功能&#xff0c;其用户界面也易于上手&#xff0c;更支…

ThingsBoard规则链节点:Script节点详解

引言 脚本节点简介 用法 含义 应用场景 实际项目运用示例 智能楼宇管理系统 工业自动化生产线 结论 引言 ThingsBoard是一个功能强大的物联网平台&#xff0c;它支持设备管理、数据收集与处理以及实时监控。其核心组件之一是规则引擎&#xff0c;允许用户定义复杂的业务…

vue特效,一片动态星空

vue实现漂亮星空&#xff0c;超级简单 1.创建vue项目&#xff1a; vue create demo 2.注册vuecli : npm i element-ui -S 3.加载依赖 &#xff1a;npm i 4.运行项目 :npm run serve <!DOCTYPE html> <html lang"en"> <head><…

JavaWeb 19 AJAX

"我就是希望你好&#xff0c;就像很多人希望我好一样&#xff0c;特别简单&#xff0c;特别真挚。也不为了什么&#xff0c;就是希望你好" —— 24.10.13 一、什么是AJAX AJAX Asynchronous JavaScript and XML(异步的JavaScript和XML) AJAX不是新的编程语言&…

仿新版QQ的聊天小软件

仿新版QQ的聊天小软件 文章说明核心源码效果展示源码下载 文章说明 新开一个聊天组件的项目的想法主要来源于想学习一下消息队列的使用&#xff0c;后来在书写界面和一些功能模块时&#xff0c;又想到可以抽离出来&#xff0c;分别写几篇文章&#xff0c;主要介绍扫码登陆、消息…

MQ快速入门【详细】个人笔记 讲解通俗易懂

1.同步通讯和异步通讯 同步通讯&#xff1a;如果举个例子来说&#xff0c;同步通讯就像是两个人在打电话&#xff0c;一方说的话&#xff0c;能够立马传给另一方&#xff0c;消息的时效性非常高&#xff0c;但是相对的&#xff0c;只能是给一个人通讯&#xff0c;如果这个时候&…

React (三) 创建安装脚手架,类组件与函数式组件;生命周期;父子通信props;插槽;非父子通信Context

文章目录 一、脚手架的创建与安装1. 认识脚手架2. 安装脚手架3. 创建react项目4. 项目结构 二、从0编写三、组件化开发1. 什么是组件化开发2. 类组件3. render函数4. 函数式组件 四、生命周期1. 挂载Mount2. 更新Update3. 卸载Unmount4. 不常用的生命周期 五、父子组件通信1. 父…

数据结构之队列(python)

华子目录 1.队列存储结构1.1队列基本介绍1.2队列的实现方式 2.顺序队列2.1顺序队列的介绍2.2顺序队列的简单实现2.3代码实现 3.链式队列和基本操作3.1链式队列数据入队3.2链式队列数据出队3.3队列的链式表示和实现 1.队列存储结构 1.1队列基本介绍 队列的两端都"开口&qu…

springcloud之服务集群注册与发现 Eureka

前言 1&#xff1a;对于能提供完整领域服务接口功能的RPC而言&#xff0c;例如&#xff1b;gRPC、Thrift、Dubbo等&#xff0c;服务的注册与发现都是核心功能中非常重要的一环&#xff0c;使得微服务得到统一管理。 2&#xff1a;在分布式领域中有个著名的CAP理论&#xff1b;…

Vue3 + Element plus 实现切换el-radio前二次确认

Vue3 Element plus 实现切换el-radio前二次确认 场景&#xff1a;点击切换el-radio之前判断当前内容是否有改变&#xff0c;如有改变弹窗提示切换el-radio将销毁操作&#xff0c;弹窗二次确认是否切换 问题&#xff1a; el-radio 没有提供类似于beforeUpdate这样的钩子去处理这…

探索极简计算的新边界:从Uxn虚拟机看未来编程生态

越来越多的开发者追求复杂度和功能性的极致,然而,有一个小众的编程社区选择了截然不同的道路——极简主义。Uxn虚拟机便是这一思潮的代表之一。它通过简洁的指令集和有限的硬件资源模拟,试图打造一种可以在多种设备上运行的便携性编程环境。 与主流的重型操作系统和复杂…

HTB:Legacy[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many TCP ports are open on Legacy? 2.What is the 2008 CVE ID for a vulnerability in SMB that allows for remote code execution? 3.What is the name of the Metasploit module that exploits CVE-2008-4250? 4.When expl…

VS+QT 自定义插件变成动态库加载及使用

一、前言 有个界面需要重复使用某个自定义的控件&#xff0c;希望自定义控件能够像动态库文件那样&#xff0c;添加引用lib就能使用&#xff0c;经过多次太坑后&#xff0c;总结如下 二、实现方式 ① 新建项目&#xff0c;选择"Qt Designer Custom Widget" 创建自定…

Springboot从入门到起飞-【day01】

个人主页→VON 收录专栏→Springboot从入门到起飞 一、前言 经过了近两个月的沉淀开始了新专栏的学习&#xff0c;经过深思熟虑还是决定重新学习java&#xff0c;因为基础部分东西太多太乱就不进行逐一的更新了&#xff0c;等到学完了一同进行更新。 二、Springboot简要概述 …

kafka消息队列核心内容及常见问题

目录 1. 使用消息队列的目的&#xff08;优点与缺点&#xff09; 2. 常见各消息队列对比 3. kafka介绍 3.1 kafka简介 3.2 kafka特点 3.3 kafka系统架构 3.4 设置数据可靠性 3.4.1 Topic 分区副本 3.4.2 消息确认机制 4. 常见问题&#xff08;面试题&#xff09; 4.…

Springboot 接入 WebSocket 实战

Springboot 接入 WebSocket 实战 前言&#xff1a; WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。 简单理解&#xff1a; 1&#xff0c;常见开发过程中我们知道 Http协议&#xff0c;客户端…

LED显示器闪烁故障原因及解决方法

随着电子显示屏在各行各业的广泛应用&#xff0c;LED显示器因其高亮度、节能和灵活的宣传功能&#xff0c;成为了宣传推广的重要工具。然而&#xff0c;LED显示器在使用过程中有时会出现闪烁的现象&#xff0c;这不仅影响了显示效果&#xff0c;还可能影响用户体验。针对这一问…