王道考研数据结构代码总结(第八章)

news2024/11/17 16:18:08

目录

  • 排序
    • 插入排序
      • 直接插入排序
      • 折半插入
      • 希尔排序
      • 链表的插入排序
      • 插入类排序总结
    • 交换排序
      • 冒泡排序
      • 快速排序
    • 选择排序
      • 简单选择排序
      • 堆排序
        • 堆的插入
        • 堆的删除
    • 归并排序
    • 基数排序


本文包含王道考研讲课中所涉及的数据结构中的所有代码,当PPT代码和书上代码有所区别时以咸鱼的PPT为主,个人认为PPT上的代码比王道书上的代码要便于理解,此外,本博客也许会补充一些额外的代码进来(不仅受限于王道考研),408中冷门考点频出,应该会囊括所有涉及到的代码,这也是我的DS的第二轮复习,希望与大家共勉之。

DS的后四章只有最后一章(排序)涉及大量的代码,而树,图,查找这三章,对于概念的考察比较深入,故本文对于前三章也会进行概念上的整理,代码的话也同样会全部给出。

(2023/06/27)由于博客体量问题,本博客只会总结第八章【排序】的知识点与代码

相关文章:
王道考研数据结构代码总结(前四章)
王道考研数据结构代码总结(第五章)
王道考研数据结构代码总结(第六章)


排序

插入排序

直接插入排序

算法思想:每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,直到全部记录插入完成。

元素不会在一次操作中就到达最终的位置

核心代码(不带哨兵):

void InsertSort(int A[], int n){
    for (int i = 1; i < n; i ++ ){
        if (A[i - 1] > A[i]){ // 前n-1个数已经是从小到大了,现在出现了比最大的数A[i-1]还小的数,所以要移动
            int temp = A[i], j;
            for (j = i - 1; j >= 0 && A[j] > temp; j -- )  // 开始遍历0~n-1的数,如果当前数比A[i]要大的话,证明A[i]还没有找到它的位置,退出循环的时候,j所指向的数的后面应该是插入点
                A[j + 1] = A[j];     // 边搜边移动这些比A[i]大的数(往后移动一格)
            A[j + 1] = temp;         // j+1所指的位置就是插入点,插入A[i]
        }
    }
}

可运行代码(不带哨兵):

#include <stdio.h>

const int N = 55;

int A[N] = {5, 7, 9, 1, 4, 6, 8, 3};;

void InsertSort(int A[], int n){
    for (int i = 1; i < n; i ++ ){
        if (A[i - 1] > A[i]){ 
            int temp = A[i], j;
            for (j = i - 1; j >= 0 && A[j] > temp; j -- )  
                A[j + 1] = A[j];    
            A[j + 1] = temp;         
        }
    }
}

int main()
{
    InsertSort(A, 8);
    for (int i = 0; i < 8; i ++ ) printf("%d ", A[i]);
    
    return 0;
}

核心代码(带哨兵):

void InsertSort(int A[], int n){
    for (int i = 2; i <= n; i ++ ){
        if (A[i - 1] > A[i]){
            A[0] = A[i];
            int j;
            for (j = i - 1; A[0] < A[j]; j -- )
                A[j + 1] = A[j];
            A[j + 1] = A[0];
        }
    }
}

