【LeetCode Cookbook(C++ 描述)】平衡二叉树

news2024/12/26 12:29:25

目录

  • 平衡二叉树基础
    • 不同插入节点方式的不同旋转
      • LL 型失衡
      • RR 型失衡
      • LR 型失衡
      • RL 型失衡
    • 删除操作
      • 删除节点为二叉树的叶子节点
      • 删除的节点只有左子树或者右子树
      • 删除的节点既有左子树又有右子树
  • LeetCode #110:Balanced Binary Tree 平衡二叉树
    • 递归法(自底向上)
    • 递归法(自顶向下)
    • 迭代法
  • LeetCode #1382:Balance a Binary Search Tree 将二叉搜索树变平衡
    • 递归法
    • 迭代法

本系列文章仅是 GitHub 大神 @halfrost 的刷题笔记 《LeetCode Cookbook》的提纲以及示例、题集的 C++转化。原书请自行下载学习。
本篇文章涉及新手应该优先刷的几道经典平衡二叉树算法题。

平衡二叉树基础

  • 平衡二叉树,是一种二叉排序树,其中对于每个节点的左右子树高度相差小于等于 1,即“高度平衡”。
  • 我们通过平衡因子(BF,balance factor,其值为左右子树高度之差)来衡量一棵树是否平衡。
  • 一棵平衡二叉树,必须满足:
    • 是一棵二叉搜索树
    • 每个节点 BF 的绝对值小于 1
  • 对于一棵有 n n n 个节点的平衡二叉树来说,它每一个操作的时间复杂度都可以维持在 O ( log ⁡ n ) O(\log n) O(logn)
  • 对于一棵平衡二叉树,插入节点可能会使其「失衡」,我们将“距离插入节点最近的,且以 BF 绝对值大于 1 的节点为根的子树”称为「最小不平衡子树」。那么,失衡的调整主要通过调整最小不平衡子树来实现重新平衡,我们具体以「旋转」的方式实现:
    • 左旋:把最小不平衡子树的右孩子作为根进行旋转操作。
      1. “根节点的右孩子”作为“新的根节点”
      2. “根节点的右孩子的左子树”(如果有)变为“根节点的右子树”
      3. “根节点”变为“根节点的右孩子”的左子树
    • 右旋:把最小不平衡子树的左孩子作为根进行旋转操作。
      1. “根节点的左孩子”作为“新的根节点”
      2. “根节点的左孩子的右子树”(如果有)变为“根节点的左子树”
      3. “根节点”变为“根节点的左孩子”的右子树

不同插入节点方式的不同旋转

对于平衡二叉树的节点 node 来说,有 4 种插入方式:

  • 插入左孩子的左子树(LL 型)
  • 插入右孩子的右子树(RR 型)
  • 插入左孩子的右子树(LR 型)
  • 插入右孩子的左子树(RL 型)

这些插入方式可能会造成 node 的 BF 绝对值大于 1,从而打破了原平衡二叉树的平衡。

LL 型失衡

针对插入左孩子的左子树失衡,只需执行一次「右旋」即可

left
left
4
3
6
2
1
5
7

插入节点 1,造成失衡,这时候最小不平衡子树的根节点为 3,直接进行一次右旋操作:

4
2
6
1
3
5
7

RR 型失衡

对于针对插入右孩子的右子树失衡,只需执行一次「左旋」即可

right
right
right
4
2
5
1
3
6
7

插入节点 7,造成失衡,这个时候最小不平衡子树的根节点为 5,直接进行一次左旋操作:

4
2
6
1
3
5
7

LR 型失衡

插入左孩子的右子树失衡,需要 2 步解决:

  1. 对最小不平衡子树的根节点的左孩子左旋,转变为 LL 型失衡
  2. 最小不平衡子树右旋
left
right
4
3
6
1
2
5
7

插入节点 2,造成失衡,最小不平衡子树的根节点为 3 。此时最小不平衡子树根节点的左孩子为节点 1,将以节点 1 为根节点的子树左旋:

left
left
4
3
6
2
1
5
7

将最小不平衡子树右旋:

4
2
6
1
3
5
7

RL 型失衡

