[LeetCode] 二叉树 I — 深度优先遍历(前中后序遍历) | 广度优先遍历(层序遍历):递归法迭代法

news2025/2/6 14:28:51

二叉树

  • 基础知识
  • 深度优先遍历
    • 递归法
    • 迭代法(栈)
    • 144# 二叉树的前序遍历
    • 94# 二叉树的中序遍历
    • 145# 二叉树的后序遍历
  • 广度优先遍历
    • 递归法
    • 迭代法(队列)
    • 102# 二叉树的层序遍历
    • 107# 二叉树的层序遍历 II
    • 199# 二叉树的右视图
    • 637# 二叉树的层平均值
    • 429# N叉树的层序遍历
    • 515# 在每个树行中找最大值
    • 116# 填充每个节点的下一个右侧节点指针
    • 117# 填充每个节点的下一个右侧节点指针 II
    • 104# 二叉树的最大深度
    • 111# 二叉树的最小深度
  • 补充知识:递归
    • 汉诺塔

基础知识

存储方式:数组顺序存储 / 指针链式存储

顺序存储:节点i的左孩子2i+1 、右孩子2i+2、父节点(i-1)/2

链式存储:

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	
	TreeNode(int x) : val(x), left(NULL), right(NULL) { }
}

完全二叉树:除底层外每层节点数都达到最大,底层节点集中在左边,包括满二叉树

满二叉树:深度为k的满二叉树有2^k-1个节点(1 2 ... 2^(k-1)

二叉搜索树:有序树,左子树<根节点<右子树,查找、插入、删除时间复杂度均为 O(logn),最坏情况为O(n)

平衡二叉树:左右子树的高度差(平衡因子)不超过1,避免树的高度过大以确保操作的时间复杂度稳定在 O(logn)

平衡二叉搜索树:AVL树、红黑树、Treap

AVL 树

  • 严格平衡(平衡因子 ≤ 1)
  • 优点:查询效率极高(严格 O(logn))
  • 缺点:插入/删除可能需要频繁旋转,维护成本高

红黑树

  • 近似平衡(最长路径不超过最短路径的 2 倍)
  • 优点:插入/删除性能更优,适合频繁修改的场景
  • 应用:C++ std::map、Java TreeMap、数据库索引

Treap

  • 结合二叉搜索树和堆的性质,通过随机优先级维护平衡

深度优先遍历 借助栈实现

  • 前序遍历:中左右

  • 中序遍历:左中右

  • 后序遍历:左右中

广度优先遍历 借助队列实现

  • 层次遍历:逐层从左到右访问所有节点

深度优先遍历

递归法

// 前序遍历
void preorder(TreeNode *root, vector<int> &vec) {
    if (root == nullptr) return;
    vec.push_back(root->val);
    preorder(root->left, vec);
    preorder(root->right, vec);
}
// 中序遍历
void inorder(TreeNode *root, vector<int> &vec) {
    if (root == nullptr) return;
    inorder(root->left, vec);
    vec.push_back(root->val);
    inorder(root->right, vec);
}
// 后序遍历
void postorder(TreeNode *root, vector<int> &vec) {
    if (root == nullptr) return;
    postorder(root->left, vec);
    postorder(root->right, vec);
    vec.push_back(root->val);
}

迭代法(栈)

沿着递归实现依靠调用栈的思想,利用栈实现前中后序遍历

// 前序遍历:中入出右左入出-->中左右
vector<int> preorderTraversal(TreeNode* root) {
    vector<int> result;
    stack<TreeNode*> st;
    if (root == nullptr) return result;
    st.push(root);
    while (!st.empty()) {
        TreeNode* node = st.top();
        st.pop();
        result.push_back(node->val);
        if (node->right) st.push(node->right);
        if (node->left) st.push(node->left);
    }
    return result;
}
// 中序遍历
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> result;
    stack<TreeNode*> st;
    TreeNode *cur = root;
    while (cur != nullptr || !st.empty()) {
        if (cur != nullptr) { // 深度遍历左子节点
            st.push(cur);
            cur = cur->left;
        } else {
            cur = st.top();
            result.push_back(cur->val);
            st.pop();
            cur = cur->right; // 访问根节点并弹出后再访问右子节点
        }
    }
    return result;
}
// 后序遍历:中入出左右入出-->中右左--reverse-->左右中
vector<int> postorderTraversal(TreeNode* root) {
    vector<int> result;
    stack<TreeNode*> st;
    if (root == nullptr) return result;
    st.push(root);
    while (!st.empty()) {
        TreeNode *node = st.top();
        result.push_back(node->val);
        st.pop();
        if (node->left) st.push(node->left);
        if (node->right) st.push(node->right);
    }
    reverse(result.begin(), result.end());
    return result;
}