哨兵就是把数组往后移了一格(空出来 A[0] 当哨兵,效果等同于不带哨兵的 temp,其优点在于每次循环不需要判断 j >= 0 (因为必定有 j=0 时, A[0] == A[j] ,即不满足 A[0] < A[j] 从而退出循环)

可运行代码(带哨兵):

#include <stdio.h>

const int N = 55;

int A[N] = {0, 5, 7, 9, 1, 4, 6, 8, 3};;

void InsertSort(int A[], int n){
    for (int i = 2; i <= n; i ++ ){
        if (A[i - 1] > A[i]){
            A[0] = A[i];
            int j;
            for (j = i - 1; A[0] < A[j]; j -- )
                A[j + 1] = A[j];
            A[j + 1] = A[0];
        }
    }
}

int main()
{
    InsertSort(A, 8);
    for (int i = 1; i <= 8; i ++ ) printf("%d ", A[i]);
    
    return 0;
}

总结:

1.空间复杂度: O ( 1 ) O(1) O(1)
2.时间复杂度: O ( n 2 ) O(n^2) O(n2)
3.由于我们在比较的时候仅仅是将比 A[i] 大的进行交换,所以算法是的算法是稳定
4.算法中的元素在一趟无法确定其最终位置

折半插入

思路:先用折半查找找到应该插入的位置,再移动元素

核心代码(带哨兵):

void InsertSort(int A[], int n){
    for (int i = 2; i <= n; i ++ ){
        A[0] = A[i];    // 哨兵
        int low = 1, high = i - 1;
        while (low <= high){
            int mid = (low + high) / 2;
            if (A[mid] > A[0]) high = mid - 1;   // 这里需要记一下是先看high的更新
            else low = mid + 1;
        }
        for (int j = i - 1; j >= high; j -- )    // 这里也需要记一下j是拿high为界
            A[j + 1] = A[j];
        A[high + 1] = A[0];
    }
}

可运行代码(带哨兵):

#include <stdio.h>

const int N = 55;

int A[N] = {0, 5, 7, 9, 1, 4, 6, 8, 3};;

void InsertSort(int A[], int n){
    for (int i = 2; i <= n; i ++ ){
        A[0] = A[i];   
        int low = 1, high = i - 1;
        while (low <= high){
            int mid = (low + high) / 2;
            if (A[mid] > A[0]) high = mid - 1; 
            else low = mid + 1;
        }
        for (int j = i - 1; j >= high; j -- )   
            A[j + 1] = A[j];
        A[high + 1] = A[0];
    }
}

int main()
{
    InsertSort(A, 8);
    for (int i = 1; i <= 8; i ++ ) printf("%d ", A[i]);
    
    return 0;
}

总结:

1.空间复杂度: O ( 1 ) O(1) O(1)
2.时间复杂度: O ( n 2 ) O(n^2) O(n2)
3.算法是稳定
4.算法中的元素在一趟无法确定其最终位置

希尔排序

先将待排序表分割成若干形如 L[i, i +d, i + 2d.... , i + kd]的“特殊”子表,对各个子表分别进行直接插入排序。缩小增量 d d d,重复上述过程,直到 d = 1 为止。

核心代码(不带哨兵):

void ShellSort(int A[], int n){
    // A[0]是暂存单元,不是哨兵
    for (int d = n / 2; d >= 1; d = d / 2)   // 步长
        for (int i = d + 1; i <= n; i ++ )   // 它是所有的有序增量子表"交替"的进行插入排序
            if (A[i] < A[i - d]){            // 将A[i]插到有序增量子表中
                A[0] = A[i];
                int j;
                for (j = i - d; j > 0 && A[0] < A[j]; j -= d) // 查找插入位置
                    A[j + d] = A[j];  
                A[j + d] = A[0];        // 插入
            }
}

可运行代码(不带哨兵):

#include <stdio.h>

const int N = 55;

int A[N] = {0, 5, 7, 9, 1, 4, 6, 8, 3};;

void ShellSort(int A[], int n){
    for (int d = n / 2; d >= 1; d = d / 2)   
        for (int i = d + 1; i <= n; i ++ )  
            if (A[i] < A[i - d]){           
                A[0] = A[i];
                int j;
                for (j = i - d; j > 0 && A[0] < A[j]; j -= d) 
                    A[j + d] = A[j];  
                A[j + d] = A[0];       
            }
}

int main()
{
    ShellSort(A, 8);
    for (int i = 1; i <= 8; i ++ ) printf("%d ", A[i]);
    
    return 0;
}

总结:

1.空间复杂度: O ( 1 ) O(1) O(1)
2.时间复杂度: O ( n 2 ) O(n^2) O(n2)[最坏], O ( n 1.3 ) O(n^{1.3}) O(n1.3)[ n n n在某个范围内时]
3.算法是不稳定
4.算法中的元素在一趟无法确定其最终位置

链表的插入排序

移动元素的次数变少了,但是关键字对比的次数依然是 O ( n 2 ) O(n^2) O(n2)数量级,整体来看时间复杂度依然是 O ( n 2 ) O(n^2) O(n2)

对链表的插入排序,只能使用直接插入排序

插入类排序总结

1.空间复杂度: O ( 1 ) O(1) O(1)
2.时间复杂度:平均 O ( n 2 ) O(n^2) O(n2),最好(原本有序) O ( n ) O(n) O(n),最坏(原本逆序) O ( n 2 ) O(n^2) O(n2)
3.算法是稳定的(除希尔排序)
4.算法中的元素在一趟无法确定其最终位置

交换排序

冒泡排序

从后往前(或从前往后)两两比较相邻元素的值,若为逆序(即A[i - 1] > A[i]),则交换它们,直到序列比较完。称这样过程为“一趟”冒泡排序。

冒泡排序过程中的优化:若一趟排序没有发生交换,那么证明此时已经整体有序。

核心代码:

void sawp(int &a, int &b){
    int temp = a;
    a = b;
    b = temp;
}

void BubbleSort(int A[], int n){
    for (int i = 0; i < n - 1; i ++ ){      // i所指位置之前的元素都已"有序"
        bool flag = false;
        for (int j = n - 1; j > i; j -- ){  // 开始冒泡
            if (A[j - 1] > A[j]){           // 只有在这种交换条件下才是稳定的
                swap(A[j], A[j - 1]);
                flag = true;
            }
        }
        if (flag == false) return;          // 遍历完一趟之后没有发生交换,说明表已有序
    }
}

可运行代码:

#include <stdio.h>

const int N = 55;

int A[N] = {5, 7, 9, 1, 4, 6, 8, 3};;

void swap(int &a, int &b){
    int temp = a;
    a = b;
    b = temp;
}

void BubbleSort(int A[], int n){
    for (int i = 0; i < n; i ++ ){
        bool flag = false;
        for (int j = n - 1; j > i; j -- ){
            if (A[j - 1] > A[j]){
                swap(A[j], A[j - 1]);
                flag = true;
            }
        }
        if (flag == false) return;
    }
}

int main()
{
    BubbleSort(A, 8);
    for (int i = 0; i < 8; i ++ ) printf("%d ", A[i]);
    
    return 0;
}

总结:

1.空间复杂度: O ( 1 ) O(1) O(1)
2.时间复杂度: O ( n 2 ) O(n^2) O(n2)
3.算法是稳定
4.算法中的元素在一趟可以确定其最终位置
5.可以用于链表(从前往后"冒泡",每一趟将更大的元素"冒"到链尾)

快速排序

算法思想:在待排序表 L[1...n] 中任取一个元素 pivot 作为枢轴(或基准,通常取首元素),通过一趟排序将待排序表划分为独立的两部分 L[1...k-1]L[k+1...n],使得 L[1...k-1]中的所有元素小于pivotL[k+1...n] 中的所有元素大于等于 pivot,则 pivot 放在了其**最终**位置 L(k) 上,这个过程称为一次“划分”。然后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在了其最终位置上。

核心代码:(必背)

// 用第一个元素将待排序序列划分为左右两个部分
int Partition(int A[], int low, int high){
    int pivot = A[low];    // 选取第一个元素作为枢轴
    while (low < high){    // 用low和high搜索pivot的最终位置
		while (low < high && A[high] >= pivot) -- high;
    	A[low] = A[high];      // 比枢轴小的元素移动到左端
    	while (low < high && A[low] <= pivot) ++ low;
    	A[high] = A[low];  
    }  
    A[low] = pivot;
    return low;            // 返回存放枢轴的最终位置
}

// 快速排序
void QuickSort(int A[], int low, int high){
    if (low < high){                               // 递归跳出条件
        int pivotpos = Partition(A, low, high);    // 划分,并把枢轴元素放到它最终的位置上
        QuickSort(A, low, pivotpos - 1);           // 划分左子表
        QuickSort(A, pivotpos + 1, high);          // 划分右子表
    }
}

可运行代码:

#include <stdio.h>

const int N = 55;

int A[N] = {5, 7, 9, 1, 4, 6, 8, 3};;

int Partition(int A[], int low, int high){
    int pivot = A[low];    
    while (low < high){    
		while (low < high && A[high] >= pivot) -- high;
    	A[low] = A[high];      
    	while (low < high && A[low] <= pivot) ++ low;
    	A[high] = A[low];  
    }  
    A[low] = pivot;
    return low;            
}

void QuickSort(int A[], int low, int high){
    if (low < high){                             
        int pivotpos = Partition(A, low, high);    
        QuickSort(A, low, pivotpos - 1);           
        QuickSort(A, pivotpos + 1, high);          
    }
}

int main()
{
    QuickSort(A, 0, 7);
    for (int i = 0; i < 8; i ++ ) printf("%d ", A[i]);
    
    return 0;
}

总结:

1.空间复杂度: O ( l o g 2 n ) O(log_2n) O(log2n)[最好], O ( n ) O(n) O(n)[最坏]
2.时间复杂度: O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)[最好], O ( n 2 ) O(n^2) O(n2)[最坏]
3.最坏情况分析:每一次枢轴元素的选取之后都将排序序列划分为很不均匀的两个部分,即导致递归层数增加,算法效率变低【若初始序列为有序逆序,则快速排序的性能最差
4.最好情况分析:每一次选中的枢轴元素都可以将待排序列划分为均匀的两个部分,这样递归深度最小,算法效率最高
5.排序算法的优化思路:尽可能选取可以把数据中分的枢轴元素。
6.快速排序是所有内部排序算法中平均性能最优的排序算法
7.算法是不稳定
8.算法中的元素的 “一次划分” 可以确定其最终位置,“一趟排序” 也许可以确定多个元素的最终位置
9.不可以应用于链表