插入右孩子的左子树失衡,也需要 2 步:

  1. 对最小不平衡子树根节点的右孩子右旋,转变为 RR 型失衡
  2. 最小不平衡子树左旋
left
right
4
2
5
1
3
7
6

插入节点 6,造成失衡,最小不平衡子树的根节点为 5 。此时最小不平衡子树根节点的右孩子为节点 7,将以节点 7 为根节点的子树右旋:

right
right
4
2
5
1
3
6
7

将最小不平衡子树左旋:

4
2
6
1
3
5
7

删除操作

同二叉搜索树一致,平衡二叉树也分为 3 种情况,但是删除完节点后,需要重新判断一下是否依然平衡并调整之;删除一个节点后可能会有多个不平衡的节点

删除节点为二叉树的叶子节点

通过平衡二叉树的查找操作找到节点,直接删除,随后,从删除节点的父节点开始判断是否失衡,如果是,则判断为 LL、RR、LR、RL 中的哪种类型的失衡,根据上述调整方式进行旋转;如果不是,就继续向父节点的父节点继续判断,以此类推。

删除的节点只有左子树或者右子树

直接用删除节点的父节点指向它的子树即可,随后,从删除节点的父节点开始判断为哪种类型的失衡,并进行旋转;如果不失衡,就继续向父节点的父节点继续判断,以此类推。

删除的节点既有左子树又有右子树

将要删除节点 node 位置上替换成左子树最右边的节点或者右子树最左边的节点,即左子树的最大值或者右子树的最小值;删除以后的调整操作,还是与前两种情况的旋转操作相同。

LeetCode #110:Balanced Binary Tree 平衡二叉树

#110
给定一个二叉树,判断它是否是高度平衡的二叉树

针对每一个节点,大致分为两步:

  1. 分别求该节点左右子树的最大高度
  2. 求该节点的 BF,若|BF| ≤ \leq 1 ,则是平衡的,继续判断下一个节点;若|BF|> 1,则直接不是平衡二叉树

因此,关键在于如何求解出每个节点的最大高度,由于二叉树的深度和层次是完全对应的,最大深度为最大层次数,而二叉树的深度和高度正好相反,求二叉树的最大高度共有 3 种方法——自底向上的递归(后序遍历)、自顶向上的递归(前序遍历),以及自左向右的层次遍历。

递归法(自底向上)

对于后序遍历,分而治之,递归左子树的最大高度,递归右子树的最大高度,求根的 BF,判断|BF|。

class Solution {
private:
    int judgeHeight(TreeNode* root) {   
        if (root == nullptr) return 0;    //节点为空,高度为 0
        //递归计算左子树的最大高度
        int leftHeight = judgeHeight(root->left);
        //如果左子树不是平衡二叉树,肯定不是平衡二叉树
        if (leftHeight == -1) return -1;
        //递归计算右子树的最大高度
        int rightHeight = judgeHeight(root->right);
        //如果右子树不是平衡二叉树,肯定不是平衡二叉树
        if (rightHeight == -1) return -1;
        //若为平衡二叉树,平衡因子为 1、0、-1
        if (abs(leftHeight - rightHeight) > 1) return -1;
        else return max(leftHeight, rightHeight) + 1;     //二叉树的最大高度 = 子树的最大高度 + 1
    }

public:
    bool isBalanced(TreeNode* root) {
        if (judgeHeight(root) != -1) return true;

        return false;
    }
};

该算法时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)

递归法(自顶向下)

类似于二叉树的前序遍历,对于当前遍历到的节点,首先计算左右子树的高度,判断左右子树的高度差是否不超过 1,再分别递归地遍历左右子节点,并判断左子树和右子树是否平衡。

class Solution {
private:
    int height(TreeNode* root) {
        if (root == nullptr) return 0;
        else return max(height(root->left), height(root->right)) + 1;
    }

public:
    bool isBalanced(TreeNode* root) {
        if (root == nullptr) return true;
        else return abs(height(root->left) - height(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right);
    }
};

最坏情况下,二叉树是满二叉树,需要遍历二叉树中的所有节点,时间复杂度是 O ( n ) O(n) O(n);对于节点 node ,如果它的高度是 d ,则 height(node) 最多会被调用 d(即遍历到它的每一个祖先节点时)。对于平均的情况,一棵树的高度 h 满足 O ( h ) = O ( log ⁡ n ) O(h)=O(\log n) O(h)=O(logn),因为 d ≤ h d≤h dh ,所以总时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn);对于最坏的情况,二叉树形成链式结构,高度为 O ( n ) O(n) O(n),此时总时间复杂度为 O ( n 2 ) O(n^2) O(n2)