以上三种遍历方法并不统一,前后序遍历用栈遍历,而中序遍历用指针遍历,因为栈无法解决访问节点和处理节点不一致的情况

通过为节点作标记统一迭代法:1. 空指针标记法;2. boolean标记法

// 中序遍历--空指针标记法
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> result;
    stack<TreeNode*> st;
    if (root == nullptr) return result;
    st.push(root);
    while (!st.empty()) {
        TreeNode* node = st.top();
        st.pop();
        if (node != nullptr) { // 检查空指针标记,右中左顺序入栈
            if (node->right) st.push(node->right);
            st.push(node);
            st.push(nullptr);
            if (node->left) st.push(node->left);
        } else {
            node = st.top();
            result.push_back(node->val);
            st.pop();
        }
    }
    return result;
}
// 中序遍历--boolean标记法
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> result;
    stack<pair<TreeNode*, bool>> st;
    if (root == nullptr) return result;
    st.push(make_pair(root, false));
    while (!st.empty()) {
        auto node = st.top().first;
        auto visited = st.top().second;
        st.pop();
        if (!visited) { // 检查boolean标记,右中左顺序入栈
            if (node->right) st.push(make_pair(node->right, false));
            st.push(make_pair(node, true));
            if (node->left) st.push(make_pair(node->left, false));
        } else {
            result.push_back(node->val);
        }
    }
    return result;
}

144# 二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

**输入:**root = [1,null,2,3]

输出:[1,2,3]

解释:

img

示例 2:

**输入:**root = [1,2,3,4,5,null,8,null,null,6,7,9]

输出:[1,2,4,5,6,7,3,8,9]

解释:

img

示例 3:

**输入:**root = []

输出:[]

示例 4:

**输入:**root = [1]

输出:[1]

提示:

  • 树中节点数目在范围 [0, 100]
  • -100 <= Node.val <= 100
// 递归法
// O(n) 0ms; O(n) 10.84MB
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void preorder(TreeNode *root, vector<int> &vec) {
        if (root == nullptr) return;
        vec.push_back(root->val);
        preorder(root->left, vec);
        preorder(root->right, vec);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        preorder(root, result);
        return result;
    }
};

空间复杂度 O(n)为递归过程中栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状为O(n)

迭代法:先将根节点入栈,根节点出栈后使其右子节点和左子节点入栈(中入出右左入出–>中左右)

// 迭代法--栈
// O(n) 0ms; O(n) 10.8MB
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root == nullptr) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);
            if (node->left) st.push(node->left);
        }
        return result;
    }
};

94# 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

示例 1:

img
输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

  • 树中节点数目在范围 [0, 100]
  • -100 <= Node.val <= 100
// 递归法
// O(n) 0ms; O(n) 10.71MB
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void inorder(TreeNode *root, vector<int> &vec) {
        if (root == nullptr) return;
        inorder(root->left, vec);
        vec.push_back(root->val);
        inorder(root->right, vec);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> vec;
        inorder(root, vec);
        return vec;
    }
};
// 迭代法--栈
// O(n) 0ms; O(n) 10.79MB
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode *cur = root;
        while (cur != nullptr || !st.empty()) {
            if (cur != nullptr) { // 深度遍历左子节点
                st.push(cur);
                cur = cur->left;
            } else {
                cur = st.top();
                result.push_back(cur->val);
                st.pop();
                cur = cur->right; // 访问根节点并弹出后再访问右子节点
            }
        }
        return result;
    }
};