选择排序

简单选择排序

每一趟在待排序元素中选取关键字最小的元素加入有序子序列,即 n n n 个元素的简单排序需要 n − 1 n-1 n1 趟处理(最后一个元素不用再处理)。

核心代码:

void swap(int &a, int &b){
    int temp = a;
    a = b;
    b = temp;
}

void SelectSort(int A[], int n){
    for (int i = 0; i < n - 1; i ++ ){
        int min = i;
        for (int j = i + 1; j < n; j ++ )
            if (A[j] < A[min]) min = j;
        if (min != i) swap(A[min], A[i]);
    }
}

可运行代码:

#include <stdio.h>

const int N = 55;

int A[N] = {5, 7, 9, 1, 4, 6, 8, 3};;

void swap(int &a, int &b){
    int temp = a;
    a = b;
    b = temp;
}

void SelectSort(int A[], int n){
    for (int i = 0; i < n - 1; i ++ ){
        int min = i;
        for (int j = i + 1; j < n; j ++ )
            if (A[j] < A[min]) min = j;
        if (min != i) swap(A[min], A[i]);
    }
}

int main()
{
    SelectSort(A, 8);
    for (int i = 0; i < 8; i ++ ) printf("%d ", A[i]);
    
    return 0;
}

总结:

1.空间复杂度: O ( 1 ) O(1) O(1)
2.时间复杂度: O ( n 2 ) O(n^2) O(n2)
3.算法是不稳定
4.算法中的元素在一趟可以确定其最终位置
5.无论有序、逆序、还是乱序,一定需要 n − 1 n-1 n1 趟处理
6.可以用于链表

