数据结构--线段树--洛谷模板线段树1-2

news2024/10/5 16:24:34
写在前面:
学习之前需要知道以下内容:
1. 递归
2. 二叉树

文章目录

  • 线段树
    • 介绍
    • 用途
    • 建树
    • 修改
      • 单点修改
      • 区间修改
    • 查询
  • 代码实现。
    • 建树
    • 更新
    • lazy传递
    • 查询
    • 优化一下
  • 练习
    • 洛谷 P3372 【模板】线段树 1
      • 题目描述
      • 题解
    • 【模板】线段树 2
      • 题目描述
      • 题解

线段树

介绍

线段树是一种二叉树,也可以归类为二叉搜索树。可以将区间的修改、维护和查询的时间复杂度优化为log级别的。

构成
如一段1-6区间
在这里插入图片描述
可以分开为1-3和4-6然后继续放下拆分直到拆分为一个数的时候。
也就可以用树的标识。
在这里插入图片描述

用途

区间的加法

也可以结合 扫描线 用于二维面积并问题。

建树

存储方式我们使用数组来进行建树。这个要用到的就是二叉树的知识了。(对于 i i i 下标节点,左儿子下标为 2 ∗ i 2*i 2i,右儿子下标为 2 ∗ i + 1 2*i +1 2i+1 父节点下标为 i / / 2 i//2 i//2

修改

单点修改

通过二叉树查询下标在进行修改。(二叉树查询为log级别)
然后更新大区间的值。

在这里插入图片描述
如修改下标2为数字3那么则需要更新为
在这里插入图片描述

区间修改

如将1-5的的值+2
则下面部分都需要+2
在这里插入图片描述
但是这样好像也没有啥优势,和数组一个个+2是一样的甚至,还多一些。

我们可以在这加一个缓存技术。
1-5就只需要更新这2个就可以了,然后在其lazy数组上设置为+2.
更新的值为长度*加的值
这里 10 10 10 就是 + 2 ∗ 3 +2*3 +23 3 3 3 加上 2 ∗ 2 2*2 22
在这里插入图片描述
每次当要用到子节点的时候就需要将lazy标记下存了。
如现在 [ 1 − 3 ] [1-3] [13]的标记为 2 2 2 当我们要用到 [ 1 ] [1] [1]的时候
[ 3 ] [3] [3]就+2
[ 1 − 2 ] [1-2] [12]也+2
[ 1 − 3 ] [1-3] [13] 设置为0
然后继续递归

查询

这里和二叉树查询一样
不过需要注意的是。lazy标记下存的操作,在这里也是需要的。

如查询 [ 1 − 2 ] [1-2] [12]的值。
首先在 [ 1 − 6 ] [1-6] [16]的左,然后发现在 [ 1 − 3 ] [1-3] [13]的左,但是lazy为+2
所以 l z a y [ 1 − 3 ] = 0 , l z a y [ 1 − 2 ] = 2 , l a z y [ 3 ] = 2 lzay[1-3] = 0,lzay[1-2]=2,lazy[3]=2 lzay[13]=0,lzay[12]=2,lazy[3]=2.
所以 [ 1 − 2 ] = l z a y [ 1 − 2 ] + [ 1 − 2 ] = 2 + 7 = 9 [1-2] = lzay[1-2]+[1-2] = 2+7=9 [12]=lzay[12]+[12]=2+7=9

代码实现。

建树

使用递归来实现

    /**
     * 建树
     * @param l 左边界
     * @param r 右边界
     * @param pos 当前位置
     * @return 当前位置的值
     */
    public long build(int l, int r, int pos) {
        if (l == r) {
            return tree[pos] = mapping[l - 1];
        } else {
            int mid = (l + r) >> 1;
            return tree[pos] = build(l, mid, pos << 1)
                    + build(mid + 1, r, pos << 1 | 1);
        }
    }

更新

每次从根节点开始进行。
如果查询和边界没有交点的时候停止递归
在这里插入图片描述
如果完全包括,那么就将这个区间更新。
更新规则:

  1. 区间值+value*长度
  2. 区间lazy +value

在这里插入图片描述
其他情况就是一部分在一部分不在,那么就进行向子节点查询
注意如果该节点lazy值不为空则需要向下传递。
向下查找完后,需要将子节点添加的值向本节点更新。
在这里插入图片描述

    /**
     * 更新
     * @param l 左边界
     * @param r 右边界
     * @param pos 当前位置
     * @param value 更新值
     * @return 当前位置的值
     */
    public long getUpdate(int l, int r, int pos, int value) {
        if (r < updateL || l > updateR)
            return 0;
        if (l >= updateL && r <= updateR) {
            lazy[pos] += value;
            long v = (long) value * (r - l + 1);
            tree[pos] += v;
            return v;
        } else {
            int mid = (l + r) >> 1;
            updateLazy(l, r, pos, mid);
            long ul = getUpdate(l, mid, pos << 1, value);
            long ur = getUpdate(mid + 1, r, pos << 1 | 1, value);
            tree[pos] += ul + ur;
            return ul + ur;
        }
    }

lazy传递

更新规则如下,

  1. 子节点的lazy设置为本节点的lazy
  2. 子节点数值更新
  3. 本节点lazy设置为0
    /**
     * 更新懒标记
     * @param l 左边界
     * @param r 右边界
     * @param pos 当前位置
     * @param mid 中间位置
     */
    private void updateLazy(int l, int r, int pos, int mid) {
        if (lazy[pos] != 0) {
            lazy[pos << 1] += lazy[pos];
            lazy[pos << 1 | 1] += lazy[pos];
            tree[pos << 1] += lazy[pos] * (mid - l + 1);
            tree[pos << 1 | 1] += lazy[pos] * (r - mid);
            lazy[pos] = 0;
        }
    }

查询

这个没有太多好说的,和更新挺像的
一样需要注意的是lazy值的下移。

    /**
     * 查询
     * @param l 左边界
     * @param r 右边界
     * @param pos 当前位置
     * @return 当前位置的值
     */
    public long getN(int l, int r, int pos) {
        if (l > getR || r < getL)
            return 0;
        if (l >= getL && r <= getR) {
            return tree[pos];
        } else {
            int mid = (l + r) >> 1;
            int i = pos << 1;
            int j = i | 1;
            updateLazy(l,r,pos,mid);
            return getN(l, mid, i) +
                    getN(mid + 1, r, j);
        }
    }

优化一下

emm因为代码是我自己想的,考虑不是特别好。
看到别人的都是把上传单独抽出一个方法,我觉得还是抽出来比较简单明了一些。

public void pushUp(int x) {
    tree[x] = (tree[x << 1] + tree[x << 1 | 1]) % p;
}

然后所有的更新都不需要返回值了
只需要在代码的最后加上一个就可以了

pushUp(pos);

    public void getUpdate(int l, int r, int pos, long value) {
        if (r < updateL || l > updateR) return;
        if (l >= updateL && r <= updateR) {
            tree[pos] = (tree[pos] + value * (r - l + 1)) % p;
            add[pos] = (add[pos] + value) % p;
        } else {
            int mid = (l + r) >> 1;
            updateLazy(l, r, pos, mid);
            getUpdate(l, mid, pos << 1, value);
            getUpdate(mid + 1, r, pos << 1 | 1, value);
            pushUp(pos);
        }
    }

练习

洛谷 P3372 【模板】线段树 1

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  1. 将某区间每一个数加上 k k k
  2. 求出某区间每一个数的和。

输入格式

第一行包含两个整数 n , m n, m n,m,分别表示该数列数字的个数和操作的总个数。

第二行包含 n n n 个用空格分隔的整数,其中第 i i i 个数字表示数列第 i i i 项的初始值。

接下来 m m m 行每行包含 3 3 3 4 4 4 个整数,表示一个操作,具体如下:

  1. 1 x y k:将区间 [ x , y ] [x, y] [x,y] 内每个数加上 k k k
  2. 2 x y:输出区间 [ x , y ] [x, y] [x,y] 内每个数的和。

输出格式

输出包含若干行整数,即为所有操作 2 的结果。

样例 #1

样例输入 #1

5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4

样例输出 #1

11
8
20

提示

对于 30 % 30\% 30% 的数据: n ≤ 8 n \le 8 n8 m ≤ 10 m \le 10 m10
对于 70 % 70\% 70% 的数据: n ≤ 10 3 n \le {10}^3 n103 m ≤ 10 4 m \le {10}^4 m104
对于 100 % 100\% 100% 的数据: 1 ≤ n , m ≤ 10 5 1 \le n, m \le {10}^5 1n,m105

保证任意时刻数列中所有元素的绝对值之和 ≤ 10 18 \le {10}^{18} 1018

【样例解释】

题解


import java.io.*;

public class Main {
    static final StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static final PrintWriter print = new PrintWriter(System.out);

    public static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }

    public static void main(String[] args) throws IOException {
        int n = nextInt();
        int m = nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = nextInt();
        }
        SegmentTrees s = new SegmentTrees(a);
        for (int i = 0; i < m; i++) {
            int j = nextInt();
            if (j == 1) {
                s.update(nextInt(), nextInt(), nextInt());
            } else
                print.println(s.get(nextInt(), nextInt()));
        }
        print.flush();
    }
}

