C++ -- 红黑树的基本操作

news2024/11/26 0:34:10

目录

摘要

基本规则

基本操作

利用Graphviz 库

总结


摘要

红黑树是一种自平衡的二叉搜索树,它在插入和删除节点时,通过颜色和旋转操作保持树的平衡,确保插入、删除和查找的时间复杂度都是 (O(log n))。红黑树的每个节点都有一个颜色属性,红色或黑色。通过一些规则,红黑树保持了相对平衡,使得最长路径长度不会超过最短路径长度的两倍。

基本规则

1. 每个节点不是红色就是黑色。
2. 根节点是黑色。
3. 每个叶子节点(NIL节点)是黑色。
4. 如果一个节点是红色的,则它的两个子节点都是黑色的(从每个叶子到根的所有路径上不能有两个连续的红色节点)。
5. 从任一节点到其每个叶子的所有简单路径都包含相同数量的黑色节点。

基本操作

插入操作

#include <iostream>

enum Color { RED, BLACK };

struct Node {
    int data;
    Color color;
    Node *left, *right, *parent;

    Node(int data) : data(data), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}
};

class RedBlackTree {
public:
    RedBlackTree() : root(nullptr) {}

    void insert(int data) {
        Node* newNode = new Node(data);
        root = bstInsert(root, newNode);
        fixViolation(newNode);
    }

    void inorder() { inorderHelper(root); }

private:
    Node* root;

    Node* bstInsert(Node* root, Node* node) {
        if (root == nullptr) return node;
        if (node->data < root->data) {
            root->left = bstInsert(root->left, node);
            root->left->parent = root;
        } else if (node->data > root->data) {
            root->right = bstInsert(root->right, node);
            root->right->parent = root;
        }
        return root;
    }