145# 二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

示例 1:

**输入:**root = [1,null,2,3]

输出:[3,2,1]

解释:

img

示例 2:

**输入:**root = [1,2,3,4,5,null,8,null,null,6,7,9]

输出:[4,6,7,5,2,9,8,3,1]

解释:

img

示例 3:

**输入:**root = []

输出:[]

示例 4:

**输入:**root = [1]

输出:[1]

提示:

  • 树中节点的数目在范围 [0, 100]
  • -100 <= Node.val <= 100
// 递归法
// O(n) 0ms; O(n) 10.73MB
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void postorder(TreeNode *root, vector<int> &vec) {
        if (root == nullptr) return;
        postorder(root->left, vec);
        postorder(root->right, vec);
        vec.push_back(root->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> vec;
        postorder(root, vec);
        return vec;
    }
};

迭代法:利用前序遍历迭代法 中入出右左入出–>中左右 的方法,这里 中入出左右入出–>中右左–reverse–>左右中

// 迭代法--栈
// O(n) 0ms; O(n) 10.87MB
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root == nullptr) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode *node = st.top();
            result.push_back(node->val);
            st.pop();
            if (node->left) st.push(node->left);
            if (node->right) st.push(node->right);
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

广度优先遍历

递归法

void order(TreeNode *root, vector<vector<int>> &vec, int depth) {
    if (root == nullptr) return;
    if (vec.size() == depth) vec.push_back(vector<int>());
    vec[depth].push_back(root->val);
    order(root->left, vec, depth + 1);
    order(root->right, vec, depth + 1);
}

迭代法(队列)

vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> result;
    queue<TreeNode*> que;
    if (root == nullptr) return result;
    que.push(root);
    while (!que.empty()) { // 以层为单位遍历,size确定当前层需要处理的节点数
        int size = que.size();
        vector<int> vec;
        for (int i = 0; i < size; i++){
            TreeNode *cur = que.front();
            que.pop();
            vec.push_back(cur->val);
            if (cur->left) que.push(cur->left);
            if (cur->right) que.push(cur->right);
        }
        result.push_back(vec);
    }
    return result;
}

102# 二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:

img
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000]
  • -1000 <= Node.val <= 1000
// 递归法
// O(n) 0ms; O(n) 16.77MB
class Solution {
public:
    void order(TreeNode *root, vector<vector<int>> &vec, int depth) {
        if (root == nullptr) return;
        if (vec.size() == depth) vec.push_back(vector<int>());
        vec[depth].push_back(root->val);
        order(root->left, vec, depth + 1);
        order(root->right, vec, depth + 1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }
};
// 迭代法--队列
// O(n) 0ms; O(n) 16.89MB
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        queue<TreeNode*> que;
        if (root == nullptr) return result;
        que.push(root);
        while (!que.empty()) { // 以层为单位遍历,size确定当前层需要处理的节点数
            int size = que.size();
            vector<int> vec;
            for (int i = 0; i < size; i++){
                TreeNode *cur = que.front();
                que.pop();
                vec.push_back(cur->val);
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
            result.push_back(vec);
        }
        return result;
    }
};

107# 二叉树的层序遍历 II

题目链接

层序遍历后反转

// 迭代法--队列
// O(n) 3ms; O(n) 15.70MB
class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> result;
        queue<TreeNode*> que;
        if (root == nullptr) return result;
        que.push(root);
        while (!que.empty()) {
            vector<int> vec;
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode *cur = que.front(); 
                vec.push_back(cur->val);
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
            result.push_back(vec);
        }
        reverse(result.begin(), result.end()); // 默认只反转第一维度的元素顺序
        return result;
    }
};

199# 二叉树的右视图

题目链接

从右侧所能看到的节点正好是层序遍历中的最后一个节点

