Java实现八种排序

news2024/12/1 0:38:38

目录

分类

直接插入排序

希尔排序

选择排序

堆排序

冒泡排序

快速排序

挖坑法

 hoare法 

双指针法

优化

非递归实现 

归并排序

非递归实现

计数排序


分类

这里的排序可以分为两大类,

  • 基于比较的排序
  • 非基于比较的排序

其中有七种基于比较的排序:

  • 直接插入排序
  • 希尔排序
  • 选择排序
  • 堆排序
  • 冒泡排序
  • 快速排序
  • 归并排序

一种非基于比较的排序:计数排序。

下面会通过Java来实现这八种排序,快速排序 和 归并排序 会有递归和非递归的实现。

直接插入排序

思路:

  1. 以两个for循环, 来实现两个数及两数中小数与前面数进行比较
  2. 假设第一个数为tmp,认为第一个数已经是排好序的,然后去和后面一个数进行比较
  3. 如果 j位置 的数 > j+1位置的数,把 j位置的数 赋值给 j+1位置;如果否,则向 j位置的前面去做,直到 j >= 0
  4. 重复进行步骤3,直到不符合循环条件

动图如下:

代码 :

public static void insertSort(int[] array){
    for (int i = 1; i < array.length; i++) {
        int tmp = array[i];
        int j = i-1;
        for (; j >= 0; j--) {
            if(array[j] > tmp){
                array[j+1] = array[j];
            }else{
                array[j+1] = tmp;
                break;
            }
        }
        array[j+1] = tmp;
    }
}

时间复杂度:O(N^2)

空间复杂度:O(1) 

稳定性:稳定

注意:

  • 本身是一个稳定的排序,那么可以实现为不稳定的 。但是 如果一个排序 本身就是不稳定,那就不能实现稳定的排序。
  • 数据越有序,直接插入排序越快

希尔排序

步骤:

希尔排序算是对直接排序进行优化,把其中的数据通过分组来不断简化 其中的有序性,上面有提到数据越有序,直接插入排序越快,不过这个分组并不是常规理解的那种把几个临近的数字化为一个组,而是,如下图所示:

通过间隔(gap)来实现分组,以上面 紫色的原图 为例,这时的gap为5,这代表着隔着5个空格的数为一组,然后进行组内排序,不断缩小间隔,增加每组内元素个数,再次进一步比较。

动图如下:

代码:

通过代码部分,我们也能看出这里面有直接排序的存在,只不过其中的部分和希尔排序有些出入。

public static void shellInsert(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 tmp = array[i];
        int j = i-gap;
        for (; j >= 0; j-= gap) {
            if(array[j] > tmp){
                array[j+gap] = array[j];
            }else{
                array[j+gap] = tmp;
                break;
            }
        }
        array[j+gap] = tmp;
    }
}

 时间复杂度:O(N^1.2) - O(N^1.3)

空间复杂度:O(1)

稳定性:不稳定

选择排序

第一种思路

步骤:

  1. 选择排序,从名字上我们可以理解为从中不断选择出最小值,然后把它交换、排到前面
  2. 之所以说是不断选出最小值,是因为每次选出最小值都是以 i位置为准,而i位置也会不断变化,两个for循环来实现

动图如下: 

代码:

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;
}

因为其中有元素位置的交换,所以我们可以自己写一个元素位置交换的方法。 

时间复杂度:O(N^2)   和数据 是否有序无关

空间复杂度:O(1)

稳定性:不稳定

第二种思路

步骤:

这里主要是通过双指针的方法来找到 最小值 和 最大值的位置,当然,这是相对于每次i位置的数的大小。整体过程和上面一种思路有些相似的部分,相对来说,掌握两种方法还是要好一点。

public static void selectSort1(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);
        //确保最大值的位置,最大值正好是 left 下标
        //此时把最大值换到了minIndex下标
        if(maxIndex == 0){
            maxIndex = minIndex;
        }
        swap(array, right, maxIndex);
        left++;
        right--;
    }
}

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

堆排序

步骤:

  1. 通过向下调整,创建一棵大根堆的树
  2. 通过把根节点和最后一个分支节点进行交换
  3. 再进行向下调整,完成排序