堆排序

若n个关键字序列L[1…n]满足下面某一条性质,则称为堆(Heap):
①若满足:L(i) ≥ L(2i)L(i) ≥ L(2i + 1) (1 ≤ i ≤ n / 2) ——大根堆(大顶堆) 【父节点比孩子们都大】
②若满足:L(i) ≤ L(2i)L(i) ≤ L(2i + 1) (1 ≤ i ≤ n / 2) ——小根堆(小顶堆) 【父节点比孩子们都小】

建立大根堆:

思路:把所有非终端结点 i <= ⌊n / 2⌋ 都检查一遍(从 i == n / 2 查到 i == 1),是否满足大根堆的要求,如果不满足,则进行调整
检查当前结点是否满足根 左、右,若不满足,将当前结点与**更大的一个孩子**互换
更小的元素下坠,可能会导致下一层的子树不符合大根堆的规则
若元素互换破坏了下一级的堆,则采用相同的方法继续往下调整(小元素不断“下坠”)

**注:**堆的建立和堆的插入是不一样的,堆的建立是查非终端结点并与孩子进行交换(自上而下),堆的插入则是先插入到堆的末尾后看是否需要向上调整(自下而上)

基于大根堆进行排序:

堆排序:每一趟将堆顶元素加入有序子序列(与待排序序列中的最后一个元素交换),即选择排序:每一趟在待排序元素中选取关键字最大的元素加入有序子序列,并将待排序元素序列再次调整为大根堆(小元素不断“下坠”)

