算法与数据结构-排序

news2024/11/24 20:26:45

文章目录

  • 一、如何分析一个排序算法
    • 1.1 排序算法的执行效率
      • 1.1.1 最好情况、最坏情况、平均情况时间复杂度
        • 1.1.1.1 最好、最坏情况分析
        • 1.1.1.2 平均情况分析
      • 1.1.2 时间复杂度的系数、常数 、低阶
      • 1.1.3 比较次数和交换(或移动)次数
    • 1.2 排序算法的内存消耗
    • 1.3 排序算法的稳定性
  • 二、排序算法分析
    • 2.1 冒泡排序
      • 2.1.1 算法代码
      • 2.1.2 算法分析
    • 2.2 插入排序
      • 2.2.1 算法代码
      • 2.2.2 算法分析
    • 2.3 选择排序
      • 2.3.1 算法代码
      • 2.3.2 算法分析
    • 2.4 归并排序
      • 2.4.1 算法代码
      • 2.4.2 算法分析
    • 2.5 快速排序
      • 2.5.1 算法代码
      • 2.5.2 算法分析
    • 2.6 桶排序
      • 2.6.1 算法代码
      • 2.6.2 算法分析
    • 2.7 计数排序
      • 2.7.1 算法代码
      • 2.7.2 算法分析


一、如何分析一个排序算法

1.1 排序算法的执行效率

1.1.1 最好情况、最坏情况、平均情况时间复杂度

1.1.1.1 最好、最坏情况分析

  我们在分析排序算法的时间复杂度时,要分别给出最好情况、最坏情况、平均情况下的时间复杂度。除此之外,你还要说出最好、最坏时间复杂度对应的要排序的原始数据是什么样的。

  为什么要区分这三种时间复杂度呢?第一,有些排序算法会区分,为了好对比,所以我们最好都做一下区分。第二,对于要排序的数据,有的接近有序,有的完全无序。有序度不同的数据,对于排序的执行时间肯定是有影响的,我们要知道排序算法在不同数据下的性能表现。

1.1.1.2 平均情况分析

  最好、最坏情况下的时间复杂度很容易分析,那平均情况下的时间复杂是多少呢?我们前面讲过,平均时间复杂度就是加权平均期望时间复杂度,分析的时候要结合概率论的知识。

  对于包含 n 个数据的数组,这 n 个数据就有 n! 种排列方式。不同的排列方式,冒泡排序执行的时间肯定是不同的。比如我们前面举的那两个例子,其中一个要进行 6 次冒泡,而另一个只需要 4 次。如果用概率论方法定量分析平均时间复杂度,涉及的数学推理和计算就会很复杂。我这里还有一种思路,通过“有序度”和“逆序度”这两个概念来进行分析。
在这里插入图片描述
  同理,对于一个倒序排列的数组,比如 6,5,4,3,2,1,有序度是 0;对于一个完全有序的数组,比如 1,2,3,4,5,6,有序度就是 n(n-1)/2*,也就是 15。我们把这种完全有序的数组的有序度叫作满有序度

  逆序度的定义正好跟有序度相反(默认从小到大为有序)。所以我们可以推导出一个公式:

逆序度 = 满有序度 - 有序度

我们排序的过程就是一种增加有序度,减少逆序度的过程,最后达到满有序度,就说明排序完成了。

1.1.2 时间复杂度的系数、常数 、低阶

  我们知道,时间复杂度反映的是数据规模 n 很大的时候的一个增长趋势,所以它表示的时候会忽略系数、常数、低阶。但是实际的软件开发中,我们排序的可能是 10 个、100 个、1000 个这样规模很小的数据,所以,在对同一阶时间复杂度的排序算法性能对比的时候,我们就要把系数、常数、低阶也考虑进来。

1.1.3 比较次数和交换(或移动)次数

  基于比较的排序算法的执行过程,会涉及两种操作,一种是元素比较大小,另一种是元素交换或移动。所以,如果我们在分析排序算法的执行效率的时候,应该把比较次数和交换(或移动)次数也考虑进去。