class SegmentTrees {
    private final long[] tree;//线段树
    private final int size;
    private final int[] mapping;
    private final long[] lazy;

    public SegmentTrees(int[] mapping) {
        this.size = mapping.length;
        this.mapping = mapping;
        this.tree = new long[size * 4 + 3];
        this.lazy = new long[size * 4 + 3];
        build(1, size, 1);
    }

    /**
     * 建树
     *
     * @param l   左边界
     * @param r   右边界
     * @param pos 当前位置
     * @return 当前位置的值
     */
    public long build(int l, int r, int pos) {
        if (l == r) {
            return tree[pos] = mapping[l - 1];
        } else {
            int mid = (l + r) >> 1;
            return tree[pos] = build(l, mid, pos << 1)
                    + build(mid + 1, r, pos << 1 | 1);
        }
    }

    public void pushUp(int x) {
        tree[x] = (tree[x << 1] + tree[x << 1 | 1]);
    }

    public void update(int l, int r, int value) {
        this.updateL = l;
        this.updateR = r;
        getUpdate(1, size, 1, value);
    }

    private int updateL;
    private int updateR;

    /**
     * 更新
     *
     * @param l     左边界
     * @param r     右边界
     * @param pos   当前位置
     * @param value 更新值
     * @return 当前位置的值
     */
    public void getUpdate(int l, int r, int pos, int value) {
        if (r < updateL || l > updateR) return;
        if (l >= updateL && r <= updateR) {
            lazy[pos] += value;
            tree[pos] += (long) value * (r - l + 1);
        } else {
            int mid = (l + r) >> 1;
            updateLazy(l, r, pos, mid);
            getUpdate(l, mid, pos << 1, value);
            getUpdate(mid + 1, r, pos << 1 | 1, value);
            pushUp(pos);
        }
    }