**总结1:**大根堆就是每一个父节点都比比左右孩子大的树,即最大值必为根节点,对大根堆的排序其实得到的是一个递增的序列,每次将根结点(目前未排序列中最大的元素)取下之后与未排序列中的最后一个元 a 素进行交换(即数组的最后几位才是已经有序的部分),然后将元素 a 执行 down 操作使得树(未排序的元素)仍然符合堆的结构

总结2:一个结点每下坠一层最多需要对比 2 2 2 次关键字,若树高为 h,某结点在第 i 层,则将这个结点向下调整最多只需要“下坠” h-i 层,关键字对比次数不超过 2(h-i),n个结点的完全二叉树树高 h = ⌊ l o g 2 n ⌋ + 1 h=⌊log_2n⌋+1 h=log2n+1,建堆的时间复杂度为 O ( n ) O(n) O(n),每一趟下坠的时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n)
1.堆排序的时间复杂度 O ( n ) + O ( n l o g 2 n ) = O ( n l o g 2 n ) O(n) + O(nlog_2n)=O(nlog_2n) O(n)+O(nlog2n)=O(nlog2n)
2.堆排序的空间复杂度为 O ( 1 ) O(1) O(1)
3.若左右孩子一样大,则优先和左孩子交换
4.堆排序是不稳定
5.算法中的元素在一趟可以确定其最终位置
6.基于大根堆得到的是递增序列,基于小根堆得到的是递减序列

堆的插入

对于根堆,新元素放到表尾,与父节点对比,若新元素比父节点更小,则将二者互换。新元素就这样一路“上升”,直到无法继续上升为止

堆的删除

被删除的元素用堆底元素替代,然后让该元素不断“下坠”,直到无法下坠为止

归并排序

归并:把两个或多个已经有序的序列合并成一个

只剩一个子表未合并时,可以将该表中剩余元素全部加到总表

二路归并:二合一,每选出一个小元素注需对比关键字 1 1 1
四路归并:四合一,每选出一个小元素注需对比关键字 3 3 3

结论 m m m 路归并,每选出一个元素需要对比关键字 m − 1 m-1 m1

核心代码:

int *B = (int *)malloc(n * sizeof(int));   // 辅助数组B

// A[low...mid]和A[mid+1...high]各自有序,将两个部分归并
void Merge(int A[], int low, int mid, int high){ 
    for (int k = low; k <= high; k ++ )
        B[k] = A[k];
    int i, j, k;
    for (i = low, j = mid + 1, k = i; i <= mid && j <= high; k ++ ){
        if (B[i] <= B[j])       // 两个元素相等的时候优先去排靠前面那个(稳定性)
            A[k] = B[i ++];
        else
            A[k] = B[j ++];
    }
    while (i <= mid) A[k ++] = B[i ++];
    while (j <= high) A[k ++] = B[j ++];
}