空间复杂度为 O ( n ) O(n) O(n)

迭代法

使用队列保存每一层的所有节点,把队列里的所有节点弹出队列,然后把这些被弹出节点各自的子节点入队列。用 depth 维护每一层,求出最大高度。

class Solution {
private:
    int maxDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        //初始化队列和层次
        queue<TreeNode*> q;
        q.push(root);
        int depth = 0;

        while (!q.empty()) {
            //当前层的节点数
            int n = q.size();
            //弹出当前层的所有节点,并将所有子节点入队列
            for (int i = 0; i < n; i++) {
                TreeNode* node = q.front();
                q.pop();
                if (node->left != nullptr) q.push(node->left);
                if (node->right != nullptr) q.push(node->right);
            }
            
            depth++;
        }
        //二叉树最大层次即为二叉树最大高度
        return depth;
    }

public:
    bool isBalanced(TreeNode* root) {
        if (root == nullptr) return true;
        //判断以二叉树的每个节点为根的二叉树是否符合平衡二叉树的条件
        //这里遍历二叉树的每个节点使用的是非递归的中序遍历,用栈来模拟
        stack<TreeNode*> stk;
        while (root != nullptr || !stk.empty()) {
            if (root != nullptr) {
                stk.push(root);
                root = root->left;
            } else {
                TreeNode* cur = stk.top();
                stk.pop();
                if (abs(maxDepth(cur->left) - maxDepth(cur->right)) > 1) return false;
 
                root = cur->right;
            }
        }
        
        return true;
    }
};

该算法遍历整棵二叉树的节点消耗 O ( n ) O(n) O(n),而对每个节点来说,求节点的最大高度又消耗了 O ( n ) O(n) O(n),所以时间复杂度为 O ( n 2 ) O(n^2) O(n2);空间复杂度依然为 O ( n ) O(n) O(n)

LeetCode #1382:Balance a Binary Search Tree 将二叉搜索树变平衡

#1382
给你一棵二叉搜索树,请你返回一棵平衡后的二叉搜索树,新生成的树应该与原来的树有着相同的节点值。如有多种构造方法,请你返回任意一种。

我们可以对二叉搜索树进行中序遍历,得到一个有序数组,针对这个数组来构造平衡二叉树,需要注意满足三个条件:

  • 有序数组中间节点为根节点
  • 根节点左侧区间为左子树
  • 根节点右侧区间为右子树

这些条件是基于贪心策略的,当左右子树的大小越「平均」,这棵树就越平衡1

对于我们之前遇到的数组元素个数的奇偶问题,若数组有偶数个元素,中间节点任取左右两个边的一个均可。

递归法

对于中序遍历,先遍历左子树,再取根节点,最后遍历右子树

inOrder(root->left, nums);
nums.push_back(root->val);
inOrder(root->right, nums);

对于构造平衡二叉树,重复的子问题就是找到根节点,递归构造左子树,递归构造右子树:

int mid = left + ((right - left) >> 1);
//根节点
TreeNode* midNode = new TreeNode(nums[mid]);
//递归构造左子树
midNode->left = process(nums, left, mid - 1);
//递归构造右子树
midNode->right = process(nums, mid + 1, right);

对于有序序列构造平衡二叉树的终止条件 base caseleft > right 时,就终止,返回 nullptr ,因为此时就是空节点。

具体代码实现如下:

class Solution {
private:
    //中序遍历,将二叉搜索树转为有序数组
    void inOrder(TreeNode* root, vector<int>& nums) {
        if (root == nullptr) return;

        inOrder(root->left, nums);
        nums.push_back(root->val);
        inOrder(root->right, nums);
    }