1.2 排序算法的内存消耗

  算法的内存消耗可以通过空间复杂度来衡量,排序算法也不例外。不过,针对排序算法的空间复杂度,我们还引入了一个新的概念,原地排序(Sorted in place)。原地排序算法,就是特指空间复杂度是 O(1) 的排序算法。我们今天讲的三种排序算法,都是原地排序算法。

1.3 排序算法的稳定性

  针对排序算法,我们还有一个重要的度量指标,稳定性。这个概念是说,如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序不变。举个例子,如果我们有个电商系统,先将订单按照ID排序,再使用相同的算法按照订单金额排序。经过两次排序后,如果金额相同的订单ID顺序保持不变则认为该算法稳定,否则认为该算法不稳定。

二、排序算法分析

2.1 冒泡排序

2.1.1 算法代码

    public static void bubbleSort(int[] arr) {
        int size = arr.length;
        for (int i = 0; i < size; i++) {
            boolean changeFlag = false;
            for (int j = 0; j < size - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    changeFlag = true;
                }
            }
            if (!changeFlag) {
                break;
            }
        }
    }

2.1.2 算法分析

在这里插入图片描述

  • 第一,冒泡排序是原地排序算法吗?
      冒泡的过程只涉及相邻数据的交换操作,只需要常量级的临时空间,所以它的空间复杂度为 O(1),是一个原地排序算法。

  • 第二,冒泡排序是稳定的排序算法吗?
      在冒泡排序中,只有交换才可以改变两个元素的前后顺序。为了保证冒泡排序算法的稳定性,当有相邻的两个元素大小相等的时候,我们不做交换,相同大小的数据在排序前后不会改变顺序,所以冒泡排序是稳定的排序算法。

  • 第三,冒泡排序的时间复杂度是多少?
      最好情况下,要排序的数据已经是有序的了,我们只需要进行一次冒泡操作,就可以结束了,所以最好情况时间复杂度是 O(n)。而最坏的情况是,要排序的数据刚好是倒序排列的,我们需要进行 n 次冒泡操作,所以最坏情况时间复杂度为 O(n²)。
    在这里插入图片描述
      最坏情况下,初始状态的有序度是 0,所以要进行 n*(n-1)/2 次交换。最好情况下,初始状态的有序度是 n*(n-1)/2,就不需要进行交换。我们可以取个中间值 n*(n-1)/4,来表示初始有序度既不是很高也不是很低的平均情况。 换句话说,平均情况下,需要 n*(n-1)/4 次交换操作,比较操作肯定要比交换操作多,而复杂度的上限是 O(n²),所以平均情况下的时间复杂度就是 O(n²)。

2.2 插入排序

2.2.1 算法代码

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

2.2.2 算法分析

在这里插入图片描述

  • 第一,插入排序是原地排序算法吗?
      从实现过程可以很明显地看出,插入排序算法的运行并不需要额外的存储空间,所以空间复杂度是 O(1),也就是说,这是一个原地排序算法。

  • 第二,插入排序是稳定的排序算法吗?
      在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。

  • 第三,插入排序的时间复杂度是多少?
      如果要排序的数据已经是有序的,我们并不需要搬移任何数据。如果我们从尾到头在有序数据组里面查找插入位置,每次只需要比较一个数据就能确定插入的位置。所以这种情况下,最好是时间复杂度为 O(n)。注意,这里是从尾到头遍历已经有序的数据。
      如果数组是倒序的,每次插入都相当于在数组的第一个位置插入新的数据,所以需要移动大量的数据,所以最坏情况时间复杂度为 O(n²)。
      还记得我们在数组中插入一个数据的平均时间复杂度是多少吗?没错,是 O(n)。所以,对于插入排序来说,每次插入操作都相当于在数组中插入一个数据,循环执行 n 次插入操作,所以平均时间复杂度为 O(n²)。

2.3 选择排序