    void fixViolation(Node* node) {
        Node* parent = nullptr;
        Node* grandParent = nullptr;

        while (node != root && node->color == RED && node->parent->color == RED) {
            parent = node->parent;
            grandParent = parent->parent;

            if (parent == grandParent->left) {
                Node* uncle = grandParent->right;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->right) {
                        rotateLeft(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateRight(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            } else {
                Node* uncle = grandParent->left;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->left) {
                        rotateRight(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateLeft(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            }
        }
        root->color = BLACK;
    }

    void rotateLeft(Node* node) {
        Node* rightNode = node->right;
        node->right = rightNode->left;

        if (node->right != nullptr) node->right->parent = node;
        rightNode->parent = node->parent;

        if (node->parent == nullptr) root = rightNode;
        else if (node == node->parent->left) node->parent->left = rightNode;
        else node->parent->right = rightNode;

        rightNode->left = node;
        node->parent = rightNode;
    }

    void rotateRight(Node* node) {
        Node* leftNode = node->left;
        node->left = leftNode->right;

        if (node->left != nullptr) node->left->parent = node;
        leftNode->parent = node->parent;

        if (node->parent == nullptr) root = leftNode;
        else if (node == node->parent->left) node->parent->left = leftNode;
        else node->parent->right = leftNode;

        leftNode->right = node;
        node->parent = leftNode;
    }

    void inorderHelper(Node* root) {
        if (root == nullptr) return;
        inorderHelper(root->left);
        std::cout << root->data << " ";
        inorderHelper(root->right);
    }
};

int main() {
    RedBlackTree tree;
    tree.insert(10);
    tree.insert(20);
    tree.insert(30);
    tree.insert(15);

    std::cout << "Inorder traversal of the constructed tree is ";
    tree.inorder();
    std::cout << std::endl;

    return 0;
}
// Output
Inorder traversal of the constructed tree is 10 15 20 30

     20(B)
   /    \
10(B)  30(B)
   \
   15(R)

插入和删除操作

#include <iostream>
#include <queue>

enum Color { RED, BLACK };

struct Node {
    int data;
    Color color;
    Node *left, *right, *parent;

    Node(int data) : data(data), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}

    Node* sibling() {
        if (parent == nullptr) return nullptr;
        return this == parent->left ? parent->right : parent->left;
    }

    bool hasRedChild() {
        return (left != nullptr && left->color == RED) || (right != nullptr && right->color == RED);
    }
};

class RedBlackTree {
public:
    Node* root;

    RedBlackTree() : root(nullptr) {}

    void insert(int data) {
        Node* newNode = new Node(data);
        root = bstInsert(root, newNode);
        fixViolation(newNode);
    }

    void deleteNode(int data) {
        Node* nodeToDelete = search(root, data);
        if (nodeToDelete == nullptr) return;
        deleteBSTNode(nodeToDelete);
    }

    void inorder() { inorderHelper(root); }

    void levelOrder() {
        if (root == nullptr) return;
        std::queue<Node*> q;
        q.push(root);

        while (!q.empty()) {
            Node* temp = q.front();
            std::cout << temp->data << " ";
            q.pop();

            if (temp->left != nullptr)
                q.push(temp->left);

            if (temp->right != nullptr)
                q.push(temp->right);
        }
    }

private:
    Node* bstInsert(Node* root, Node* node) {
        if (root == nullptr) return node;
        if (node->data < root->data) {
            root->left = bstInsert(root->left, node);
            root->left->parent = root;
        } else if (node->data > root->data) {
            root->right = bstInsert(root->right, node);
            root->right->parent = root;
        }
        return root;
    }

    Node* search(Node* root, int data) {
        if (root == nullptr || root->data == data) return root;
        return data < root->data ? search(root->left, data) : search(root->right, data);
    }

    void deleteBSTNode(Node* node) {
        Node* replacement = BSTreplace(node);
        bool bothBlack = ((replacement == nullptr || replacement->color == BLACK) && (node->color == BLACK));
        Node* parent = node->parent;

        if (replacement == nullptr) {
            if (node == root) {
                root = nullptr;
            } else {
                if (bothBlack) {
                    fixDoubleBlack(node);
                } else {
                    if (node->sibling() != nullptr) node->sibling()->color = RED;
                }
                if (node == node->parent->left) {
                    node->parent->left = nullptr;
                } else {
                    node->parent->right = nullptr;
                }
            }
            delete node;
            return;
        }

        if (node->left == nullptr || node->right == nullptr) {
            if (node == root) {
                node->data = replacement->data;
                node->left = node->right = nullptr;
                delete replacement;
            } else {
                if (node == node->parent->left) {
                    parent->left = replacement;
                } else {
                    parent->right = replacement;
                }
                delete node;
                replacement->parent = parent;
                if (bothBlack) {
                    fixDoubleBlack(replacement);
                } else {
                    replacement->color = BLACK;
                }
            }
            return;
        }

        std::swap(node->data, replacement->data);
        deleteBSTNode(replacement);
    }

    Node* BSTreplace(Node* node) {
        if (node->left != nullptr && node->right != nullptr) return successor(node->right);
        if (node->left == nullptr && node->right == nullptr) return nullptr;
        return node->left != nullptr ? node->left : node->right;
    }

    Node* successor(Node* node) {
        Node* temp = node;
        while (temp->left != nullptr) temp = temp->left;
        return temp;
    }

    void fixViolation(Node* node) {
        Node* parent = nullptr;
        Node* grandParent = nullptr;

        while (node != root && node->color == RED && node->parent->color == RED) {
            parent = node->parent;
            grandParent = parent->parent;

            if (parent == grandParent->left) {
                Node* uncle = grandParent->right;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->right) {
                        rotateLeft(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateRight(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            } else {
                Node* uncle = grandParent->left;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->left) {
                        rotateRight(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateLeft(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            }
        }
        root->color = BLACK;
    }

    void fixDoubleBlack(Node* node) {
        if (node == root) return;

        Node* sibling = node->sibling();
        Node* parent = node->parent;
        if (sibling == nullptr) {
            fixDoubleBlack(parent);
        } else {
            if (sibling->color == RED) {
                parent->color = RED;
                sibling->color = BLACK;
                if (sibling == parent->left) {
                    rotateRight(parent);
                } else {
                    rotateLeft(parent);
                }
                fixDoubleBlack(node);
            } else {
                if (sibling->hasRedChild()) {
                    if (sibling->left != nullptr && sibling->left->color == RED) {
                        if (sibling == parent->left) {
                            sibling->left->color = sibling->color;
                            sibling->color = parent->color;
                            rotateRight(parent);
                        } else {
                            sibling->left->color = parent->color;
                            rotateRight(sibling);
                            rotateLeft(parent);
                        }
                    } else {
                        if (sibling == parent->left) {
                            sibling->right->color = parent->color;
                            rotateLeft(sibling);
                            rotateRight(parent);
                        } else {
                            sibling->right->color = sibling->color;
                            sibling->color = parent->color;
                            rotateLeft(parent);
                        }
                    }
                    parent->color = BLACK;
                } else {
                    sibling->color = RED;
                    if (parent->color == BLACK) {
                        fixDoubleBlack(parent);
                    } else {
                        parent->color = BLACK;
                    }
                }
            }
        }
    }

    void rotateLeft(Node* node) {
        Node* rightNode = node->right;
        node->right = rightNode->left;

        if (node->right != nullptr) node->right->parent = node;
        rightNode->parent = node->parent;

        if (node->parent == nullptr) root = rightNode;
        else if (node == node->parent->left) node->parent->left = rightNode;
        else node->parent->right = rightNode;

        rightNode->left = node;
        node->parent = rightNode;
    }

    void rotateRight(Node* node) {
        Node* leftNode = node->left;
        node->left = leftNode->right;

        if (node->left != nullptr) node->left->parent = node;
        leftNode->parent = node->parent;

        if (node->parent == nullptr) root = leftNode;
        else if (node == node->parent->left) node->parent->left = leftNode;
        else node->parent->right = leftNode;

        leftNode->right = node;
        node->parent = leftNode;
    }

    void inorderHelper(Node* root) {
        if (root == nullptr) return;
        inorderHelper(root->left);
        std::cout << root->data << " ";
        inorderHelper(root->right);
    }
};

int main() {
    RedBlackTree tree;
    tree.insert(10);
    tree.insert(20);
    tree.insert(30);
    tree.insert(15);
    tree.insert(25);
    tree.insert(5);

    std::cout << "Inorder traversal of the constructed tree is ";
    tree.inorder();
    std::cout << std::endl;

    tree.deleteNode(20);

    std::cout << "Inorder traversal after deleting 20 is ";
    tree.inorder();
    std::cout << std::endl;

    std::cout << "Level order traversal of the tree is ";
    tree.levelOrder();
    std::cout << std::endl;

    return 0;
}
// Output

Inorder traversal of the constructed tree is 5 10 15 20 25 30 
Inorder traversal after deleting 20 is 5 10 15 25 30 
Level order traversal of the tree is 15 10 30 5 25 


     15(B)
   /    \
10(B)  30(B)
 /     /
5(B)  25(R)

利用Graphviz 库

利用 Graphviz 库的图形化表示我们需要生成的红黑树。

Graphviz Online

#include <iostream>
#include <fstream>
#include <queue>

enum Color { RED, BLACK };

struct Node {
    int data;
    Color color;
    Node *left, *right, *parent;

    Node(int data) : data(data), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}

    Node* sibling() {
        if (parent == nullptr) return nullptr;
        return this == parent->left ? parent->right : parent->left;
    }

    bool hasRedChild() {
        return (left != nullptr && left->color == RED) || (right != nullptr && right->color == RED);
    }
};

class RedBlackTree {
public:
    Node* root;

    RedBlackTree() : root(nullptr) {}

    void insert(int data) {
        Node* newNode = new Node(data);
        root = bstInsert(root, newNode);
        fixViolation(newNode);
    }

    void deleteNode(int data) {
        Node* nodeToDelete = search(root, data);
        if (nodeToDelete == nullptr) return;
        deleteBSTNode(nodeToDelete);
    }

    void inorder() { inorderHelper(root); }

    void levelOrder() {
        if (root == nullptr) return;
        std::queue<Node*> q;
        q.push(root);

        while (!q.empty()) {
            Node* temp = q.front();
            std::cout << temp->data << " ";
            q.pop();

            if (temp->left != nullptr)
                q.push(temp->left);

            if (temp->right != nullptr)
                q.push(temp->right);
        }
    }

    void generateGraphviz(const std::string& filename) {
        std::ofstream file(filename);
        file << "digraph G {\n";
        if (root == nullptr) {
            file << "}\n";
            return;
        }
        generateGraphvizHelper(file, root);
        file << "}\n";
    }

private:
    Node* bstInsert(Node* root, Node* node) {
        if (root == nullptr) return node;
        if (node->data < root->data) {
            root->left = bstInsert(root->left, node);
            root->left->parent = root;
        } else if (node->data > root->data) {
            root->right = bstInsert(root->right, node);
            root->right->parent = root;
        }
        return root;
    }

    Node* search(Node* root, int data) {
        if (root == nullptr || root->data == data) return root;
        return data < root->data ? search(root->left, data) : search(root->right, data);
    }

    void deleteBSTNode(Node* node) {
        Node* replacement = BSTreplace(node);
        bool bothBlack = ((replacement == nullptr || replacement->color == BLACK) && (node->color == BLACK));
        Node* parent = node->parent;

        if (replacement == nullptr) {
            if (node == root) {
                root = nullptr;
            } else {
                if (bothBlack) {
                    fixDoubleBlack(node);
                } else {
                    if (node->sibling() != nullptr) node->sibling()->color = RED;
                }
                if (node == node->parent->left) {
                    node->parent->left = nullptr;
                } else {
                    node->parent->right = nullptr;
                }
            }
            delete node;
            return;
        }

        if (node->left == nullptr || node->right == nullptr) {
            if (node == root) {
                node->data = replacement->data;
                node->left = node->right = nullptr;
                delete replacement;
            } else {
                if (node == node->parent->left) {
                    parent->left = replacement;
                } else {
                    parent->right = replacement;
                }
                delete node;
                replacement->parent = parent;
                if (bothBlack) {
                    fixDoubleBlack(replacement);
                } else {
                    replacement->color = BLACK;
                }
            }
            return;
        }

        std::swap(node->data, replacement->data);
        deleteBSTNode(replacement);
    }

    Node* BSTreplace(Node* node) {
        if (node->left != nullptr && node->right != nullptr) return successor(node->right);
        if (node->left == nullptr && node->right == nullptr) return nullptr;
        return node->left != nullptr ? node->left : node->right;
    }

    Node* successor(Node* node) {
        Node* temp = node;
        while (temp->left != nullptr) temp = temp->left;
        return temp;
    }

    void fixViolation(Node* node) {
        Node* parent = nullptr;
        Node* grandParent = nullptr;

        while (node != root && node->color == RED && node->parent->color == RED) {
            parent = node->parent;
            grandParent = parent->parent;

            if (parent == grandParent->left) {
                Node* uncle = grandParent->right;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->right) {
                        rotateLeft(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateRight(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            } else {
                Node* uncle = grandParent->left;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->left) {
                        rotateRight(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateLeft(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            }
        }
        root->color = BLACK;
    }

    void fixDoubleBlack(Node* node) {
        if (node == root) return;

        Node* sibling = node->sibling();
        Node* parent = node->parent;
        if (sibling == nullptr) {
            fixDoubleBlack(parent);
        } else {
            if (sibling->color == RED) {
                parent->color = RED;
                sibling->color = BLACK;
                if (sibling == parent->left) {
                    rotateRight(parent);
                } else {
                    rotateLeft(parent);
                }
                fixDoubleBlack(node);
            } else {
                if (sibling->hasRedChild()) {
                    if (sibling->left != nullptr && sibling->left->color == RED) {
                        if (sibling == parent->left) {
                            sibling->left->color = sibling->color;
                            sibling->color = parent->color;
                            rotateRight(parent);
                        } else {
                            sibling->left->color = parent->color;
                            rotateRight(sibling);
                            rotateLeft(parent);
                        }
                    } else {
                        if (sibling == parent->left) {
                            sibling->right->color = parent->color;
                            rotateLeft(sibling);
                            rotateRight(parent);
                        } else {
                            sibling->right->color = sibling->color;
                            sibling->color = parent->color;
                            rotateLeft(parent);
                        }
                    }
                    parent->color = BLACK;
                } else {
                    sibling->color = RED;
                    if (parent->color == BLACK) {
                        fixDoubleBlack(parent);
                    } else {
                        parent->color = BLACK;
                    }
                }
            }
        }
    }

    void rotateLeft(Node* node) {
        Node* rightNode = node->right;
        node->right = rightNode->left;

        if (node->right != nullptr) node->right->parent = node;
        rightNode->parent = node->parent;

        if (node->parent == nullptr) root = rightNode;
        else if (node == node->parent->left) node->parent->left = rightNode;
        else node->parent->right = rightNode;

        rightNode->left = node;
        node->parent = rightNode;
    }

    void rotateRight(Node* node) {
        Node* leftNode = node->left;
        node->left = leftNode->right;

        if (node->left != nullptr) node->left->parent = node;
        leftNode->parent = node->parent;

        if (node->parent == nullptr) root = leftNode;
        else if (node == node->parent->left) node->parent->left = leftNode;
        else node->parent->right = leftNode;

        leftNode->right = node;
        node->parent = leftNode;
    }

    void inorderHelper(Node* root) {
        if (root == nullptr) return;
        inorderHelper(root->left);
        std::cout << root->data << " ";
        inorderHelper(root->right);
    }

    void generateGraphvizHelper(std::ofstream& file, Node* root) {
        if (root->left != nullptr) {
            file << root->data << " -> " << root->left->data << ";\n";
            generateGraphvizHelper(file, root->left);
        } else {
            file << "null" << root->data << "L [shape=point];\n";
            file << root->data << " -> null" << root->data << "L;\n";
        }

        if (root->right != nullptr) {
            file << root->data << " -> " << root->right->data << ";\n";
            generateGraphvizHelper(file, root->right);
        } else {
            file << "null" << root->data << "R [shape=point];\n";
            file << root->data << " -> null" << root->data << "R;\n";
        }
    }
};

int main() {
    RedBlackTree tree;
    tree.insert(10);
    tree.insert(20);
    tree.insert(30);
    tree.insert(15);
    tree.insert(25);
    tree.insert(5);

    tree.generateGraphviz("rbtree.dot");

    std::cout << "Graphviz dot file generated as rbtree.dot" << std::endl;

    return 0;
}
// Output
digraph G {
10 -> 5;
10 -> 20;
20 -> 15;
20 -> 30;
30 -> 25;
null5L [shape=point];
5 -> null5L;
null5R [shape=point];
5 -> null5R;
null15L [shape=point];
15 -> null15L;
null15R [shape=point];
15 -> null15R;
null25L [shape=point];
25 -> null25L;
null25R [shape=point];
25 -> null25R;
null30L [shape=point];
30 -> null30L;
null30R [shape=point];
30 -> null30R;
}

  10
 /  \
5    20
    /  \
   15  30
       /
      25

总结

红黑树(Red-Black Tree)是一种自平衡二叉搜索树,常用于需要高效插入、删除和查找操作的数据结构中。红黑树的特点包括每个节点是红色或黑色、根节点是黑色、红色节点的子节点必须是黑色、从任一节点到其每个叶子节点的路径上的黑色节点数目相同。

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

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

相关文章

CentOS 7 安装MySQL以及常见问题解决

访问网站&#xff1a;http://repo.mysql.com 找到适配CentOS 7版本的MySQL 的YUM仓库包rpm文件&#xff0c;如下图 下载后&#xff0c;找到安装包的位置 空白处右键&#xff0c;选择在终端打开 查看当前目录下文件 # 安装MySQL 5.7的YUM仓库包rpm -ivh mysql57-community-rele…

学生成绩评分 - Scala

文章目录 一、第1关&#xff1a;对学生成绩进行评分 一、第1关&#xff1a;对学生成绩进行评分 实训目标 掌握 Scala 中运算符嵌套的使用 了解 if-else if-else 语句的使用 实训分析 利用条件运算符的嵌套来完成此题&#xff1a;学习成绩 150 - 90 分的同学成绩评分为&#…

【安防视界新飞跃】液晶拼接屏:安防事业的“超级守护者”!

在守护安全的征途上&#xff0c;每一双“电子眼”都是智慧与科技的结晶。视频监控&#xff0c;这个安防领域的超级英雄&#xff0c;正以它敏锐的洞察力&#xff0c;24小时不间断地守望着我们的世界。而今&#xff0c;随着科技的飞跃&#xff0c;液晶拼接屏如同安防界的“变形金…

windows环境下,怎么查看本机的IP、MAC地址和端口占用情况

1.输入ipconfig,按回车。即查看了IP地址&#xff0c;子码掩码&#xff0c;网关信息。 2.输入ipconfig/all,按回车。即查看了包含IP地址&#xff0c;子码掩码&#xff0c;网关信息以及MAC地址 3.我们有时在启动应用程序的时候提示端口被占用&#xff0c;如何知道谁占有了我们需要…

JAVAFX打包部署真正能用的办法(jdk21,javafx23)IntelliJ IDEA

我之前创建了javafx项目&#xff0c;想打包试试。一试&#xff0c;全是坑&#xff0c;所以记录下来&#xff0c;为有缘人节约时间。直接构建工件是错误的&#xff0c;别尝试了&#xff0c;找不在JDK的。我也花了一天多的时间尝试了网上各种大神的办法&#xff0c;就没找到一个是…

从手动到自动再到智能,IT运维的进击之路

过去十年&#xff0c;科技化进程飞速发展&#xff0c;作为保障企业信息安全运行的运维行业&#xff0c;从手动发展到自动&#xff0c;又从自动发展到智能&#xff0c;IT运维也从原来的辅助角色逐渐变成了业务推动。 手动——自动——智能的发展 以银行用户为例&#xff0c;最初…

面试题之CSS

1. 引入样式的方式 外部样式 link import 区别 内部样式 /* 写在头部标签 */ <style></style>行内样式 2. 三行代码画三角形 .triangle{width:0px;border:100px solid;border-color:transparent transparent transparent red; }3.属性的继承 可继承的属性 …

边缘检测(一)-灰度图像边缘检测方法

灰度图像边缘检测是数字图像处理与机器视觉中经常遇到的一个问题&#xff0c;边缘检测是否连续、光滑是判断检测方法优劣的一个重要标准&#xff0c;下面通过一个实例提供灰度图像边缘检测方法&#xff0c;该方法对其他图像检测也具有一定的参考价值。 首先&#xff0c;读入一幅…

MongoDB使用$addToSet向数组中添加元素

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第66篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

前端菜鸡学习日记 -- computed和watch的用法

目录 1.computed&#xff1a; 2.watch&#xff1a; 哈喽哇大家&#xff0c;又是新的一周&#xff0c;因为一些特殊的原因&#xff0c;所以目前是比较闲的&#xff0c;就趁机多学习一点东西把&#xff0c;这些学习日记就是学习中的笔记咯&#xff0c;流水账日记则是工作中遇到…

基于Elementui组件,在vue中实现多种省市区前端静态JSON数据展示并支持与后端交互功能,提供后端名称label和id

基于Elementui组件&#xff0c;在vue中实现多种省市区前端静态数据&#xff08;本地JSON数据&#xff09;展示并支持与后端交互功能&#xff0c;提供后端名称label和id 话不多说&#xff0c;先上图 1.支持传递给后端选中省市区的id和名称&#xff0c;示例非常完整&#xff0c…

WordPress简单好看的线报主题模板源码

安装说明 到WordPress管理后台中的「外观」-「主题」中点击「添加」&#xff0c;选择baolog的主题包进行上传安装并启用即可。 提示&#xff1a;为了防止主题不兼容&#xff0c;请在安装主题前进行数据备份&#xff0c;防止数据字段重复覆盖等情况发生。 源码截图 源码下载 …

Git--Part3--远程操作 配置 标签管理

theme: nico 远程仓库 Git 是分布式版本控制系统&#xff0c;同⼀个 Git 仓库&#xff0c;可以分布到不同的机器上。怎么分布呢&#xff1f; 最早&#xff0c;肯定只有⼀台机器有⼀个原始版本库&#xff0c;此后&#xff0c;别的机器可以 “克隆” 这个原始版本库&#xff0…

php配合fiddler批量下载淘宝天猫商品数据分享

有个做电商的朋友问我&#xff0c;每次上款&#xff0c;需要手动去某宝去搬运商品图片视频&#xff0c;问我能不能帮忙写个脚本&#xff0c;朋友开口了&#xff0c;那就尝试一下 首先打开某宝&#xff0c;访问一款商品&#xff0c;找出他的数据来源 通过观察我们发现主图数据来…

网络学习(三)TCP三次握手、四次挥手,及Wireshark抓包验证

目录 一、什么是 TCP 三次握手&#xff1f;二、什么是 TCP 四次挥手&#xff1f;三、Wireshark抓包验证3.1 如何捕获三次握手、四次挥手3.2 TCP 三次握手的记录3.3 数据传输3.4 TCP 四次挥手的记录 一、什么是 TCP 三次握手&#xff1f; TCP&#xff08;Transmission Control …

设计模式(三)代理模式

目录 一、什么是代理模式 二、静态代理 1、定义 2、代码 2.1、接口 2.2、被代理对象 2.3、代理对象 2.4、测试 三、动态代理 1、定义 2、代码 2.1、接口 2.2、目标对象 2.3、代理对象 2.4、测试 一、什么是代理模式 代理模式(Proxy Pattern)是一种结构性模式。代理模…

学习笔记——网络管理与运维——SNMP(SNMP原理)

四、SNMP原理 SNMP的工作原理基于客户端-服务器模型。其中&#xff0c;网络管理系统是客户端&#xff0c;而网络设备是服务器。客户端向服务器发送请求消息(即"Get"或"Set"命令)来获取或修改服务器的信息。服务器收到请求消息后&#xff0c;会返回相应的响…

物联网技术-第2章-物联网技术架构

目录 1.1为什么需要物联网架构 1.2系统体系结构的基本概念 1.3物联网工作过程与人的智能处理问题过程比较 1.4物联网的四层体系架构 1.4.1物联网感知层 1.4.1.1感知层要解决的问题 1.4.1.2感知层的形态 1.4.2物联网网络层 1.4.2.1网络层相关概念 1.4.2.2计算机网络的逻…

深度学习神经网络协同过滤模型(NCF)与用户协同过滤(UCF)的区别

一、效果图 点我查看在线demo 二、启发式推荐系统 推荐系统的核心是根据用户的兴趣需求&#xff0c;给用户推荐喜欢的内容。常用的推荐算法有启发式推荐算法&#xff0c;可分为基于用户的 协同过滤&#xff0c;基于物品的协同过滤。 1、基于用户的协同过滤&#xff08;UCF…

Api Post快速上手教程

Apipost快速上手教程可以按照以下步骤进行&#xff1a; 一、准备工作 访问Apipost官网下载并安装Apipost客户端&#xff0c;或者选择使用其Web端版本。注册并登录Apipost账号&#xff0c;以便更好地管理和使用你的项目。官网&#xff1a;Apipost-API 文档、设计、调试、自动化…