    /**
     * 更新懒标记
     *
     * @param l   左边界
     * @param r   右边界
     * @param pos 当前位置
     * @param mid 中间位置
     */
    private void updateLazy(int l, int r, int pos, int mid) {
        if (lazy[pos] != 0) {
            lazy[pos << 1] += lazy[pos];
            lazy[pos << 1 | 1] += lazy[pos];
            tree[pos << 1] += lazy[pos] * (mid - l + 1);
            tree[pos << 1 | 1] += lazy[pos] * (r - mid);
            lazy[pos] = 0;
        }
    }

    public long get(int l, int r) {
        this.getL = l;
        this.getR = r;
        return getN(1, size, 1);
    }

    private int getL;
    private int getR;

    /**
     * 查询
     *
     * @param l   左边界
     * @param r   右边界
     * @param pos 当前位置
     * @return 当前位置的值
     */
    public long getN(int l, int r, int pos) {
        if (l > getR || r < getL)
            return 0;
        if (l >= getL && r <= getR) {
            return tree[pos];
        } else {
            int mid = (l + r) >> 1;
            int i = pos << 1;
            int j = i | 1;
            updateLazy(l, r, pos, mid);
            return getN(l, mid, i) +
                    getN(mid + 1, r, j);

        }
    }
}


【模板】线段树 2