2.3.1 算法代码

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

            int tmp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = tmp;
        }
    }

2.3.2 算法分析

在这里插入图片描述

  • 第一,选择排序是原地排序算法吗?
      选择排序空间复杂度为 O(1),是一种原地排序算法。

  • 第二,选择排序是稳定的排序算法吗?
      选择排序是一种不稳定的排序算法,选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。

  • 第三,选择排序的时间复杂度是多少?
      选择排序的最好情况时间复杂度、最坏情况和平均情况时间复杂度都为 O(n²)。

2.4 归并排序

2.4.1 算法代码

    public static void mergeSort(int[] arr, int startIndex, int endIndex) {
        if (startIndex >= endIndex) {
            return;
        }

        int middle = (startIndex + endIndex) / 2;
        mergeSort(arr, startIndex, middle);
        mergeSort(arr, middle + 1, endIndex);
        merge(arr, startIndex, endIndex);
    }

    public static void merge(int[] arr, int startIndex, int endIndex) {
        int[] arrNew = new int[endIndex - startIndex + 1];
        int middle = (startIndex + endIndex) / 2;

        int k = 0;
        int i = startIndex;
        int j = middle + 1;
        while (i <= middle && j <= endIndex) {
            if (arr[i] < arr[j]) {
                arrNew[k++] = arr[i++];
            } else {
                arrNew[k++] = arr[j++];
            }
        }
        int start = i;
        int end = middle;
        if (j <= endIndex) {
            start = j;
            end = endIndex;
        }
        while (start <= end) {
            arrNew[k++] = arr[start++];
        }

        for (int m = 0; m < arrNew.length; m++) {
            arr[startIndex++] = arrNew[m];
        }
    }

2.4.2 算法分析

在这里插入图片描述

  • 第一,归并排序是原地排序算法吗?
      通过代码可以看到,在合并数组时,需要开辟额外的数组空间来保证顺序,所以归并排序不是原地排序算法。

  • 第二,归并排序是稳定的排序算法吗?
      归并排序稳不稳定关键要看 merge() 函数,也就是两个有序子数组合并成一个有序数组的那部分代码。 在合并的过程中,如果 A[p…q]和 A[q+1…r]之间有值相同的元素,那我们可以像伪代码中那样,先把 A[p…q]中的元素放入 tmp 数组。这样就保证了值相同的元素,在合并前后的先后顺序不变。所以,归并排序是一个稳定的排序算法。

  • 第三,归并排序的时间复杂度是多少?
      可以看到,归并排序主要就是通过递归的方式,即那求解问题 a 就可以分解为求解问题 b、c。问题 b、c 解决之后,我们再把 b、c 的结果合并成 a 的结果。
      
      如果我们定义求解问题 a 的时间是 T(a),求解问题 b、c 的时间分别是 T(b) 和 T( c),那我们就可以得到这样的递推关系式:T( a ) = T( b ) + T( c ) + K。其中 K 等于将两个子问题 b、c 的结果合并成问题 a 的结果所消耗的时间。
      
      我们假设对 n 个元素进行归并排序需要的时间是 T(n),那分解成两个子数组排序的时间都是 T(n/2)。我们知道,merge() 函数合并两个有序子数组的时间复杂度是 O(n)。所以,套用前面的公式,归并排序的时间复杂度的计算公式就是:T(n) = 2*T(n/2) + n(当n=1时,T(1) = C)
      
      通过这个公式,如何来求解 T(n) 呢?还不够直观?那我们再进一步分解一下计算过程。
      T(n) = 2*T(n/2) + n
         = 2(2T(n/4) + n/2) + n = 4T(n/4) + 2n
         = 4(2T(n/8) + n/4) + 2*n = 8T(n/8) + 3n
         = 8(2T(n/16) + n/8) + 3*n = 16T(n/16) + 4n
        
         = 2^k * T(n/2^k) + k * n
        
      通过这样一步一步分解推导,我们可以得到 T(n) = 2kT(n/2k)+kn。当 T(n/2k)=T(1) 时,也就是 n/2^k=1,我们得到 k=log2n 。我们将 k 值代入上面的公式,得到 T(n)=Cn+nlog2n 。如果我们用大 O 标记法来表示的话,T(n) 就等于 O(nlogn)。所以归并排序的时间复杂度是 O(nlogn)。
      
      从我们的原理分析和代码可以看出,归并排序的执行效率与要排序的原始数组的有序程度无关,所以其时间复杂度是非常稳定的,不管是最好情况、最坏情况,还是平均情况,时间复杂度都是 O(nlogn)。