// 层序遍历
// O(n) 3ms; O(n) 14.77MB
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        vector<int> result;
        queue<TreeNode*> que;
        if (root == nullptr) return result;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode *cur = que.front();
                if (i == size - 1) result.push_back(cur->val);
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
        }
        return result;
    }
};

637# 二叉树的层平均值

题目链接

// 层序遍历
// O(n) 0ms; O(n) 23.39MB
class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        vector<double> result;
        queue<TreeNode*> que;
        if (root == nullptr) return result;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            double sum = 0;
            for (int i = 0; i < size; i++) {
                TreeNode *cur = que.front();
                que.pop();
                sum += cur->val;
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
            result.push_back(sum / size);
        }
        return result;
    }
};

429# N叉树的层序遍历

题目链接

// 迭代法--队列
// O(n) 14ms; O(n) 15.7MB
/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> result;
        queue<Node*> que;
        if (root == nullptr) return result;
        que.push(root);
        while (!que.empty()) {
            vector<int> vec;
            int size = que.size();
            for (int i = 0; i < size; i++) {
                Node *cur = que.front();
                vec.push_back(cur->val);
                que.pop();
                for (Node *child : cur->children) que.push(child);
            }
            result.push_back(vec);
        }
        return result;
    }
};

515# 在每个树行中找最大值

题目链接

// 层序遍历
// O(n) 0ms; O(n) 22.41MB
class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        vector<int> result;
        queue<TreeNode*> que;
        if (root == nullptr) return result;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            int max = INT_MIN;
            for (int i = 0; i < size; i++) {
                TreeNode *cur = que.front();
                max = max > cur->val ? max : cur->val;
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
            result.push_back(max);
        }
        return result;
    }
};

116# 填充每个节点的下一个右侧节点指针

题目链接

// 层序遍历
// O(n) 16ms; O(n) 19.0MB
/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> que;
        if (root == nullptr) return root;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                Node *cur = que.front();
                que.pop();
                if (i == size - 1) cur->next = nullptr;
                else cur->next = que.front();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
        }
        return root;
    }
};

117# 填充每个节点的下一个右侧节点指针 II

题目链接

与上题代码相同(是否为完美二叉树不影响代码逻辑)

// 层序遍历
// O(n) 7ms; O(n) 18.52MB
class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> que;
        if (root == nullptr) return root;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                Node *cur = que.front();
                que.pop();
                if (i == size - 1) cur->next = nullptr;
                else cur->next = que.front();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
        }
        return root;
    }
};

104# 二叉树的最大深度

题目链接

// 递归法
// O(n) 0ms; O(n) 18.61MB
class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        return max(maxDepth(root->left), maxDepth(root->right)) + 1;
    }
};
// 层序遍历
// O(n) 0ms; O(n) 18.68MB
class Solution {
public:
    int maxDepth(TreeNode* root) {
        int depth = 0;
        queue<TreeNode*> que;
        if (root == nullptr) return depth;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            depth++;
            for (int i = 0; i < size; i++) {
                TreeNode *cur = que.front();
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
        }
        return depth;
    }
};

111# 二叉树的最小深度

题目链接

注意:叶子节点需要左右孩子都为空

// 层序遍历
// O(n) 0ms; O(n) 143.41MB
class Solution {
public:
    int minDepth(TreeNode* root) {
        int depth = 0;
        queue<TreeNode*> que;
        if (root == nullptr) return depth;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            depth++;
            for (int i = 0; i < size; i++) {
                TreeNode *cur = que.front();
                que.pop();
                if (!cur->left && !cur->right) return depth;
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
        }
        return depth;
    }
};

补充知识:递归

推荐教学视频:快速掌握递归

  • 确定问题,即函数参数和返回值
  • 解决基准问题,确定终止条件
  • 拆解问题,寻找规模更小的子问题,确定单层递归逻辑

每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中

栈溢出,系统输出的异常是Segmentation fault,考虑是否是无限递归导致

汉诺塔