void MergeSort(int A[], int low, int high){
    if (low < high){
        int mid = (low + high) / 2;     // 从中间划分
        MergeSort(A, low, mid);         // 右边归并
        MergeSort(A, mid + 1, high);    // 左边归并
        Merge(A, low, mid, high);       // 归并
    }
}

可运行代码:

#include <stdio.h>
#include <cstdlib>

const int N = 55;

int A[N] = {5, 7, 9, 1, 4, 6, 8, 3};;

int *B = (int *)malloc(10 * sizeof(int));   // 辅助数组B

// A[low...mid]和A[mid+1...high]各自有序,将两个部分归并
void Merge(int A[], int low, int mid, int high){ 
    for (int k = low; k <= high; k ++ )
        B[k] = A[k];
    int i, j, k;
    for (i = low, j = mid + 1, k = i; i <= mid && j <= high; k ++ ){
        if (B[i] <= B[j])       // 两个元素相等的时候优先去排靠前面那个(稳定性)
            A[k] = B[i ++];
        else
            A[k] = B[j ++];
    }
    while (i <= mid) A[k ++] = B[i ++];
    while (j <= high) A[k ++] = B[j ++];
}

void MergeSort(int A[], int low, int high){
    if (low < high){
        int mid = (low + high) / 2;     // 从中间划分
        MergeSort(A, low, mid);         // 右边归并
        MergeSort(A, mid + 1, high);    // 左边归并
        Merge(A, low, mid, high);       // 归并
    }
}

int main()
{
    MergeSort(A, 0, 7);
    for (int i = 0; i < 8; i ++ ) printf("%d ", A[i]);
    
    return 0;
}

总结:n个元素的2路归并排序

1.空间复杂度: O ( n ) O(n) O(n),来自于辅助数组 B
2.归并趟数 O ( ⌈ l o g 2 n ⌉ ) O(⌈log_2n⌉) O(⌈log2n⌉)
3.每趟归并的时间复杂度为 O ( n ) O(n) O(n),算法的时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
4.算法中的元素在一趟不可以确定其最终位置
5.算法是稳定

基数排序

比如要求得到关键字“递减”的有序序列

第一趟:

初始态:

在这里插入图片描述

中间状态:
在这里插入图片描述
结束态(第一趟):
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述第一趟收集结束:

在这里插入图片描述
第二趟:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
第三趟:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基数,如上例中十进制的基数就是10,即每一位可以取 [ 0 , 9 ] [0,9] [0,9],初始化的队列需要有 r r r

d d d元组,如上例中 d = 3,即我们分为个,十,百,三个不同的权值。
在这里插入图片描述总结:

1.空间复杂度: O ( r ) O(r) O(r),需要 r r r 个辅助队列
2.时间复杂度:一趟分配 O ( n ) O(n) O(n),收集一个队列只需 O ( 1 ) O(1) O(1) 时间,一趟收集 r r r 个队列共 O ( r ) O(r) O(r),总共 d d d 趟分配、收集,总的时间复杂度 = O ( d ( n + r ) ) =O(d(n+r)) =O(d(n+r))
3.算法是稳定
4.算法中的元素在一趟不可以确定其最终位置
基数排序擅长解决的问题:

①数据元素的关键字可以方便地拆分为 d d d 组,且 d d d 较小;反例:给5个人的身份证号排序
②每组关键字的取值范围不大,即 r r r 较小;反例:给中文人名排序
③数据元素个数 n n n 较大;擅长:给十亿人的身份证号排序

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

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

相关文章

“智慧”北京,人工智能引领“新风尚”

原创 | 文 BFT机器人 北京时间&#xff0c;9月15日&#xff0c;北京人工智能产业峰会暨中关村科学城科创大赛颁奖典礼在北京中关村举行&#xff0c;同时惠阳还举行了“中关村人工智能大模型产业集聚区”启动建设的揭牌仪式。 此次大会围绕北京AI产业的建设与发展&#xff0c;各…