2.5 快速排序

2.5.1 算法代码

    public static void quickSort(int[] arr, int startIndex, int endIndex) {
        if (startIndex >= endIndex) {
            return;
        }

        int part = part(arr, startIndex, endIndex);
        quickSort(arr, startIndex, part - 1);
        quickSort(arr, part + 1, endIndex);
    }

    public static int part(int[] arr, int startIndex, int endIndex) {
        int midValue = arr[endIndex];
        int i = startIndex;
        int j = startIndex;
        for (; i < endIndex; i++) {
            if (arr[i] < midValue) {
                if (j == i) {
                    j++;
                } else {
                    int tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                    j++;
                }
            }
        }

        arr[endIndex] = arr[j];
        arr[j] = midValue;
        return j;
    }

2.5.2 算法分析

在这里插入图片描述

  • 第一,快速排序是原地排序算法吗?
      通过代码可以看到,快速排序不需要开辟单独的空间,所以快速排序是原地排序算法。

  • 第二,快速排序是稳定的排序算法吗?
      通过代码可以看出来,快速排序是基于“分而治之”思想的数据交换,所以快速排序不是稳定的排序算法。

  • 第三,快速排序的时间复杂度是多少?
      快排也是用递归来实现的。对于递归代码的时间复杂度,我前面总结的公式,这里也还是适用的。如果每次分区操作,都能正好把数组分成大小接近相等的两个小区间,那快排的时间复杂度递推求解公式跟归并是相同的。所以,快排的时间复杂度也是 O(nlogn)。
      
      但是,公式成立的前提是每次分区操作,我们选择的 pivot 都很合适,正好能将大区间对等地一分为二。但实际上这种情况是很难实现的。
      
      我举一个比较极端的例子。如果数组中的数据原来已经是有序的了,比如 1,3,5,6,8。如果我们每次选择最后一个元素作为 pivot,那每次分区得到的两个区间都是不均等的。我们需要进行大约 n 次分区操作,才能完成快排的整个过程。每次分区我们平均要扫描大约 n/2 个元素,这种情况下,快排的时间复杂度就从 O(nlogn) 退化成了 O(n2)。
      
      但是我们可以通过首中尾三点取中法来尽量避免取到极限值的情况。首中尾三点取中法的意思就是取第一个节点、中间的节点、最后一个节点三者进行比较,取中间值作为分界点。

2.6 桶排序

2.6.1 算法代码

    public static void bucketSort(int[] arr, int bucketSize) {
        // 取最大最小值
        int minValue = arr[0];
        int maxValue = arr[0];
        int size = arr.length;
        for (int i = 0; i < size; i++) {
            if (arr[i] < minValue) {
                minValue = arr[i];
            }
            if (arr[i] > maxValue) {
                maxValue = arr[i];
            }
        }

        // 计算桶的个数
        int bucketCount = (maxValue - minValue) / bucketSize + 1;
        // 定义桶
        int[][] bucketArr = new int[bucketCount][bucketSize];
        // 记录每个桶里数据量
        int[] bucketIndexArr = new int[bucketCount];

        // 循环将放入桶中
        for (int i = 0; i < size; i++) {
            int bucketIndex = (arr[i] - minValue) / bucketSize;
            bucketArr[bucketIndex][bucketIndexArr[bucketIndex]] = arr[i];
            bucketIndexArr[bucketIndex]++;
        }

        // 为每个桶排序,并将排序好的桶数据重设到数组里
        int k = 0;
        for (int i = 0; i < bucketCount; i++) {
            if (bucketIndexArr[i] == 0) {
                continue;
            }
            // 这里使用的是快速排序,代码省略
            QuickSort.quickSort(bucketArr[i], 0, bucketIndexArr[i] - 1);
            for (int j = 0; j < bucketIndexArr[i]; j++) {
                arr[k++] = bucketArr[i][j];
            }
        }
    }