这个思路主要是通过大根堆的由大到小的原理,再通过换位来实现排序。

代码:

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--;
    }
}

//创建大根堆
public static void createHeap(int[] array){
    //length-1为最后一棵子树,-1 / 2 是为了找到最后一棵子树的根节点
    for (int parent = (array.length-1-1)/2; parent >= 0; parent--) {
        siftDown(array,parent,array.length);//向下调整,创建大根堆
    }
}

/**
 *
 * @param array
 * @param parent 每棵子树调整的根节点
 * @param length 每棵子树调整的结束节点,跳到最后
 */
public static void siftDown(int[] array, int parent, int length) {
    int child = 2*parent+1;
    while(child < length){
        if(child + 1 < length && array[child] < array[child +1]){
            child++;
        }

        if(array[child] > array[parent]){
            swap(array, child, parent);
            parent = child;
            child = 2*parent+1;
        }else{
            break;
        }
    }
}

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

时间复杂度:O(N*logN)
空间复杂度:O(1)

稳定性:不稳定

冒泡排序

步骤:

通过相邻的两个元素相互比较,若 前位置 比 后位置的数要大,进行交换

动图如下:

下面代码部分是优化后的部分,未优化则不包含(flg元素 和 -i操作 )

代码:

public static void bubbleSort(int[] array){
    for (int i = 0; i < array.length-1; i++) {
        boolean flg = false;
        for (int j = 0; j < array.length-1-i; j++) {
            if(array[j] > array[j+1]){
                swap(array, j, j+1);
                flg = true;
            }
        }
        //优化后的情况
        //n个数据,比较n-1次,有可能其中i次就有序了
        if(!flg){
            break;
        }
    }
}

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

时间复杂度:不优化的情况(没有下方的boolean元素和-i操作) O(n^2)

                     优化以后,最快情况能达到O(N)

空间复杂度:O(1) 

稳定性:稳定

快速排序

快速排序有三种方式能来实现

  • 挖坑法
  • hoare法
  • 双指针法

如果问题问到快速排序,优先使用挖坑法,其次hoare法、双指针法

挖坑法

步骤:

  1. 先是实现 保证一个数的左边都比它小,右边都比它大,具体步骤如下步骤2,3,4
  2. 把第一个数存起来,为tmp,第一个位置当作是坑
  3. 从后面找比tmp小的值,放到坑里面,后面被放入坑的数的位置再当作坑
  4. 从前面找比tmp大的值,放到坑里面,前面被放入坑的数的位置当作坑
  5. 再向两边进行递归来处理

动图如下:

代码:

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

private static void quick(int[] array, int start, int end){
    // = 是为了应对没有右边的情况,递归结束条件
    if(start >= end){
        return;
    }
    //整个方法走完之后,为第一次交换位置
    int pivot = partition1(array, start, end);
    quick(array, start, pivot-1);
    quick(array, pivot+1, end);
}

private static int partition1(int[] array, int left, int right) {
    int tmp = array[left];
   
    while(left < right){
        //循环找,不循环时则代表找到,找到比tmp小的数
        while(left < right && array[right] >= tmp){
            right--;
        }
        //挖坑法,然后填坑
        //先是把第一个位置当作空,从后面数,如果有数比它小,就放到第一位
        //然后是从前数,找最大值,找到后放到,刚刚的位置
        //最后再把第一个数放到right和left相交的位置
        //方法就是把两边的数分大小放到第一个数两边
        array[left] = array[right];


        //找到比tmp大的数
        while(left < right && array[left] <= tmp){
            left++;
        }
        array[right] = array[left];
    }
    array[left] = tmp;
    return left;
}

 hoare法 

步骤:

  1. 先是实现 保证一个数的左边都比它小,右边都比它大,具体步骤如下步骤2,3,4
  2. 把第一个数存起来,为tmp
  3. tmp和后面的数进行比较,然后把小数放到tmp前面,大数放到tmp后面
  4. 递归实现对tmp两边进行排序

代码如下:

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