    //将有序数组转为平衡二叉树
    TreeNode* process(const vector<int>& nums, int left, int right) {
        if (left > right) return nullptr;
        //找数组中间元素
        int mid = left + ((right - left) >> 1);
        //根节点
        TreeNode* midNode = new TreeNode(nums[mid]);
        //递归构造左子树
        midNode->left = process(nums, left, mid - 1);
        //递归构造右子树
        midNode->right = process(nums, mid + 1, right);

        return midNode;
    }

public:
    TreeNode* balanceBST(TreeNode* root) {
        vector<int> nums;
        inOrder(root, nums);
        TreeNode* rootNew = process(nums, 0, nums.size() - 1);
        
        return rootNew;
    }
};

该算法使用中序遍历将二叉搜索树转化为有序序列消耗 O ( n ) O(n) O(n),而由于有序序列构造平衡二叉树时每个元素都要访问且构造单个节点消耗 O ( 1 ) O(1) O(1),即有序序列构造平衡二叉树也消耗 O ( n ) O(n) O(n),所以总体的时间复杂度为 O ( n ) O(n) O(n)

无论是中序遍历,还是有序序列构造平衡二叉树,调用的栈大小都是 O ( log ⁡ n ) O(\log n) O(logn),此外还使用了一个数组 nums 存储中序遍历之后的有序序列,消耗 O ( n ) O(n) O(n),所以总体的空间复杂度为 O ( n ) O(n) O(n)

迭代法

我们依然还是有序序列构造平衡二叉树,需要用到 3 个队列:

  • rootQue 存放遍历的节点
  • leftQue 存放左区间的下标
  • rightQue 存放右区间的下标

之后不断地模拟寻找根节点,构造左子树和构造右子树。

class Solution {
private:
    vector<int> inOrder(TreeNode* root) {
        if (root == nullptr) return {};

        vector<int> nums;
        stack<TreeNode*> stk;
        while (!stk.empty() || root != nullptr) {
            if (root != nullptr) {
                stk.push(root);
                root = root->left;
            } else {
                TreeNode* cur = stk.top();
                stk.pop();
                nums.push_back(cur->val);
                root = cur->right;
            }
        }
        
        return nums;
    }

public:
    TreeNode* balanceBST(TreeNode* root) {
        vector<int> nums = inOrder(root);
        if (nums.size() == 0) return nullptr;
        //初始化根节点
        TreeNode* rootNew = new TreeNode(0);
        //队列存放遍历的节点
        queue<TreeNode*> rootQue;
        //队列存放左区间下标
        queue<int> leftQue;
        //队列存放右区间下标
        queue<int> rightQue;
        //初始化 3 个队列
        rootQue.push(rootNew);
        leftQue.push(0);
        rightQue.push(nums.size() - 1);

        while (!rootQue.empty()) {
            TreeNode* cur = rootQue.front();
            rootQue.pop();
            int left = leftQue.front();
            leftQue.pop();
            int right = rightQue.front();
            rightQue.pop();
            //找数组中间元素
            int mid = left + ((right - left) >> 1);
            //将中间元素值赋值给节点
            cur->val = nums[mid];
            //处理左区间
            if (left < mid) {
                cur->left = new TreeNode(0);
                rootQue.push(cur->left);
                leftQue.push(left);
                rightQue.push(mid - 1);
            }
            //处理右区间
            if (right > mid) {
                cur->right = new TreeNode(0);
                rootQue.push(cur->right);
                leftQue.push(mid + 1);
                rightQue.push(right);
            }
        }

        return rootNew;
    }
};