题目描述

如题,已知一个数列,你需要进行下面三种操作:

  • 将某区间每一个数乘上 x x x

  • 将某区间每一个数加上 x x x

  • 求出某区间每一个数的和

输入格式

第一行包含三个整数 n , m , p n,m,p n,m,p,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含 n n n 个用空格分隔的整数,其中第 i i i 个数字表示数列第 i i i 项的初始值。

接下来 m m m 行每行包含若干个整数,表示一个操作,具体如下:

操作 1 1 1: 格式:1 x y k 含义:将区间 [ x , y ] [x,y] [x,y] 内每个数乘上 k k k

操作 2 2 2: 格式:2 x y k 含义:将区间 [ x , y ] [x,y] [x,y] 内每个数加上 k k k

操作 3 3 3: 格式:3 x y 含义:输出区间 [ x , y ] [x,y] [x,y] 内每个数的和对 p p p 取模所得的结果

输出格式

输出包含若干行整数,即为所有操作 3 3 3 的结果。

样例 #1

样例输入 #1

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

样例输出 #1

17
2

提示

【数据范围】

对于 30 % 30\% 30% 的数据: n ≤ 8 n \le 8 n8 m ≤ 10 m \le 10 m10
对于 70 % 70\% 70% 的数据:$n \le 10^3 , , m \le 10^4$
对于 100 % 100\% 100% 的数据:$ n \le 10^5 , , m \le 10^5$

除样例外, p = 571373 p = 571373 p=571373

(数据已经过加强_

样例说明:

故输出应为 17 17 17 2 2 2 40   m o d   38 = 2 40 \bmod 38 = 2 40mod38=2

题解

这个题目的难点较于普通的就在于对于乘法的控制了。
一个就是标记的下传。
如果同时有着乘法和加法标记应该怎么来做呢。
我们看到 ( x + d ) ∗ m (x+d)*m (x+d)m等价于 x ∗ m + d ∗ m x*m+d*m xm+dm,那么我们做向下传递的时候就可以传递 d 子 ∗ m + d 父 d_子*m+d_父 dm+d
传递规则如下

  1. 对于区间和: t r e e [ p o s ] = t r e e [ p o s ] ∗ m u l + a d d ∗ l e n % p tree[pos] = tree[pos]*mul+add*len \%p tree[pos]=tree[pos]mul+addlen%p
  2. 对于mul标记: m u l [ p o s ] = m u l [ p o s ] ∗ v a l u e % p mul[pos] = mul[pos]*value\%p mul[pos]=mul[pos]value%p
  3. 对于add标记: a d d [ p o s ] = a d d [ p o s ] + a d d [ p o s ] ∗ m u l [ p o s ] % p add[pos] = add[pos]+add[pos]*mul[pos] \%p add[pos]=add[pos]+add[pos]mul[pos]%p
import java.io.*;
import java.util.Arrays;

public class Main {
     static final StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
   

    static final PrintWriter print = new PrintWriter(System.out);

    public static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }

    public static void main(String[] args) throws IOException {
        int n = nextInt();
        int m = nextInt();
        int p = nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = nextInt();
        }
        SegmentTrees s = new SegmentTrees(a);
        for (int i = 0; i < m; i++) {
            int j = nextInt();
            if (j == 1) {
                s.update(nextInt(), nextInt(), -nextInt());
            } else if (j == 2) {
                s.update(nextInt(), nextInt(), nextInt());
            } else {
                print.println(s.get(nextInt(), nextInt()) % p);
            }
        }
        print.flush();
    }
}