private static void quick(int[] array, int start, int end){
    // = 是为了应对没有右边的情况,递归结束条件
    if(start >= end){
        return;
    }
    //整个方法走完之后,为第一次交换位置
    int pivot = partition(array, start, end);
    quick(array, start, pivot-1);
    quick(array, pivot+1, end);
}

private static int partition(int[] array, int left, int right) {
    int tmp = array[left];
    int tmpleft = left;

    while(left < right){
        //循环找,不循环时则代表找到
        //right是为了把右边的小数移到左边
        while(left < right && array[right] >= tmp){
            right--;
        }

        while(left < right && array[left] <= tmp){
            left++;
        }
        swap(array, left, right);
    }
    //因为left所找的是把左边的大数放到右边,所以找到最后的数会比left小,进行交换
    swap(array,left,tmpleft);
    return left;
}

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

双指针法

步骤:

这个主要是靠 cur + left 双指针来实现排序的,通过前后条件判断来进行排序

代码如下:

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

private static void quick(int[] array, int start, int end){
    // = 是为了应对没有右边的情况,递归结束条件
    if(start >= end){
        return;
    }
    //整个方法走完之后,为第一次交换位置
    int pivot = partition3(array, start, end);
    quick(array, start, pivot-1);
    quick(array, pivot+1, end);
}

public static int partition3(int[] array, int left, int right){
    int prev = left;
    int cur = left+1;
    while(cur <= right){
        if(array[left] > array[cur] && array[cur] != array[prev]){
            swap(array, cur, prev);
        }
        cur++;
    }
    swap(array,prev,left);
    return prev;
}

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

关于快速排序

时间复杂度:当数据给定的是1 2 3 4 5 6……有序的情况是 O(n^2) 

                      最好的情况是O(N*logN)均匀分为叉,满二叉树

空间复杂度:最坏情况,递归是要开辟内存的O(N),最好的情况,满二叉树O(logN)

稳定性:不稳定

优化

通过上面三种方法,我们能看到三种方法中都有递归方式,每次递归都需要开辟内存,那么我们可以采取怎样的方式来减少递归的次数?

通过下面两种方法可以实现我们的想法:

  1. 三数取中

  2. 直接插入法【针对一定范围】

关于三数取中的意思是:找到左、右、中三个数的中位数。

 部分直接插入,也可以减少递归次数,因为数据有越有序,直接插入法越快。