呜啊?


  1. 该贪心算法的正确性证明
    要证明基于这三个条件构造的这棵树是平衡的,就要证明这棵树的根节点为空或者左右两个子树的高度差的绝对值不超过 1。观察这个过程,我们不难发现它和二分查找非常相似——对于一个长度为 x x x 的区间,由它构建出的二叉树的最大高度应该等于对长度为 x x x 的有序序列进行二分查找「查找成功」时的「最大」比较次数,为 ⌊ log ⁡ 2 x ⌋ + 1 \lfloor \log_2 x\rfloor + 1 log2x+1,记为 h ( x ) h(x) h(x)
    「引理 A」 长度为 k k k 的区间与长度为 k + 1 k+1 k+1 的区间(其中 k ≥ 1 k≥1 k1)按照以上方法构造出的二叉树的最大高度差不超过 1
    要证明「引理 A」,我们要证明:
    h ( k + 1 ) − h ( k ) = [ ⌊ log ⁡ 2 ( k + 1 ) ⌋ + 1 ] − [ ⌊ log ⁡ 2 k ⌋ + 1 ] = ⌊ log ⁡ 2 ( k + 1 ) ⌋ − ⌊ log ⁡ 2 k ⌋ ≤ 1 \begin{aligned} h(k+1)-h(k) &= \left[ \lfloor \log_2(k+1)\rfloor+1 \right] - \left[ \lfloor \log_2k\rfloor+1 \right] \\ &= \lfloor \log_2(k+1)\rfloor - \lfloor \log_2 k \rfloor \leq 1 \end{aligned} h(k+1)h(k)=[log2(k+1)⌋+1][log2k+1]=log2(k+1)⌋log2k1
    由此我们可以证明不等式: ⌊ log ⁡ 2 ( k + 1 ) ⌋ ≤ ⌊ log ⁡ 2 k ⌋ + 1. \lfloor\log_2 (k+1)\rfloor \leq \lfloor\log_2k\rfloor + 1. log2(k+1)⌋log2k+1.
    k = 2 r + b k=2^r+b k=2r+b,其中 0 ≤ b ≤ 2 r 0\leq b \leq 2^r 0b2r,那么 k ∈ [ 2 r , 2 r + 1 ) k\in [2^r,2^{r+1}) k[2r,2r+1) ⌊ log ⁡ 2 k ⌋ = r \lfloor\log_2k\rfloor=r log2k=r,不等式右边等于 r + 1 r+1 r+1。由于 k ∈ [ 2 r , 2 r + 1 ) k\in [2^r,2^{r+1}) k[2r,2r+1),则 k + 1 ∈ ( 2 r , 2 r + 1 ] k+1\in (2^r,2^{r+1}] k+1(2r,2r+1],故 ⌊ log ⁡ 2 ( k + 1 ) ⌋ = r + 1 \lfloor\log_2 (k+1)\rfloor=r+1 log2(k+1)⌋=r+1,即不等式右边等于 ⌊ log ⁡ 2 ( k + 1 ) ⌋ \lfloor\log_2 (k+1)\rfloor log2(k+1)⌋,因此我们需要证明
    ⌊ log ⁡ 2 ( k + 1 ) ⌋ ≤ ⌊ log ⁡ 2 ( k + 1 ) ⌋ \lfloor\log_2 (k+1)\rfloor \leq \lfloor\log_2 (k+1)\rfloor log2(k+1)⌋log2(k+1)⌋
    显然成立。由此逆推可得,引理 A 成立。
    下面我们利用「引理 A」来证明这一贪心算法的正确性:
    假设我们要讨论的区间长度为 k k k,我们用数学归纳法来证明:

    • k = 1 k=1 k=1 k = 2 k=2 k=2 时显然成立;
    • 假设 k = m k=m k=m k = m + 1 k=m+1 k=m+1 时正确性成立:
      • 那么根据「引理 A」,长度为 m m m m + 1 m+1 m+1 的区间构造出的子树都是平衡的,并且它们的高度差不超过 1;
      • k = 2 ( m + 1 ) − 1 k=2(m+1)−1 k=2(m+1)1 时,创建出的节点的值等于第 m + 1 m+1 m+1 个元素的值,它的左边和右边各有长度为 m m m 的区间,根据「假设推论」, k = 2 ( m + 1 ) − 1 k=2(m+1)−1 k=2(m+1)1 时构造出的左右子树都是平衡树,且树形完全相同,故高度差为 0,所以 k = 2 ( m + 1 ) − 1 k=2(m+1)−1 k=2(m+1)1 时,正确性成立;
      • k = 2 ( m + 1 ) k=2(m+1) k=2(m+1) 时,创建出的节点的值等于第 m + 1 m+1 m+1 个元素的值,它的左边的区间长度为 m m m,右边区间的长度为 m + 1 m+1 m+1,那么 k = 2 ( m + 1 ) k=2(m+1) k=2(m+1) 时构造出的左右子树都是平衡树,且高度差不超过 1,所以 k = 2 ( m + 1 ) k=2(m+1) k=2(m+1) 时,正确性成立.
    • 通过这种归纳方法,可以覆盖所有的 k ≥ 1 k≥1 k1。故在 k ≥ 1 k≥1 k1 时,正确性成立,证毕。
    ↩︎

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

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