void hanoi(int n, char F, char A, char T) {
	if (n = 1) {
		printf("move %d from %c to %c\n", n, F, T);
		return;
	}
	
	hanoi(n-1, F, T, A);
	printf("move %d from %c to %c\n", n, F, T);
	hanoi(n-1, A, F, T);
}

本文参考 LeetCode官方题解 及 代码随想录

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

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

相关文章

Python aiortc API

本研究的主要目的是基于Python aiortc api实现抓取本地设备&#xff08;摄像机、麦克风&#xff09;媒体流实现Web端预览。本文章仅仅描述实现思路&#xff0c;索要源码请私信我。 demo-server解耦 原始代码解析 http服务器端 import argparse import asyncio import json…

OpenCV4,快速入门,第二讲:图像色彩空间转换

文章目录 引言一、色彩空间概述1.1 RGB与HSV的区别1.2 HSV的详细含义cvtColor二、cvtColor函数详解2.1 函数原型2.2 参数说明2.3 使用示例三、imwrite函数详解3.1 函数原型3.2 参数说明3.3 使用示例四、完整示例代码五、应用场景与注意事项5.1 HSV的典型应用5.2 注意事项结语引…

86.(2)攻防世界 WEB PHP2

之前做过&#xff0c;回顾一遍&#xff0c;详解见下面这篇博客 29.攻防世界PHP2-CSDN博客 既然是代码审计题目&#xff0c;打开后又不显示代码&#xff0c;肯定在文件里 <?php // 首先检查通过 GET 请求传递的名为 "id" 的参数值是否严格等于字符串 "admi…

RK3588——解决Linux系统触摸屏坐标方向相反问题

问题描述&#xff1a;触摸正常产生中断&#xff0c;但系统上报的触摸坐标不正确&#xff0c;是反向的坐标。 解决办法通过修改设备树添加属性翻转坐标。 注&#xff1a;需确认对应的驱动是否有解析该属性的具体内容&#xff0c;否则仍然无法生效。

面对全球化的泼天流量,出海企业如何观测多地域网络质量?

作者&#xff1a;俞嵩、白玙 泼天富贵背后&#xff0c;技术挑战接踵而至 随着全球化进程&#xff0c;出海、全球化成为很多 Toc 产品的必经之路&#xff0c;保障不同地域、不同网络环境的一致的用户体验成为全球化应用的不得不面对的问题。在跨运营商、跨地域的网络环境中&am…

YOLOv11实时目标检测 | 摄像头视频图片文件检测

在上篇文章中YOLO11环境部署 || 从检测到训练https://blog.csdn.net/2301_79442295/article/details/145414103#comments_36164492&#xff0c;我们详细探讨了YOLO11的部署以及推理训练&#xff0c;但是评论区的观众老爷就说了&#xff1a;“博主博主&#xff0c;你这个只能推理…

自定义序列化数据类型

目录 1. WritableComparable1.1 Writable1.2 Comparable1.3 IntWritable 2. 自定义序列化数据类型RectangleWritable3. 矩形面积计算3.1 Map3.2 Reduce 4. 代码和结果4.1 pom.xml中依赖配置4.2 工具类util4.3 矩形面积计算4.4 结果 参考 本文引用的Apache Hadoop源代码基于Apac…

【Linux网络编程】:URL(encode),HTTP协议,telnet工具

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ Linux网络编程笔记&#xff1a; https://mp.csdn…

C语言基础系列【3】VSCode使用

前面我们提到过VSCode有多么的好用&#xff0c;本文主要介绍如何使用VSCode编译运行C语言代码。 安装 首先去官网&#xff08;https://code.visualstudio.com/&#xff09;下载安装包&#xff0c;点击Download for Windows 获取安装包后&#xff0c;一路点击Next就可以。 配…

学前端框架之前,你需要先理解 MVC