代码部分如下:

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

    private static void quick(int[] array, int start, int end){
        // = 是为了应对没有右边的情况,递归结束条件
        if(start >= end){
            return;
        }

        if(end - start + 1 <= 7){
            insertSortRange(array, start, end);
            return;
        }
        int minIndex = getMiddleNum(array, start, end);
        swap(array, start, minIndex);

        //整个方法走完之后,为第一次交换位置
        int pivot = partition1(array, start, end);
        quick(array, start, pivot-1);
        quick(array, pivot+1, end);
    }

    public static void insertSortRange(int[] array, int start, int end){
        for (int i = start+1; i <= end; i++) {
            int tmp = array[i];
            int j = i-1;
            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 getMiddleNum(int[] array, int left, int right){
        int mid = (left+right)/2;
        if(array[left] < array[right]){
            if(array[mid] < array[left]){
                return left;
            }else if(array[mid] > array[right]){
                return right;
            }else{
                return mid;
            }
        }else{
            if(array[mid] > array[left]){
                return left;
            }else if(array[mid] < array[right]){
                return right;
            }else{
                return mid;
            }
        }
    }

    private static int partition1(int[] array, int left, int right) {
        int tmp = array[left];

        while(left < right){
            //循环找,不循环时则代表找到,找到比tmp小的数
            while(left < right && array[right] >= tmp){
                right--;
            }
            //挖坑法,然后填坑
            //先是把第一个位置当作空,从后面数,如果有数比它小,就放到第一位
            //然后是从前数,找最大值,找到后放到,刚刚的位置
            //最后再把第一个数放到right和left相交的位置
            //方法就是把两边的数分大小放到第一个数两边
            array[left] = array[right];


            //找到比tmp大的数
            while(left < right && array[left] <= tmp){
                left++;
            }
            array[right] = array[left];
        }
        array[left] = tmp;
        return left;
    }

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

非递归实现 

非递归实现,主要是栈的使用,通过控制出栈和入栈的元素及其顺序来实现

代码如下:

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

private static void quickNor(int[] array, int start, int end){

    Deque<Integer> stack = new ArrayDeque<>();
    int pivot = partition1(array, start, end);
    //pivot左边有两个元素
    if(pivot > start+1){
        stack.push(start);
        stack.push(pivot-1);
    }

    if(pivot < end-1){
        stack.push(pivot+1);
        stack.push(end);
    }

    while(!stack.isEmpty()){
        end = stack.pop();
        start = stack.pop();
        pivot = partition1(array, start, end);
        if(pivot > start+1){
            stack.push(start);
            stack.push(pivot-1);
        }

        if(pivot < end-1){
            stack.push(pivot+1);
            stack.push(end);
        }
    }
}

private static int partition1(int[] array, int left, int right) {
    int tmp = array[left];

    while(left < right){
        //循环找,不循环时则代表找到,找到比tmp小的数
        while(left < right && array[right] >= tmp){
            right--;
        }
        //挖坑法,然后填坑
        //先是把第一个位置当作空,从后面数,如果有数比它小,就放到第一位
        //然后是从前数,找最大值,找到后放到,刚刚的位置
        //最后再把第一个数放到right和left相交的位置
        //方法就是把两边的数分大小放到第一个数两边
        array[left] = array[right];


        //找到比tmp大的数
        while(left < right && array[left] <= tmp){
            left++;
        }
        array[right] = array[left];
    }
    array[left] = tmp;
    return left;
}

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

归并排序

步骤:

  1. 先把要排序的元素分为两个组,接着继续向下分组(有种递归的味道了)
  2. 把每组元素比较完后,再把两个有序数组组合起来

代码如下: 

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

//递归实现归并排序
private static void mergeSortTmp(int[] array, int left, int right) {
    if(left >= right){
        return;
    }
    //找中间值
    int mid = (left + right)/2;
    mergeSortTmp(array, left, mid-1);
    mergeSortTmp(array, mid+1, right);
    //走到这里,相当于全部分解完
    //合并,合并有序数组
    merge(array, left, mid, right);


}

private static void merge(int[] array, int left, int mid, int right) {
    int[] tmp = new int[right-left+1];
    int k = 0;
    int s1 = left;
    int e1 = mid;
    int s2 = mid+1;
    int e2 = right;

    while(s1 <= e1 &&  s2 <= e2){
        if(array[s1] <= array[s2]){
            tmp[k++] = array[s1++];
        }else {
            tmp[k++] = array[s2++];
        }
    }

    while(s1 <= e1){
        tmp[k++] = array[s1++];
    }

    while(s2 <= e2){
        tmp[k++] = array[s2++];
    }
    //可以保证tmp数组是有序的
    for (int i = 0; i < k; i++) {
        array[i+left] = tmp[i];
    }
}

时间复杂度:O(N*logN)

空间复杂度:O(N)

稳定性:稳定

非递归实现

非递归的实现,主要依靠的间隔gap的不断变大,然后通过每一小部分的排序进而来实现整个数据组的排序

代码如下:

 

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

private static void merge(int[] array, int left, int mid, int right) {
    int[] tmp = new int[right-left+1];
    int k = 0;
    int s1 = left;
    int e1 = mid;
    int s2 = mid+1;
    int e2 = right;

    while(s1 <= e1 &&  s2 <= e2){
        if(array[s1] <= array[s2]){
            tmp[k++] = array[s1++];
        }else {
            tmp[k++] = array[s2++];
        }
    }

    while(s1 <= e1){
        tmp[k++] = array[s1++];
    }

    while(s2 <= e2){
        tmp[k++] = array[s2++];
    }
    //可以保证tmp数组是有序的
    for (int i = 0; i < k; i++) {
        array[i+left] = tmp[i];
    }
}

计数排序

非基于比较的排序

还有桶排序, 基数排序,感兴趣可以了解一下

使用场景:集中在某个范围内的一组数据

 步骤:

  1. 根据数据的个数来创建数组
  2. 把对应元素出现的个数给到对应的位置,记录出现的次数
  3. 根据记录的次数,依次输出元素

代码如下 :

public static void countSort(int[] array){

    //1.找最大值 和 最小值 来确定 计数数组的大小
    int maxVal = array[0];
    int minVal = array[0];
    for (int i = 1; i < array.length; i++) {
        if(array[i] > maxVal){
            maxVal = array[i];
        }
        if(array[i] < minVal){
            minVal = array[i];
        }
    }
    int len = maxVal - minVal + 1;
    int[] count = new int[len];

    //2.遍历原来的数组array, 把每个元素 放到对应的计数数组中 进行比较
    for (int i = 0; i < array.length; i++) {
        int index = array[i];
        count[index-minVal]++;
    }

    //3.依次 遍历计数数组
    int index = 0;
    for (int i = 0; i < count.length; i++) {
        while(count[i] != 0){
            array[index] = i+minVal;
            index++;
            count[i]--;
        }
    }
}

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

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

相关文章

.NET 一款读取Excel文件敏感数据的工具

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

【机器学习】智能聊天机器人——基于自然语言处理的智能对话系统

1. 什么是自动化客户服务与智能聊天机器人&#xff1f; 自动化客户服务是一种通过技术手段自动处理客户问题的服务方式&#xff0c;能够在无需人工干预的情况下为客户提供即时、准确的帮助。这种服务通常依托智能系统&#xff0c;通过预设的响应机制或学习历史数据&#xff0c…

数电(编码器、数据分配器、数据选择器)

目录 一、编码器&#xff1a; 1.二进制编码器&#xff1a; 三、优先编码器&#xff08;Priority Encoder&#xff09; 1.二-十进制优先编码器 二、数据分配器和数据选择器(功能正好相反) 1.数据分配器 2.数据选择器 一、编码器&#xff1a; 1.二进制编码器&#xff1a; …

【Linux系统编程】第三十二弹---动态库实战指南:从零构建与高效集成的奥秘

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、动态库 1.1、怎么做动态库 1.2、怎么使用动态库 2、外部库使用 1、动态库 1.1、怎么做动态库 方式一 1、将.c文件编…

创客项目秀|基于XIAO ESP32C3的Night Lamp With Chinese Traditional Pane项目

Fab Academy&#xff0c;源自麻省理工学院的先进教育项目&#xff0c;致力于培养具有全球视野的创新者和制造者。通过密集学习和实践&#xff0c;学生们掌握了从基础到高级的制造技术&#xff0c;学习了如何将创意转化为现实。今天小编给大家带来的是Fab academy学员Dion Tsang…

前端全栈混合之路Deno篇:Deno2.0与Bun对比,谁更胜一筹?或者说谁更适合怎样的项目

在前端全栈开发中&#xff0c;工具的不断演变让开发者们始终在寻找更高效、更现代化的解决方案。继Node.js之后&#xff0c;Deno和Bun 成为了两个比较火热的运行时。Deno2.0的近期的发布让它在性能和兼容性方面大幅提升-尤其是兼容了npm包&#xff08;但我感觉应该不是全部兼容…

如何给低代码平台取名?命名策略与技巧全解析

低代码平台正日益成为企业数字化转型的重要工具。为了确保您的平台能够脱颖而出&#xff0c;吸引到更多的用户和开发者&#xff0c;选择一个恰到好处的名字至关重要。本文将探讨如何为您的低代码平台选择一个既独特又易于记忆的好名字&#xff0c;并详细介绍一系列行之有效的命…

第二百七十九节 JPA教程 - JPA查询IN一对多示例

JPA教程 - JPA查询IN一对多示例 以下JPQL显示如何在一对多映射中使用IN运算符。 executeAndPrintQuery("SELECT DISTINCT p FROM Employee e, IN(e.directs) p");例子 下面的代码来自Department.java。 package cn.w3cschool.common;import java.util.ArrayList; …

中药药材推荐系统

毕业设计还在发愁选题&#xff1f;又想实用又怕复杂&#xff1f;那这篇介绍你一定感兴趣&#xff01; 今天为大家推荐一个基于Django框架开发的中药药材推荐系统&#xff0c;简洁易用&#xff0c;功能丰富&#xff0c;非常适合毕业设计。无论你是技术经验丰富的开发人员&#…

praat语音标注

一、软件下载 praat软件下载链接 下载后双击 二、软件界面

【机器学习】朴素贝叶斯算法|商品评论情感分析案例介绍及代码实现

文章目录 朴素贝叶斯算法朴素贝叶斯算法介绍概率数学基础复习朴素贝叶斯算法-利用概率值进行分类的一种机器学习算法贝叶斯公式朴素贝叶斯算法拉普拉斯平滑系数 朴素贝叶斯API案例分析流程数据集代码实现运行结果 朴素贝叶斯算法 朴素贝叶斯算法介绍 概率数学基础复习 条件概…

扇形旋转切换效果(等级切换转盘)

实现动态扇形旋转切换效果&#xff0c;切换进度支持渐变效果 效果展示 在线示例 https://code.juejin.cn/pen/7425559403589271588 源码实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"v…

华宇携司法大模型亮相2024中国移动全球合作伙伴大会

2024中国移动全球合作伙伴大会于10月11日在广州琶洲保利世贸博览馆盛大开幕。本届大会以“智焕新生 共创AI时代”为主题&#xff0c;深入探讨数据、算力与人工智能如何深度融合&#xff0c;全力推进AI规模发展、规模应用&#xff0c;加快形成AI技术能力、经济效益上的规模效应&…

【NestJS入门到精通】装饰器

目录 方法装饰器通过prototype添加属性、方法 属性装饰器拓展 方法装饰器参数装饰器 方法装饰器 ClassDecorator 定义了一个类装饰器 a&#xff0c;并将其应用于类 A。装饰器 a 会在类 A 被定义时执行。 const a:ClassDecorator (target:any)>{console.log(target,targe…

Python Django 数据库优化与性能调优

Python Django 数据库优化与性能调优 Django 是一个非常流行的 Python Web 框架&#xff0c;它的 ORM&#xff08;对象关系映射&#xff09;允许开发者以简单且直观的方式操作数据库。然而&#xff0c;随着数据量的增长&#xff0c;数据库操作的效率可能会成为瓶颈&#xff0c…

【SQL Server】数据库在新建查询后闪退——解决方案:以管理员的身份运行

我的SQLServer2022之前都是可以用的&#xff0c;隔了好久没有使用&#xff0c;今天要用到去写一些SQL 语句 结果在点击新建查询后闪退了&#xff0c; 经过查询后&#xff0c;解决方案&#xff1a; 以管理员的身份运行后点击新建查询&#xff0c;发现正常了 总结&#xff1a;以…

PyQt 入门教程(2)搭建开发环境

文章目录 一、搭建开发环境1、安装PyQt6与pyqt6-tools2、配置外部工具QtDesigner与PYUIC 一、搭建开发环境 1、安装PyQt6与pyqt6-tools PyQt6&#xff1a; PyQt的开发库。pyqt6-tools&#xff1a; QtDesigner 设计器支撑库。 通过PyCharm安装开发库&#xff0c;命令如下&…

探索全流量回溯分析系统:IT运维的必备利器

目录 一、什么是全流量回溯分析系统&#xff1f; 二、全流量回溯分析系统的核心功能 三、IT运维中的实际应用案例 四、IT运维中使用全流量回溯分析系统的技巧 结语 AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具 在当今的IT运维中&#xff0c;网络故…

【Python爬虫实战】正则:多字符匹配、开头与结尾定位、分组技术详解

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、匹配多个字符 &#xff08;一&#xff09;匹配任意多个字符 &#xff0…

OpenAI Canvas:提升编程与写作效率的全新工作界面

随着人工智能技术的飞速发展&#xff0c;大语言模型&#xff08;LLM&#xff09;不仅限于生成文本&#xff0c;还能逐步扩展至编程、设计等任务的支持。近期&#xff0c;OpenAI 推出了一个名为 Canvas 的全新功能&#xff0c;专门用于协助用户进行编程和写作。这一功能与 Claud…