class SegmentTrees {
    private final long[] tree;//线段树
    private final int size;
    private final int[] mapping;
    private final long[] add;
    private final long[] mul;
    private final int p = 571373;

    public SegmentTrees(int[] mapping) {
        this.size = mapping.length;
        this.mapping = mapping;
        this.tree = new long[size * 4 + 1];
        this.add = new long[size * 4 + 1];
        this.mul = new long[size * 4 + 1];
        Arrays.fill(mul, 1);
        build(1, size, 1);
    }

    /**
     * 建树
     *
     * @param l   左边界
     * @param r   右边界
     * @param pos 当前位置
     * @return 当前位置的值
     */
    public long build(int l, int r, int pos) {
        if (l == r) {
            return tree[pos] = mapping[l - 1] % p;
        } else {
            int mid = (l + r) >> 1;
            return tree[pos] = (build(l, mid, pos << 1)
                    + build(mid + 1, r, pos << 1 | 1)) % p;
        }
    }


    private int updateL;
    private int updateR;

    public void pushUp(int x) {
        tree[x] = (tree[x << 1] + tree[x << 1 | 1]) % p;
    }

    public void update(int l, int r, int value) {
        this.updateL = l;
        this.updateR = r;
        if (value > 0)
            getUpdate(1, size, 1, value);
        else
            getNewUpdate(1, size, 1, -value);
    }
    private void getNewUpdate(int l, int r, int pos, int value) {
        if (r < updateL || l > updateR) return;
        if (l >= updateL && r <= updateR) {
            tree[pos] = (tree[pos] * value) % p;
            mul[pos] = mul[pos] * value % p;
            add[pos] = add[pos] * value % p;
        } else {
            int mid = (l + r) >> 1;
            updateLazy(l, r, pos, mid);
            getNewUpdate(l, mid, pos << 1, value);
            getNewUpdate(mid + 1, r, pos << 1 | 1, value);
            pushUp(pos);

        }

    }

    /**
     * 更新
     *
     * @param l     左边界
     * @param r     右边界
     * @param pos   当前位置
     * @param value 更新值
     * @return 当前位置的值
     */
    public void getUpdate(int l, int r, int pos, long value) {
        if (r < updateL || l > updateR)
            return;
        if (l >= updateL && r <= updateR) {
            tree[pos] = (tree[pos] + value * (r - l + 1)) % p;
            add[pos] = (add[pos] + value) % p;
        } else {
            int mid = (l + r) >> 1;
            updateLazy(l, r, pos, mid);
            getUpdate(l, mid, pos << 1, value);
            getUpdate(mid + 1, r, pos << 1 | 1, value);
            pushUp(pos);
        }
    }

    /**
     * 更新懒标记
     *
     * @param l   左边界
     * @param r   右边界
     * @param pos 当前位置
     * @param mid 中间位置
     */
    private void updateLazy(int l, int r, int pos, int mid) {
        if (add[pos] != 0 || mul[pos] != 1) {
            int ls = pos << 1;
            int lr = ls | 1;
            tree[ls] = (tree[ls] * mul[pos] % p + add[pos] * (mid - l + 1) % p) % p;
            mul[ls] = mul[ls] * mul[pos] % p;
            add[ls] = (add[ls] * mul[pos] % p + add[pos]) % p;

            tree[lr] = (tree[lr] * mul[pos] % p + add[pos] * (r - mid) % p) % p;
            mul[lr] = mul[lr] * mul[pos] % p;
            add[lr] = (add[lr] * mul[pos] % p + add[pos]) % p;

            add[pos] = 0;
            mul[pos] = 1;
        }
    }

    public long get(int l, int r) {
        this.getL = l;
        this.getR = r;
        return getN(1, size, 1);
    }

    private int getL;
    private int getR;