2.6.2 算法分析

在这里插入图片描述

  • 第一,桶排序是原地排序算法吗?
      通过代码我们可以看到,桶排序需要新的桶(数组)来存储数据,那么桶排序算法不是原地排序算法。

  • 第二,桶排序是稳定的排序算法吗?
      桶排序需要借助其他排序算法,由于我们这里借助的是快速排序(不稳定),所以这里的桶排序算法是不稳定的排序算法。

  • 第三,桶排序的时间复杂度是多少?
      如果要排序的数据有 n 个,我们把它们均匀地划分到 m 个桶内,每个桶里就有 k=n/m 个元素。每个桶内部使用快速排序,时间复杂度为 O(k * logk)。m 个桶排序的时间复杂度就是 O(m * k * logk),因为 k=n/m,所以整个桶排序的时间复杂度就是 O(n*log(n/m))。当桶的个数 m 接近数据个数 n 时,log(n/m) 就是一个非常小的常量,这个时候桶排序的时间复杂度接近 O(n)。
      
      桶排序比较适合用在外部排序中。所谓的外部排序就是数据存储在外部磁盘中,数据量比较大,内存有限,无法将数据全部加载到内存中。

2.7 计数排序

2.7.1 算法代码

// 计数排序,a是数组,n是数组大小。假设数组中存储的都是非负整数。
public void countingSort(int[] a, int n) {
  if (n <= 1) return;

  // 查找数组中数据的范围
  int max = a[0];
  for (int i = 1; i < n; ++i) {
    if (max < a[i]) {
      max = a[i];
    }
  }

  int[] c = new int[max + 1]; // 申请一个计数数组c,下标大小[0,max]
  for (int i = 0; i <= max; ++i) {
    c[i] = 0;
  }

  // 计算每个元素的个数,放入c中
  for (int i = 0; i < n; ++i) {
    c[a[i]]++;
  }

  // 依次累加
  for (int i = 1; i <= max; ++i) {
    c[i] = c[i-1] + c[i];
  }

  // 临时数组r,存储排序之后的结果
  int[] r = new int[n];
  // 计算排序的关键步骤,有点难理解
  for (int i = n - 1; i >= 0; --i) {
    int index = c[a[i]]-1;
    r[index] = a[i];
    c[a[i]]--;
  }

  // 将结果拷贝给a数组
  for (int i = 0; i < n; ++i) {
    a[i] = r[i];
  }
}

2.7.2 算法分析

在这里插入图片描述

  • 第一,计数排序是原地排序算法吗?
      通过代码可以看到,我们需要一个单独的数组存储计数信息,所以计数排序不是原地排序算法。

  • 第二,计数排序是稳定的排序算法吗?
      通过代码可以看到,在计数排序中,如果两个元素的计数结果不同,它们的相对顺序就会改变,因此计数排序是不稳定的排序算法。

  • 第三,计数排序的时间复杂度是多少?
      通过代码我们可以看到,计数排序的时间复杂度是O(n)。
      但是计数排序只能用在数据范围不大的场景中,如果数据范围 k 比要排序的数据 n 大很多,就不适合用计数排序了。而且,计数排序只能给非负整数排序,如果要排序的数据是其他类型的,要将其在不改变相对大小的情况下,转化为非负整数。

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

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

相关文章

第六届字节跳动青训营报录比(宣传大使)