一篇文章彻底弄懂单调栈!!!

前言 最近梳理完中间件后荔枝一边学项目一边刷算法&#xff0c;一刷了代码随想录中的字符串、双指针、栈和队列以及单调栈。其中感觉比较有难度的还是单调栈嘿&#xff0c;因此有必要(水)梳理一篇文章来复盘一下单调栈的相关知识~ 希望复盘完后可以有所收获&#xff01; 文章目…

某音网页端 X-Bogus 参数

逆向目标 目标&#xff1a;某音网页端用户信息接口 X-Bogus 参数 接口&#xff1a;aHR0cHM6Ly93d3cuZG91eWluLmNvbS9hd2VtZS92MS93ZWIvdXNlci9wcm9maWxlL290aGVyLw 什么是 JSVMP&#xff1f; JSVMP 全称 Virtual Machine based code Protection for JavaScript&#xff0c;即 …

根据条件关闭软件

使用下载工具时&#xff0c;经常出现磁盘空间已满&#xff0c;无法下载的情况。 使用shell写一个监控&#xff0c;每2分钟执行一次。判断当前磁盘的空间&#xff0c;低于2G时&#xff0c;关闭下载软件。 获取空间大小 ➜ ~ df -h …

如何运用API接口获取淘宝1688京东商品数据:从入门到实践

一、引言 随着电子商务的飞速发展&#xff0c;许多电商平台提供了API接口&#xff0c;允许开发者获取商品数据&#xff0c;以创建各种创新的应用。本文将详细介绍如何使用API接口获取商品数据&#xff0c;并通过代码示例进行演示。 二、API接口概述 1.API接口定义 API&…

【校招VIP】数据库理论之数据库范式

考点介绍&#xff1a; 范式是指关系数据库中的一种数据结构设计规范&#xff0c;用于规范关系型数据库中数据的存储方式&#xff0c;目的是为了消除冗余数据&#xff0c;减少数据的重复性&#xff0c;提高数据的一致性、完整性和正确性&#xff0c;避免数据的不一致性和冲突 …

三相组合式过电压保护器试验

三相组合式过电压保护器试验 试验目的 三相组合式过电压保护器主要分为有带串联间隙过压保护器和无间隙过压保护器两大类&#xff0c;其试验项目内容要求分别使用高压工频交流和高压直流电源。 三相组合式过电压保护器试验&#xff0c;主要是为了及早发现设备内部绝缘受潮及…

华为云云耀云服务器L实例评测|云耀云服务器L实例部署Dashdot服务器仪表盘

华为云云耀云服务器L实例评测&#xff5c;云耀云服务器L实例部署Dashdot服务器仪表盘 一、云耀云服务器L实例介绍二、Dashdot介绍2.1 Dashdot简介2.2 开发环境要求2.3 Yarn介绍 三、本次实践介绍3.1 本次实践简介3.2 本次环境规划 四、检查服务器环境4.1 购买云耀云服务器L实例…

Android中的缓存策略:LruCache和DiskLruCache

Android中的缓存策略&#xff1a;LruCache和DiskLruCache 导言 本篇文章主要是介绍Android中内置的两个缓存类的原理。所谓缓存&#xff0c;就是将获取的数据保存下来以便下次继续使用&#xff0c;这种技术尤其在网络请求和图片加载中有用&#xff0c;可以显著地提升App的性能…

SSM - Springboot - MyBatis-Plus 全栈体系(十三)

第三章 MyBatis 一、MyBatis 简介 1. 简介 MyBatis 最初是 Apache 的一个开源项目 iBatis, 2010 年 6 月这个项目由 Apache Software Foundation 迁移到了 Google Code。随着开发团队转投 Google Code 旗下&#xff0c; iBatis3.x 正式更名为 MyBatis。代码于 2013 年 11 月迁…

大模型训练显存优化推理加速方案