    /**
     * 查询
     *
     * @param l   左边界
     * @param r   右边界
     * @param pos 当前位置
     * @return 当前位置的值
     */
    public long getN(int l, int r, int pos) {
        if (l > getR || r < getL)
            return 0;
        if (l >= getL && r <= getR) {
            return tree[pos];
        } else {
            int mid = (l + r) >> 1;
            int i = pos << 1;
            int j = i | 1;
            updateLazy(l, r, pos, mid);
            return (getN(l, mid, i) +
                    getN(mid + 1, r, j)) % p;
        }
    }
}

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

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

相关文章

生产流程图怎么制作?思路提供

生产流程图是一种图表&#xff0c;用来展示生产流程中的各个环节及其顺序。这种图表可以帮助企业管理者更好地了解生产过程中的各个环节&#xff0c;从而更好地进行管理和优化。生产流程图通常包括各个生产环节的名称、所需时间、参与人员、设备和工具等信息。 在制作生产流程图…

虚拟机 03 补充 redis的命令

Redis的操作命令&#xff1a; Redis的启动命令&#xff1a;redis-server redis.conf 进入redis的客户端操作命令&#xff1a;redis-cli -p 6379 退出redis客户端的操作命令&#xff1a;exit或者ctrlc 关闭redis的命令&#xff1a;redis-cli -p 6379 shutdown Redis数据操作命令…

免费优质的网页设计素材网站推荐

找到一个免费优质的网页设计素材网站并不容易。 有些网站要么需要网站的会员&#xff0c;要么设计素材质量差。本文整理总结了10个免费的网页设计材料网站&#xff0c;希望给大家带来一些帮助。 即时设计资源社区 即时设计资源社区是由在线协同设计软件即时设计推出的设计社…

2023乡村振兴三点:粮食安全,数字乡村,特色产业

2023乡村振兴三条&#xff1a;粮食安全&#xff0c;数字乡村&#xff0c;特色产业 人工智能总趋势在减少就业 乡村生活综合服务领域&#xff5e; 可能是以后吸纳劳动力的重要领域 农业现代化最后在实现中… 趣讲大白话&#xff1a;人没事干&#xff0c;咋办 【趣讲信息科技168期…

基于 debian 发行版本的密码设置策略

密码过期时间设置 修改 /etc/login.defs 中的选项 PASS_MAX_DAYS 99999 代表不过期 我们将该值改为 90 密码复杂度设置 需要安装 pam 扩展包 libpam-pwquality 或 libpam-cracklib 。 这里选择安装 libpam-cracklib sudo apt updatesudo apt install libpam-cracklib查看…

虚拟机 03 redis安装和启动服务

redis在linux上的安装&#xff1a; 01.先找到redis的压缩文件 这里的是gz格式的。 02.在linux系统中&#xff0c;先去切换到根目录先 使用命令 cd / 再切换到usr/local/src中 直接把压缩文件拖入到linux系统的命令行中 src文件中会出现redis-5.0.4.tar.gz的文件 03.对这个文…

arm作业

用for循环实现1~100之间的和13BA for(i1;i<100;i) { sum sumi; }

面试7轮,结果对接的HR离职了……

面试鹅厂总共进行了7轮&#xff0c;还没有结果。先是面了三轮&#xff0c;然后hr告诉她没hc了&#xff0c;然后又推荐了另外一个岗位&#xff0c;又面了四轮。然后追问HR后续的进展&#xff0c;她告诉我已经离职了&#xff0c;让我联系另外一个同事。 这么说吧&#xff0c;大厂…

密码学A5算法VHDL设计及仿真验证

A5算法是一种用于GSM(Global System for Mobile Communications)移动通信标准的加密算法。它是一种对称密钥算法,使用一个64位密钥和一个22位帧号作为输入,生成一个228位的伪随机序列,该序列被用于加密语音和数据通信。 A5算法由三个线性反馈移位寄存器(LFSR)组成,每个…

创建一个Go项目

创建一个Go项目 1.创建项目 package mainfunc main() {println("你好啊&#xff0c;简单点了&#xff01;") }如果是本地的话可以采用go run 项目名的方式。 可以采用go run --work 项目名的方式&#xff0c;此时可以展示日志信息。 如果是只编译的话 go build 项…