相关文章

[C++番外] 抛异常

一、C语言的时候我们怎么判断错误的呢&#xff1f; C语言的错误处理机制&#xff1a; 终止程序&#xff0c;如assert&#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&#xff0c;除0错误时就会终止程序。返回错误码&#xff0c;缺陷&#xff1a;需要程序员自己去查…

字典序排数

题目链接 字典序排数 题目描述 注意点 1 < n < 5 * 10^4 解答思路 参照题解使用dfs完成本题&#xff0c;需要注意的是结果不包含0&#xff0c;所以先遍历第一层&#xff08;1~9&#xff09;&#xff0c;再根据每个节点继续深搜&#xff0c;将访问到的节点按顺序添加…

测试开发面试题目汇总

之前因为面临换工作&#xff0c;所以通过一些渠道汇总了一些面试题目&#xff0c;然后加入了部分自己面试过程中遇到的问题&#xff0c;因此记录下来。文末有惊喜。 1. 项目经验 2. 测试的过程 3. 京东登录页面怎么测&#xff1f; 4. 如果一个普通用户&#xff0c;他的百度首…

EasyExcel动态映射Excel数据到任意实体类教程

在使用EasyExcel进行Excel导入时&#xff0c;我们经常需要将Excel中的数据映射到Java实体类中。如果Excel的列名是固定的&#xff0c;我们可以通过ExcelProperty("列名")注解直接在实体类中指定列名。但如果Excel的列名不固定&#xff0c;或者我们希望根据Excel的第一…

NS2582 同步升压双节锂电池充电管理 IC

1 特性  最大 2A 输出同步开关型升压充电器  升压效率可高达 90% 以上  内置电池短路 / 涓流 / 恒流 / 恒压模式  0.5% 电池恒压模式电压精度  支持 LED 充电状态指示  支持充电电流外部可调  支持输入适配器 DPM 功能  外置 EN 使能…

SQL语法:create、insert、update、

1.create创建表 创建表时&#xff0c;通常会有如下设置&#xff1a;主键、非空、取值唯一、使用自动增长等。 根据如图创建表名为userinfo的数据表&#xff1a; create table userinfo(id int not null primary key auto_increment,username varchar(50) not null unique,cre…

java框架第二课(Reflection反射机制)

一.关于反射 (1)使用场景介绍 平常我们写代码时&#xff0c;都是已知类名&#xff0c;类的属性&#xff0c;构造方法&#xff0c;其他方法等信息&#xff0c;然后根据类名new对象&#xff0c;这个过程称为正向操作(例如&#xff1a;有一个管理员类&#xff0c;有账号和密码属…

WEB渗透Win提权篇-BypassUAC

提权工具合集包&#xff08;免费分享&#xff09;&#xff1a; 夸克网盘分享 往期文章 WEB渗透Win提权篇-提权工具合集-CSDN博客 WEB渗透Win提权篇-RDP&Firewall-CSDN博客 WEB渗透Win提权篇-MSSQL-CSDN博客 WEB渗透Win提权篇-MYSQL-udf-CSDN博客 WEB渗透Win提权篇-Acc…

大模型基础环境部署之一:安装 Nvidia 的驱动(详细实操版)

一、系统准备前置条件 1、更新软件包列表 sudo apt-get update2、安装编译工具和依赖项 sudo apt-get install gcc sudo apt-get install make sudo apt-get install g注&#xff1a;如果在安装 g 时遇到错误消息&#xff1a;“***you do not appear to have libc header fi…

【C++ Primer Plus习题】6.2