MVC 软件架构设计模式鼎鼎大名&#xff0c;相信你已经听说过了&#xff0c;但你确定自己已经完全理解到 MVC 的精髓了吗&#xff1f; 如果你是新同学&#xff0c;没听过 MVC&#xff0c;那可以到网上搜一些文章来看看&#xff0c;不过你要有心理准备&#xff0c;那些文章大多都…

Mysql:数据库

Mysql 一、数据库概念&#xff1f;二、MySQL架构三、SQL语句分类四、数据库操作4.1 数据库创建4.2 数据库字符集和校验规则4.3 数据库修改4.4 数据库删除4.4 数据库备份和恢复其他 五、表操作5.1 创建表5.2 修改表5.3 删除表 六、表的增删改查6.1 Create(创建):数据新增1&#…

熟练掌握Http协议

目录 基本概念请求数据Get请求方式和Post请求方式 响应数据响应状态码 基本概念 Http协议全称超文本传输协议(HyperText Transfer Protocol)&#xff0c;是网络通信中应用层的协议&#xff0c;规定了浏览器和web服务器数据传输的格式和规则 Http应用层协议具有以下特点&#…

C++的 I/O 流

本文把复杂的基类和派生类的作用和关系捋出来&#xff0c;具体的接口请参考相关文档 C的 I/O 流相关的类&#xff0c;继承关系如下图所示 https://zh.cppreference.com/w/cpp/io I / O 的概念&#xff1a;内存和外设进行数据交互称为 I / O &#xff0c;例如&#xff1a;把数…

【PDF多区域识别】如何批量PDF指定多个区域识别改名,基于Windows自带的UWP的文字识别实现方案

海关在对进口货物进行查验时,需要核对报关单上的各项信息。对报关单 PDF 批量指定区域识别改名后,海关工作人员可以更高效地从文件名中获取关键信息,如货物来源地、申报价值等。例如文件名 “[原产国]_[申报价值].pdf”,有助于海关快速筛选重点查验对象,提高查验效率和监管…

【大数据技术】本机PyCharm远程连接虚拟机Python

本机PyCharm远程连接虚拟机Python 注意:本文需要使用PyCharm专业版。 pycharm-professional-2024.1.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本地PyCharm远程连接虚拟机,运行Python脚本,提高编程效率。 注意: …

数字化转型:概念性名词浅谈(第四讲)

​大家好&#xff0c;本篇文章是在新年之际写的&#xff0c;所以在这里先给大家拜个年。 今天要介绍的名词为ETL: ETL&#xff0c;是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;extract&#xff09;、转换&#xff08;transfor…

【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(四) -> 常见组件(一)

目录 1 -> List 1.1 -> 创建List组件 1.2 -> 添加滚动条 1.3 -> 添加侧边索引栏 1.4 -> 实现列表折叠和展开 1.5 -> 场景示例 2 -> dialog 2.1 -> 创建Dialog组件 2.2 -> 设置弹窗响应 2.3 -> 场景示例 3 -> form 3.1 -> 创建…

Linux:文件系统(软硬链接)

目录 inode ext2文件系统 Block Group 超级块&#xff08;Super Block&#xff09; GDT&#xff08;Group Descriptor Table&#xff09; 块位图&#xff08;Block Bitmap&#xff09; inode位图&#xff08;Inode Bitmap&#xff09; i节点表&#xff08;inode Tabl…

深度学习系列--01.入门

一.深度学习概念 深度学习&#xff08;Deep Learning&#xff09;是机器学习的分支&#xff0c;是指使用多层的神经网络进行机器学习的一种手法抖音百科。它学习样本数据的内在规律和表示层次&#xff0c;最终目标是让机器能够像人一样具有分析学习能力&#xff0c;能够识别文字…

如何抓取酒店列表: 揭开秘密

搜索酒店列表是一种强大的工具&#xff0c;可以从各种在线资源中收集有关住宿、价格和可用性的综合数据。无论您是要比较价格、分析市场趋势&#xff0c;还是要创建个性化的旅行计划&#xff0c;搜索都能让您有效地汇编所需的信息。在本文中&#xff0c;我们将介绍如何搜索酒店…