1.Buffer_Overflow-1.Basic_Jump

github上面的练习题 git clone https://github.com/Adamkadaban/LearnPwn 然后开始做 先进行 readelf 然后进行执行看看 是怎么回事 ./buf1发现就是一个输入和输出 我们checksec看看 发现stack 保护关闭 开启了NX保护 我们进入ida64看看反汇编 我习惯先看看字符串 SHITF…

MATLAB 之 函数文件、特殊形式的函数和程序调试与优化

文章目录 一、函数文件1. 函数文件的基本结构2. 函数调用2.1 函数调用的格式2.2 函数的递归调用2.3 函数参数的可调性2.4 全局变量与局部变量 二、特殊形式的函数1. 子函数2. 内联函数3. 匿名函数 三、程序调试与优化1. 程序调试方法1.1 利用调试函数进行程序测试1.2 利用调试工…

【Linux】多线程概念再理解

文章目录 1. 物理内存与磁盘的关系如何理解物理内存&#xff1f;凭什么物理内存要分为一个个4KB大小&#xff1f;若以块方式存储&#xff0c;则多出的空间是否浪费&#xff1f; 2. 虚拟地址到物理地址的转换3. 缺页中断4. 为什么字符常量区是不允许被修改的&#xff1f;5. 线程…

七大软件架构设计原则详解

目录 1、概述 2、七大设计原则 2.1、开闭原则 2.2、里氏替换原则 2.3、依赖倒置原则 2.4、单一职责原则 2.5、接口隔离原则 2.6、迪米特法则 2.7、合成复用原则 3、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&…

22 KVM管理虚拟机-查询虚拟机信息

文章目录 22 KVM管理虚拟机-查询虚拟机信息22.1 概述22.2 前提条件22.3 查询主机上的虚拟机信息22.4 查询虚拟机基本信息22.5 查询虚拟机基本信息示例 22 KVM管理虚拟机-查询虚拟机信息 22.1 概述 管理员在管理虚拟机的过程中经常需要知道一些虚拟机信息&#xff0c;libvirt提…

机器学习强基计划10-1:为什么需要集成学习?核心原理是什么?

目录 0 写在前面1 集成学习概念与优势2 结合策略梳理2.1 加权平均法2.2 投票法2.3 学习法 3 误差-分歧分解 0 写在前面 机器学习强基计划聚焦深度和广度&#xff0c;加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理&#xff1b;“广”在分析多个机器…

工业能效提升行动计划-安科瑞EMS能效管理平台解决方案

摘要 2022年6月29日工信部、发改委、财政部、生态环境部、国资委、市场监管总局六部门联合下发《关于印发工业能效提升行动计划的通知》&#xff08;工信部联节〔2022〕76号&#xff0c;以下简称《行动计划》&#xff09;&#xff0c;主要目的是为了提高工业领域能源利用效率&…

读《Spring Boot 3核心技术与最佳实践》有感

我是谁&#xff1f; &#x1f468;‍&#x1f393;作者&#xff1a;bug菌 ✏️博客&#xff1a;CSDN、掘金、infoQ、51CTO等 &#x1f389;简介&#xff1a;CSDN/阿里云/华为云/51CTO博客专家&#xff0c;C站历届博客之星Top50&#xff0c;掘金/InfoQ/51CTO等社区优质创作者&am…

硬件系统工程师宝典(23)-----磁珠选型,你做对了吗?

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。上篇我们说到常用的电容种类有铝电解电容、钽电容、陶瓷电容、OSCON固态电容和薄膜电容&#xff0c;应用时都有各自的特点&#xff1b;电感可分为电源…

最新版Cesium使用天地图三维地形、地名服务

目录 1、项目地址2、实现效果3、实现方法 1、项目地址 可直接运行。 https://github.com/zhengjie9510/cesium-tdt 2、实现效果 3、实现方法 参考博客修改cesiumTdt.js。