当前的深度学习框架大都采用的都是fp32来进行权重参数的存储&#xff0c;比如Python float的类型为双精度浮点数fp64&#xff0c;pytorch Tensor的默认类型为单精度浮点数fp32。随着模型越来越大&#xff0c;加速训练模型的需求就产生了。在深度学习模型中使用fp32主要存在几个…

R语言贝叶斯MCMC:GLM逻辑回归、Rstan线性回归、Metropolis Hastings与Gibbs采样算法实例...

原文链接&#xff1a;http://tecdat.cn/?p23236 在频率学派中&#xff0c;观察样本是随机的&#xff0c;而参数是固定的、未知的数量&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 相关视频 什么是频率学派&#xff1f; 概率被解释为一个随机过程的许多观测…

Spark SQL【电商购买数据分析】

Spark 数据分析 &#xff08;Scala&#xff09; import org.apache.spark.rdd.RDD import org.apache.spark.sql.{DataFrame, SparkSession} import org.apache.spark.{SparkConf, SparkContext}import java.io.{File, PrintWriter}object Taobao {case class Info(userId: Lo…

最该考的高含金量计算机证书盘点(文末领资料)

谈到大学规划&#xff0c;不少过来人都会建议萌新们在课余时间多多考证&#xff0c;俗话说的好“证多不压身”&#xff0c;今天我们就来聊一聊&#xff0c;计算机相关专业的大学生&#xff0c;有哪些证书可以考&#xff1f; 首先&#xff0c;不得不提的就是全国计算机二级考试…

web:[ACTF2020 新生赛]Exec

背景知识 命令执行漏洞 linux命令 题目 打开题目&#xff0c;页面显示的是一个ping 尝试一下 查看源代码发现 尝试ping一下百度 由题目名可知这道题关于exec&#xff08;命令执行&#xff09;&#xff0c;这里需要联想到可以多条命令执行 输入baidu.com;ls 尝试;号是否能够…

从统计语言模型到预训练语言模型---预训练语言模型(Transformer)

预训练模型的概念在计算机视觉领域并不陌生&#xff0c; 通常我们可以在大规模图像数据集上预先训练出一个通用 模型&#xff0c; 之后再迁移到类似的具体任务上去&#xff0c; 这样在减少对图像样本需求的同时&#xff0c; 也加速了模型的开发速度。计 算机视觉领域采用 Image…

互联网医院系统|互联网医院软件功能与广阔应用领域

随着科技的不断进步和人们对健康需求的提高&#xff0c;互联网医院已经成为当今医疗领域的热点话题。作为一种融合了互联网和医疗服务的创新模式&#xff0c;互联网医院带来了许多便利和改变。本文将详细介绍互联网医院的软件功能、应用范围以及未来的发展趋势。 互联网医院通过…

【计算机毕业设计】基于SpringBoot+Vue电影在线订票系统的开发与实现

博主主页&#xff1a;一季春秋博主简介&#xff1a;专注Java技术领域和毕业设计项目实战、Java、微信小程序、安卓等技术开发&#xff0c;远程调试部署、代码讲解、文档指导、ppt制作等技术指导。主要内容&#xff1a;毕业设计(Java项目、小程序等)、简历模板、学习资料、面试题…

机器学习笔记:概念对比——损失函数,代价函数,目标函数

损失函数 Loss Function 通常是针对单个训练样本而言 给定一个模型输出 和一个真实值y &#xff0c;损失函数是 代价函数 Cost Function 通常是针对整个训练集&#xff08;或者在使用 mini-batch gradient descent 时一个 mini-batch&#xff09;的总损失 目标函数 Objec…

备考cisp拿证,收藏这一篇就够了

为什么要考CISP 认证机构&#xff1a;中国信息安全测评中心&#xff0c;是中央批准成立的国家权威信息安全测评机构&#xff0c;CISP是当之无愧的国家级认证&#xff0c;是国内对信息安全从业人员资质能力的最高认可。 持证人数&#xff1a;在信息安全行业&#xff0c;持有CI…