问题: 解答: #include <iostream> #include <array> using namespace std;#define MAX 10int main() {array<float, MAX> arr;float sum0;float average0;int i 0;int count0;int bigger 0;for (i 0; i < MAX; i){cout << "请输入donation…

大数据技术之Flume 企业开发案例——聚合(7)

目录 聚合 1&#xff09;案例需求&#xff1a; 2&#xff09;需求分析 3&#xff09;实现步骤&#xff1a; 准备工作 创建 flume1-logger-flume.conf 创建 flume2-netcat-flume.conf 创建 flume3-flume-logger.conf 执行配置文件 聚合 1&#xff09;案例需求&#x…

华为eNSP:路由器子接口配置

一、拓扑图 二、 路由器配置 [R1]int g0/0/0.1#进入子接口 [R1-GigabitEthernet0/0/0.1]ip add 192.168.1.254 24#配置子接口地址 [R1-GigabitEthernet0/0/0.1]dot1q termination vid 10#标记终止的vid编号 [R1-GigabitEthernet0/0/0.1]arp broadcast enable #开启子接口的arp…

Keilv5 逻辑分析仪的使用

声明&#xff1a;基于视频【事件驱动型编程和 QP/C 框架】所做的笔记 Keilv5逻辑分析仪是Keil MDK集成开发环境&#xff08;IDE&#xff09;中的一个工具&#xff0c;用于帮助开发人员进行嵌入式系统的调试和分析。 它的作用主要有&#xff1a; 监测信号&#xff1a;Keilv5逻…

DBSCAN算法详解

1. 算法原理 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基于密度的聚类算法&#xff0c;主要用于发现数据中的任意形状的簇&#xff0c;并能够有效地识别噪声点。它的基本思想是通过密度来定义簇&#xff0c;即在数据…

Python -- GUI图形界面编程—GUI编程实例 博主也在持续学习中[ 持续更新中!!! 欢迎白嫖 ]

本文继上篇文章http://t.csdnimg.cn/mJlmW继续介绍GUI的图形界面编程&#xff08;相关视频是哔站上的应该搜这个题目就能找到&#xff09;&#xff0c;文章还是很基础的&#xff0c;目前博主处于有一点基础的状态。 文章的主要介绍了依旧非常重要的结构tinkter库、常见的三种布…

Patch-Package:一款灵活的开源依赖修复工具

一、背景 在现代软件开发中&#xff0c;开发者通常依赖大量的开源库来加快开发进程。然而&#xff0c;随着时间的推移&#xff0c;可能会遇到一些问题&#xff1a; 开源包的缺陷&#xff1a;开源库可能存在 Bug 或者与项目不兼容的问题。开发者可以自己修复这些问题&#xff0…

QML控件: 动画输入框 LineEdit PySide6

1. 前言 本代码为扫地僧-smile原创, 废话不多说, 直接看效果图由于录制的这个GIF图掉帧严重, 实际动画效果非常细腻 2.看代码 控件模块代码如下 SmileLineEdit.qml import QtQuick import QtQuick.Controls/* __author__: 扫地僧-smile */Rectangle {// 属性property int …

这些年使用Delphi的成果

成果1&#xff1a; 收到了一件文化衫 成果2&#xff1a;被评为亚洲专家&#xff0c;收到了一套Delphi7 光碟找不到了。

Arista与英伟达IB网络竞争格局分析

悄然崛起的英伟达新对手 英伟达都有哪些对手&#xff1f; 当然首选AMD和英特尔。AMD具备AI加速卡业务&#xff0c;融合CPU和GPU设计能力&#xff1b;英特尔作为x86架构的开创者&#xff0c;如今也涉足AI加速卡领域。它们的产品在参数上与英伟达对标&#xff0c;同时在定位和售…

江西生物科技职业学院春雨宣讲团丨弘扬西柏坡精神,共绘时代新篇章

今年五月&#xff0c;江西生物科技职业学院春雨宣讲团获批共青团中央2024年全国大学生西柏坡精神志愿宣讲团之一。 秉承传承红色文化、弘扬西柏坡精神的崇高使命&#xff0c;该宣讲团成员自7月3日起至8月20日&#xff0c;踏上了深入江西省南昌市、九江市、景德镇市、吉安市等地…