统计 前端基础卷&#xff1a;105 前端基础班&#xff1a;120-22(笔试不过基础班&#xff0c;宣传大使奖励进入&#xff09;98 前端进阶卷&#xff1a;77 前端进阶班&#xff1a;18-216 后端基础卷&#xff1a;151 后端基础班&#xff1a;220 后端进阶卷&#xff1a;133 后端进…

【论文笔记】KDD2019 | KGAT: Knowledge Graph Attention Network for Recommendation

Abstract 为了更好的推荐&#xff0c;不仅要对user-item交互进行建模&#xff0c;还要将关系信息考虑进来 传统方法因子分解机将每个交互都当作一个独立的实例&#xff0c;但是忽略了item之间的关系&#xff08;eg&#xff1a;一部电影的导演也是另一部电影的演员&#xff09…

133、仿真-基于51单片机太阳能热水器水温水位智能监控仪报警设计(Proteus仿真+程序+配套资料等)

方案选择 单片机的选择 方案一&#xff1a;STM32系列单片机控制&#xff0c;该型号单片机为LQFP44封装&#xff0c;内部资源足够用于本次设计。STM32F103系列芯片最高工作频率可达72MHZ&#xff0c;在存储器的01等等待周期仿真时可达到1.25Mip/MHZ(Dhrystone2.1)。内部128k字节…

【QT】元对象系统学习笔记(二)

QT元对象系统 01、属性系统1.1、 属性基础1.2、 QVariant类1.3、 使用QObject类存取属性值与动态属性1.4、 使用反射机制获取属性信息 02、信号与槽2.1、 信号与槽原理2.2、 创建信号与槽2.3、 信号与槽的连接2.4、 断开信号与槽2.5、 关键字原型 03、对象树与生命期3.1、组合模…

【TiDB理论知识 03】TiKV-持久化与数据读取

目录 一 TiKV架构和作用 二 数据持久化 1 RocksDB&#xff1a;写入 写入过程 第一步 &#xff1a;WAL 写日志 &#xff08;磁盘日志&#xff09; 第二步&#xff1a;写MemTable (内存中) 第三步 &#xff1a; 转存为immutable MemTable&#xff08;内存中&#xff09; …

JAVA集成国密SM4

JAVA集成国密SM4加解密 一、pom配置二、代码集成2.1、目录结构2.2、源码2.3、测试 三、遇到的坑3.1、秘钥长度3.2、转码问题 四、相关链接 国密算法概述&#xff1a;https://blog.csdn.net/qq_38254635/article/details/131801527 SM4对称算法 SM4 无线局域网标准的分组数据算…

线性表的链式存储结构以及顺序表和链表的比较

2.2线性表的链式存储结构 **链式存储结构&#xff1a;**结点在存储器中的位置是任意的&#xff0c;即逻辑上相邻的数据元素在物理上不一定相邻。 线性表的链式表示又称为非顺序映像或链式映像 这组存储单元既可以是连续的&#xff0c;也可以是不连续的&#xff0c;甚至是零散…

C++基础算法前缀和和差分篇

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C算法 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 主要讲解了前缀和和差分算法 文章目录 Ⅳ. 前缀和 和 差分Ⅵ .Ⅰ前缀和…

AtcoderABC244场

A - Last LetterA - Last Letter 题目大意 给定一个长度为N的字符串S&#xff0c;由小写英文字母组成&#xff0c;打印出S的最后一个字符。 思路分析 题目要求打印出字符串S的最后一个字符&#xff0c;可以直接通过访问S的最后一个元素来获取该字符。可以使用字符串的back()…

旅游卡小程序软件招商加盟代理

旅游卡小程序软件招商加盟代理 我国人民生活水平的提高&#xff0c;旅游业成为了人们生活中必不可少的一部分。旅游卡小程序软件作为旅游行业的重要组成部分&#xff0c;也日益受到人们的关注。如今&#xff0c;旅游卡小程序软件招商加盟代理已经成为了一个热门的投资创业项…

$.getScript()方法获取js文件

通过$.getScript(‘xxxx.js’)获取xxxx.js文件&#xff0c;这时的ajax是一个get请求的状态&#xff0c;如果进行了入参data的赋值那么他就会跟在url后面,同理获取json文件&#xff0c;css文件。 一开始没想起这茬。。。

使用PostgreSQL创建高级搜索引擎

​本文我们将探索PostgreSQL中的全文搜索功能&#xff0c;并研究我们能够复制多少典型搜索引擎功能。 如果您想跟随并尝试示例查询&#xff08;我们建议这样做&#xff0c;这样更有趣&#xff09;&#xff0c;可以使用来自Kaggle的Wikipedia电影情节数据集执行代码示例。要导入…

C++day4 (拷贝构造函数、拷贝赋值函数、匿名对象、友元函数、常成员函数、常对象、运算符重载)

#include <iostream> #include <cstring> using namespace std;class mystring { private:char *str; //记录C风格字符串int size; //记录字符串的实际长度public://无参构造mystring():size(10){strnew char[size];//构造出一个长度为10的字符串strcpy(str,&…

第七章嵌套矢量中断控制器(Cortex-M7 Processor)

目录 第七章嵌套矢量中断控制器 7.1关于NVIC 7.2NVIC功能描述 7.2.1低功耗模式 7.2.2电平与脉冲中断 7.3NVIC程序员模型 7.3.1中断控制器类型寄存器 第七章嵌套矢量中断控制器 本章描述了嵌套矢量中断控制器(NVIC)。它包含以下部分: 关于NVIC在7-2页。NVIC功能描述见第7-…

【软考】系统架构设计风格分类的个人理解

个人适当学习了软考系统架构设计师中关于系统架构设计相关的内容&#xff0c;梳理了一下相关信息。 常见架构类型和常见分类 常见的软考中出现的系统架构列举如下&#xff1a; 分层架构管道-过滤器架构客户端-服务器架构模型-视图-控制器架构&#xff0c;即MVC架构事件驱动架…

Meta 最新发布 LLaMA 2(允许商业化)

文章目录 Llama 2 模型介绍Llama 2的核心点Llama 2的测评结果Llama 2的预训练预处理数据预训练设置和模型架构 Llama-2-chat 模型介绍Llama-2-chat 模型在帮助性和安全性上的表现Llama-2-chat 模型的训练过程 Llama 2 模型介绍 2023年7月18日&#xff0c;Meta 发布了Llama 2&a…

字节跳动后端面试,笔试部分

背景 笔者在刷B站的时候&#xff0c;看到了一个关于面试的实录&#xff0c;前半段是八股文&#xff0c;后半段是笔试部分&#xff0c;感觉笔试部分的题目还是挺有意思的&#xff0c;特此记录一下。 笔试部分 问题1&#xff1a;SQL 这题考的是 union all 的用法&#xff0c;在…

流程工业停机的实际成本

流程制造工厂面临着避免停机的巨大压力&#xff0c;因为这可能会严重影响企业的整体生产力、盈利能力和声誉。企业对计划外停机的原因和成本了解得越多&#xff0c;就能做更多的事情来帮助降低停机的发生率&#xff0c;并在停机发生时更好地做好应对准备。 图.石油炼化工厂&…

在Redis主从系统中使用哨兵

一、什么是哨兵 Redis的哨兵&#xff08;Sentinel&#xff09;是Redis分布式系统中的一种特殊角色&#xff0c;用于监控和管理Redis主从复制架构中的主节点&#xff08;master&#xff09;和从节点&#xff08;slave&#xff09;。 哨兵的主要功能是确保Redis系统的高可用性。它…

学校教室巡课,为何你总是出错?

教育是社会进步和个人发展的重要基石&#xff0c;而教师的教学质量和专业能力直接关系着教育的成效和学生的学习成果。为了促进教师的专业发展和提高教学质量&#xff0c;在线巡课系统应运而生。 通过在线巡课系统&#xff0c;巡课者可以远程观察教师的授课过程&#xff0c;并提…