Python实现二叉搜索树的删除功能

2023-11-20

Python实现二叉搜索树的删除功能

二叉搜索树(二叉查找树,Binary Search Tree)又称为排序二叉树、有序二叉树。

二叉搜索树的实现可以参考:https://blog.csdn.net/weixin_43790276/article/details/105753543

本文使用 Python 实现二叉搜索树的删除功能,在此之前必须先知道二叉搜索树的特性:

1. 如果二叉树的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。

2. 如果二叉树的右子树不为空,则右子树上所有节点的值均大于它的根节点的值。

3. 如果独立地看,左子树、右子树也分别为二叉搜素树。

一、准备二叉搜索树类

在实现二叉搜索树的删除功能前,先实现一个二叉搜索树的类 SearchBinaryTree 。

# coding=utf-8
class Node(object):
    """节点类"""
    def __init__(self, data, left_child=None, right_child=None):
        self.data = data
        self.parent = None
        self.left_child = left_child
        self.right_child = right_child


class SearchBinaryTree(object):
    """二叉树类"""
    def __init__(self):
        self.__root = None
        self.prefix_branch = '├'
        self.prefix_trunk = '|'
        self.prefix_leaf = '└'
        self.prefix_empty = ''
        self.prefix_left = '─L─'
        self.prefix_right = '─R─'

    def is_empty(self):
        return not self.__root

    @property
    def root(self):
        return self.__root

    @root.setter
    def root(self, value):
        self.__root = value if isinstance(value, Node) else Node(value)

    def show_tree(self):
        if self.is_empty():
            print('空二叉树')
            return
        print('-' * 20)
        print(self.__root.data)
        self.__print_tree(self.__root)
        print('-' * 20)

    def insert(self, root, value):
        """二叉搜索树插入节点-递归"""
        node = value if isinstance(value, Node) else Node(value)
        if self.is_empty():
            self.root = node
            return
        if root is None:
            root = node
        elif node.data < root.data:
            root.left_child = self.insert(root.left_child, value)
            root.left_child.parent = root
        elif node.data > root.data:
            root.right_child = self.insert(root.right_child, value)
            root.right_child.parent = root
        return root

    def __print_tree(self, node, prefix=None):
        if prefix is None:
            prefix, prefix_left_child = '', ''
        else:
            prefix = prefix.replace(self.prefix_branch, self.prefix_trunk)
            prefix = prefix.replace(self.prefix_leaf, self.prefix_empty)
            prefix_left_child = prefix.replace(self.prefix_leaf, self.prefix_empty)
        if self.has_child(node):
            if node.right_child is not None:
                print(prefix + self.prefix_branch + self.prefix_right + str(node.right_child.data))
                if self.has_child(node.right_child):
                    self.__print_tree(node.right_child, prefix + self.prefix_branch + ' ')
            else:
                print(prefix + self.prefix_branch + self.prefix_right)
            if node.left_child is not None:
                print(prefix + self.prefix_leaf + self.prefix_left + str(node.left_child.data))
                if self.has_child(node.left_child):
                    prefix_left_child += '  '
                    self.__print_tree(node.left_child, self.prefix_leaf + prefix_left_child)
            else:
                print(prefix + self.prefix_leaf + self.prefix_left)

    def has_child(self, node):
        return node.left_child is not None or node.right_child is not None

    def __str__(self):
        return str(self.__class__)

上面的代码实现了一个节点类 Node,实现了二叉搜索树的类 SearchBinaryTree。在 SearchBinaryTree 中,实现了判断二叉搜索树是否为空的 is_empty() 方法、一对供实例对象调用的 root() 方法、按树形结构打印二叉搜索树的 show_tree() 方法和添加数据到二叉搜索树中的 insert(root, value)方法。 

现在先在树中添加一些节点,供后面的删除方法使用。

if __name__ == '__main__':
    tree = SearchBinaryTree()
    data = [50, 77, 55, 29, 10, 30, 66, 80, 51, 18, 90, 78, 79]
    for i in data:
        tree.insert(tree.root, i)
    tree.show_tree()

运行结果:

--------------------
50
├─R─77
| ├─R─80
| | ├─R─90
| | └─L─78
| |   ├─R─79
| |   └─L─
| └─L─55
|   ├─R─66
|   └─L─51
└─L─29
  ├─R─30
  └─L─10
    ├─R─18
    └─L─
--------------------

添加数据后的二叉搜索树如下图:

添加完成节点后,继续准备删除节点时需要使用到的方法。返回二叉搜索树的高度的方法 height(root),用于判断被删除的节点在树的第几层。在二叉搜索树中查找节点的方法 search(root, data),要从二叉搜索树中删除节点,首先要保证节点是属于二叉搜索树的,所以先搜索节点是否在二叉搜索树中。返回二叉搜索树中值最大的节点的方法 get_max(root) 和返回值最小的节点的方法 get_min(root) ,用于寻找被删除节点的前继节点或后继节点。

    def height(self, root):
        """二叉树的深度"""
        if root.data is None:
            return 0
        if root.left_child is None and root.right_child is None:
            return 1
        if root.left_child is not None and root.right_child is None:
            return 1 + self.height(root.left_child)
        if root.left_child is None and root.right_child is not None:
            return 1 + self.height(root.right_child)
        if root.left_child is not None and root.right_child is not None:
            return 1 + max(self.height(root.left_child), self.height(root.right_child))

    def search(self, root, data):
        """二叉搜索树的查询操作"""
        if root is None:
            return
        if root.data == data:
            return root
        elif data < root.data:
            return self.search(root.left_child, data)
        elif data > root.data:
            return self.search(root.right_child, data)

    def get_max(self, root):
        """查找二叉搜索树值最大的节点"""
        if self.is_empty():
            return
        return self.get_max(root.right_child) if root.right_child else root

    def get_min(self, root):
        """查找二叉搜索树值最小的节点"""
        if self.is_empty():
            return
        return self.get_min(root.left_child) if root.left_child else root

二、二叉搜索树删除节点

如果被删除的节点是叶节点,比较好办,找到这个节点,然后删除。如果被删除的节点不是叶节点,节点有左子树或右子树,或两者都有,删除节点后,左子树和右子树会跟着节点一起从树中“断”掉,那就不仅仅是删除节点了,而是把子树给全部删除了。所以,删除非叶节点时,必须从子树中选择一个节点来填补被删除的节点位置,避免树的断裂,也避免“牵连”到其他的节点,还要保证删除节点后的二叉树依然是一棵二叉搜索树,满足二叉搜索树的特性。

由简到繁,根据被删除节点是否有左右子树,二叉搜索树的删除可以分为三种情况,被删除节点为叶节点、被删除节点只有一棵子树和被删除节点有两棵子树。

1. 被删除节点为叶节点,即被删除节点没有左子树和右子树。删除叶节点后,不会破坏整棵树的结构,只要找到此节点,然后将节点从二叉树中“断开”(父节点的指针指向空)即可。在上面添加数据后的二叉搜索树中,随机选一个叶节点,如 66。

    def _delete_no_child(self, node):
        """删除叶节点"""
        if node == self.root:
            self.root = None
            return
        if node == node.parent.left_child:
            node.parent.left_child = None
        else:
            node.parent.right_child = None
        node.parent = None

_delete_no_child(node): 删除叶节点的方法。这个方法只属于删除的部分功能,所以在前面加一个下划线,表示等删除功能完全实现后,不会再直接使用。

    node = tree.search(tree.root, 66)
    tree._delete_no_child(node)
    tree.show_tree()

运行结果:

--------------------
50
├─R─77
| ├─R─80
| | ├─R─90
| | └─L─78
| |   ├─R─79
| |   └─L─
| └─L─55
|   ├─R─
|   └─L─51
└─L─29
  ├─R─30
  └─L─10
    ├─R─18
    └─L─
--------------------

删除节点 66 后的二叉搜索树结构如下图。

2. 被删除节点只有一棵子树,即被删除节点只有左子树或只有右子树。删除节点后,为了保证节点的子树不被“牵连”,要将节点的子树进行“补位”。如删除下图中的节点 10,被删除节点是其父节点的左子节点,被删除节点有右子树,则删除节点后,直接将被删除节点的右子树补位成为其父节点的左子树。

    def _delete_one_child(self, node):
        """删除有一个子节点的节点"""
        if node.left_child:
            if node.parent and node.parent.left_child == node:
                node.left_child.parent = node.parent
                node.parent.left_child = node.left_child
            elif node.parent and node.parent.right_child == node:
                node.left_child.parent = node.parent
                node.parent.right_child = node.left_child
            else:
                self.root = node.left_child
                node.left_child.parent = None
                node.left_child = None
        else:
            if node.parent and node.parent.left_child == node:
                node.right_child.parent = node.parent
                node.parent.left_child = node.right_child
            elif node.parent and node.parent.right_child == node:
                node.right_child.parent = node.parent
                node.parent.right_child = node.right_child
            else:
                self.root = node.right_child
                node.right_child.parent = None
                node.right_child = None
        node.left_child = None
        node.parent = None

_delete_one_child(node): 删除只有一棵子树的节点。同理,这个方法也只属于删除的部分功能,所以在前面加一个下划线,表示删除功能完全实现后,不会直接使用。

    node = tree.search(tree.root, 10)
    tree._delete_one_child(node)
    tree.show_tree()

运行结果:

--------------------
50
├─R─77
| ├─R─80
| | ├─R─90
| | └─L─78
| |   ├─R─79
| |   └─L─
| └─L─55
|   ├─R─66
|   └─L─51
└─L─29
  ├─R─30
  └─L─18
--------------------

删除节点 10 后的二叉搜索树结构如下图。

3. 被删除节点有两棵子树,即被删除节点同时有左子树和右子树。删除节点后,为了避免两棵子树从树中“断裂”,必须找到一个节点来填补被删除节点的位置。如删除下图中的节点 77,必须找一个节点来补位,否则两棵子树也会被删除。

为了保证删除节点后二叉树仍然是一棵二叉搜索树,补位节点有两种选择方式,选择被删除节点的前继节点或后继节点,前继节点一定存在左子树中,后继节点一定存在右子树中,选择两种方式都可以,本文选择后继节点。

那什么是后继节点和前继节点?如果将二叉搜索树中的节点按存储的数值的大小升序排列,排在当前节点的后一个节点就是后继节点,排在当前节点的前一个节点就是前继节点。节点 77 的后继节点是 78。

将节点删除后,找到它的后继节点,将后继节点补位到被删除节点的位置,这样就保证了被删除节点的两棵子树没有断裂。但是还没有完,后继节点补位之后,相当于是将后继节点从它原来的位置删除了。节点 78 补位到 77 的位置后,相当于将节点 78 从原来的位置删除了。

所以还要对后继节点进行处理,后继节点可能是叶节点,可以用情况1,后继节点可能有右子树,可以用情况2,如节点 78,后继节点不可能有左子树,不用考虑。

为什后继节点一定没有左子树?假设后继节点有左子树,根据二叉搜索树的特性,后继节点的值比当前节点大,后继节点一定在当前节点的右子树中,而后继节点的左子树中的节点值要小于后继节点的值,这样,就存在比当前节点大又比后继节点小的节点,与后继节点的定义矛盾,所以假设不成立。

当然这里并不是说二叉搜索树中所有节点的后继节点都没有左子树,而是当一个节点有两棵子树时,它的后继节点不可能有左子树。

到这里,删除节点 77 分为两步,第一步是找到后继节点 78,将节点 78 补位到 77 的位置,第二步是删除节点 78 。

    def delete(self, value):
        """二叉搜索树删除节点"""
        if self.height(self.root) >= 1:
            node_delete = self.search(self.root, value)
            if node_delete:
                self._delete(node_delete)
            else:
                raise KeyError("Error, value not in this tree")
        else:
            raise KeyError("Error, value not in this tree")

    def _delete(self, node):
        """删除节点"""
        if not node.left_child and not node.right_child:
            self._delete_no_child(node)
        elif node.left_child and not node.right_child or not node.left_child and node.right_child:
            self._delete_one_child(node)
        else:
            rear_node = self.get_min(node.right_child)
            node.data = rear_node.data
            self._delete(rear_node)

_delete(node): 删除节点的方法。该方法中通过 get_min() 方法找到当前节点的后继节点 rear_node ,然后进行补位操作。而删除后继节点的操作,只要递归一次就可以,因为删除后继节点的方法一定属于前面的两种情况之一。

delete(node): 删除节点的通用方法。前面提过,要删除节点,首先节点要属于当前二叉搜索树。所以无法指定节点来删除,只能根据节点中存储的值,先在树中进行搜索,找到了再执行删除操作。

    tree.delete(77)
    tree.show_tree()

运行结果:

--------------------
50
├─R─78
| ├─R─80
| | ├─R─90
| | └─L─79
| └─L─55
|   ├─R─66
|   └─L─51
└─L─29
  ├─R─30
  └─L─10
    ├─R─18
    └─L─
--------------------

删除节点 77 后的二叉搜索树结构如下图。

三、完整代码

# coding=utf-8
class Node(object):
    """节点类"""
    def __init__(self, data, left_child=None, right_child=None):
        self.data = data
        self.parent = None
        self.left_child = left_child
        self.right_child = right_child


class SearchBinaryTree(object):
    """二叉树类"""
    def __init__(self):
        self.__root = None
        self.prefix_branch = '├'
        self.prefix_trunk = '|'
        self.prefix_leaf = '└'
        self.prefix_empty = ''
        self.prefix_left = '─L─'
        self.prefix_right = '─R─'

    def is_empty(self):
        return not self.__root

    @property
    def root(self):
        return self.__root

    @root.setter
    def root(self, value):
        self.__root = value if isinstance(value, Node) else Node(value)

    def show_tree(self):
        if self.is_empty():
            print('空二叉树')
            return
        print('-' * 20)
        print(self.__root.data)
        self.__print_tree(self.__root)
        print('-' * 20)

    def insert(self, root, value):
        """二叉搜索树插入节点-递归"""
        node = value if isinstance(value, Node) else Node(value)
        if self.is_empty():
            self.root = node
            return
        if root is None:
            root = node
        elif node.data < root.data:
            root.left_child = self.insert(root.left_child, value)
            root.left_child.parent = root
        elif node.data > root.data:
            root.right_child = self.insert(root.right_child, value)
            root.right_child.parent = root
        return root

    def delete(self, value):
        """二叉搜索树删除节点"""
        if self.height(self.root) >= 1:
            node_delete = self.search(self.root, value)
            if node_delete:
                self._delete(node_delete)
            else:
                raise KeyError("Error, value not in this tree")
        else:
            raise KeyError("Error, value not in this tree")

    def _delete(self, node):
        """删除节点"""
        if not node.left_child and not node.right_child:
            self._delete_no_child(node)
        elif node.left_child and not node.right_child or not node.left_child and node.right_child:
            self._delete_one_child(node)
        else:
            rear_node = self.get_min(node.right_child)
            node.data = rear_node.data
            self._delete(rear_node)

    def _delete_no_child(self, node):
        """删除叶节点"""
        if node == self.root:
            self.root = None
            return
        if node == node.parent.left_child:
            node.parent.left_child = None
        else:
            node.parent.right_child = None
        node.parent = None

    def _delete_one_child(self, node):
        """删除有一个子节点的节点"""
        if node.left_child:
            if node.parent and node.parent.left_child == node:
                node.left_child.parent = node.parent
                node.parent.left_child = node.left_child
            elif node.parent and node.parent.right_child == node:
                node.left_child.parent = node.parent
                node.parent.right_child = node.left_child
            else:
                self.root = node.left_child
                node.left_child.parent = None
                node.left_child = None
        else:
            if node.parent and node.parent.left_child == node:
                node.right_child.parent = node.parent
                node.parent.left_child = node.right_child
            elif node.parent and node.parent.right_child == node:
                node.right_child.parent = node.parent
                node.parent.right_child = node.right_child
            else:
                self.root = node.right_child
                node.right_child.parent = None
                node.right_child = None
        node.left_child = None
        node.parent = None

    def height(self, root):
        """二叉树的深度"""
        if root.data is None:
            return 0
        if root.left_child is None and root.right_child is None:
            return 1
        if root.left_child is not None and root.right_child is None:
            return 1 + self.height(root.left_child)
        if root.left_child is None and root.right_child is not None:
            return 1 + self.height(root.right_child)
        if root.left_child is not None and root.right_child is not None:
            return 1 + max(self.height(root.left_child), self.height(root.right_child))

    def search(self, root, data):
        """二叉搜索树的查询操作"""
        if root is None:
            return
        if root.data == data:
            return root
        elif data < root.data:
            return self.search(root.left_child, data)
        elif data > root.data:
            return self.search(root.right_child, data)

    def get_max(self, root):
        """查找二叉搜索树值最大的节点"""
        if self.is_empty():
            return
        return self.get_max(root.right_child) if root.right_child else root

    def get_min(self, root):
        """查找二叉搜索树值最小的节点"""
        if self.is_empty():
            return
        return self.get_min(root.left_child) if root.left_child else root

    def __print_tree(self, node, prefix=None):
        if prefix is None:
            prefix, prefix_left_child = '', ''
        else:
            prefix = prefix.replace(self.prefix_branch, self.prefix_trunk)
            prefix = prefix.replace(self.prefix_leaf, self.prefix_empty)
            prefix_left_child = prefix.replace(self.prefix_leaf, self.prefix_empty)
        if self.has_child(node):
            if node.right_child is not None:
                print(prefix + self.prefix_branch + self.prefix_right + str(node.right_child.data))
                if self.has_child(node.right_child):
                    self.__print_tree(node.right_child, prefix + self.prefix_branch + ' ')
            else:
                print(prefix + self.prefix_branch + self.prefix_right)
            if node.left_child is not None:
                print(prefix + self.prefix_leaf + self.prefix_left + str(node.left_child.data))
                if self.has_child(node.left_child):
                    prefix_left_child += '  '
                    self.__print_tree(node.left_child, self.prefix_leaf + prefix_left_child)
            else:
                print(prefix + self.prefix_leaf + self.prefix_left)

    def has_child(self, node):
        return node.left_child is not None or node.right_child is not None

    def __str__(self):
        return str(self.__class__)


if __name__ == '__main__':
    tree = SearchBinaryTree()
    data = [50, 77, 55, 29, 10, 30, 66, 80, 51, 18, 90, 78, 79]
    for i in data:
        tree.insert(tree.root, i)
    # tree.show_tree()

    # node = tree.search(tree.root, 66)
    # tree._delete_no_child(node)
    # tree.show_tree()

    # node = tree.search(tree.root, 10)
    # tree._delete_one_child(node)
    # tree.show_tree()

    tree.delete(80)
    tree.show_tree()

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python实现二叉搜索树的删除功能 的相关文章

  • Maven--快照(SNAPSHOT)版本介绍

    Maven快照 SNAPSHOT 版本介绍 在 Maven 中 任何一个项目和构件都必须有自己的版本 版本的值可能是 1 0 0 1 0 alpha 4 1 3 SNAPSHOT 等 其中 1 0 0 1 0 alpha 4 是稳定的发布版
  • Python实现数值列表(数组)的逆置输出

    题目描述 输入10个数字 然后逆序输出 输入 十个整数 输出 逆序输出 空格分开 样例输入 1 2 3 4 5 6 7 8 9 0 样例输出 0 9 8 7 6 5 4 3 2 1 arr list map int input split
  • mgrid

    numpy中的一个函数叫mgrid 例子 import numpy as np X Y np mgrid 0 1 1 1 7 0 1 1 1 7 print X shape print X print Y shape print Y 生成两
  • 分配操作菜单

    目录 概述 介绍 数据库 后端 前端 效果展示 概述 在写后台管理系统时 我们可以根据不同的登录人 给予不同的功能菜单 如 给楼栋管理员登录时分配 楼栋管理 宿舍管理 所以在数据库就要创建 1 登录人与角色表 2再给角色表分配操作菜单 登录
  • va_start和va_end使用详解

    转载于 http www cnblogs com hanyonglu archive 2011 05 07 2039916 html 本文主要介绍va start和va end的使用及原理 在以前的一篇帖子Format MessageBox

随机推荐

  • 工作日记NO.13

    1 执行机安装Qt 2 编译精简Qt5 15 X库 3 研究liadwg项目 尝试编译
  • 元宇宙与数字孪生有区别

    在元宇宙爆红之前 有一项技术已经慢慢渗透到各行各业之中 它可以逼真 实时地还原现实世界 它就是 数字孪生 目前很多人认为元宇宙与数字孪生的区别不大 元宇宙是数字孪生在技术层面的进阶与优化 其实不然 元宇宙和数字孪生虽然都属于用数字技术构建虚
  • 【廖雪峰python入门笔记】字符串_转义字符的使用

    转义字符的使用 字符串可以用 或者 括起来表示 如果字符串本身包含 怎么办 比如我们要表示字符串 I m OK 这时 可以用 括起来表示 I m OK 类似的 如果字符串包含 我们就可以用 括起来表示 Learn Python in imo
  • Qt 教程(传智教育)

    1 一个简单的 Qt 应用程序 Qt一个类对应一个头文件 类名就是头文件名 QApplication 应用程序类 管理图形用户界面应用程序的控制流和主要设置 是 Qt 的整个后台管理的命脉 它包含主事件循环 在其中来自窗口系统和其它资源的所
  • 快速排序(三种算法实现和非递归实现)

    快速排序 Quick Sort 是对冒泡排序的一种改进 基本思想是选取一个记录作为枢轴 经过一趟排序 将整段序列分为两个部分 其中一部分的值都小于枢轴 另一部分都大于枢轴 然后继续对这两部分继续进行排序 从而使整个序列达到有序 递归实现 v
  • (转)原理到实现

    转 https mp weixin qq com s Mrr1Rnl 594Gyyn9fHekjw 1NFS介绍 NFS是Network File System的简写 即网络文件系统 NFS是FreeBSD支持的文件系统中的一种 NFS基于
  • opencv中resize错误可能导致的原因之一

    cv2 error OpenCV 4 5 5 1 error 5 Bad argument in function resize 在用resize时会产生这个错误 有可能时传入的图片不存在了 假如你是从摄像头读取的图片 需要通过 ret f
  • vue 子父组件间的那些事儿——搭建项目(一)

    一 搭建vue项目 1 环境准备 基于nodejs vue cli cnpm 搭建vue项目 由于本博主已经具备以上环境 现在直接进行项目搭建 环境准备可参考这篇博客 https blog csdn net xcymorningsun ar
  • uni-app使用CSS实现无限旋转动画

    本来想用uni createAnimation创建一个旋转动画 发现转完一圈后就不动了 没法循环旋转 后来又用setInterval每隔一个周期就把旋转角度加180度 发现运行一段时间后动画逐渐崩坏 应该是动画的周期和定时器的周期时间没有完
  • 为什么重写equals就要重写hashcode

    在学习java的时候常常提到 重写equals就要重写hashcode hashcode和equals是个绑定在一起的东西 要了解这个我们需要了解两个函数 hashCode 方法 散列码 hash code 是由对象导出的一个整型值 散列码
  • js 设置网页打印的页眉页脚和页边距

    http blog sina com cn s blog 629788b70100n9zr html
  • React 教程及其API接口文档

    React 详细中文开发文档 可以阅读 http reactjs cn react docs tutorial html 英文原文 http facebook github io react 中文论坛 http react china or
  • mmdetection No module named 'imagecorruptions'

    报错原因 imagecorruptions cpp文件需要重新编译 解决方案 mmdetection 目录下运行 python setup py develop
  • 权重计算方法_终身持续学习-可塑权重巩固(Elastic Weight Consolidation)

    回过头来梳理了一下EWC方法 在持续终身学习里面很经典的一个方法 Deepmind写的晦涩难懂x 当时折腾了好久才理解 因为自己有点菜 条件和目标 论文中 假设存在两个任务A和B 可以推广为旧任务和新任务 数据集分别为D和D 模型学习完任务
  • 2021-07-01 RuoYi-Vue-Plus

    提示 https gitee com JavaLionLi RuoYi Vue Plus from gitee search 疯狂的狮子li icon https www iconfont cn 渐变色 http color oulu me
  • ASP.NET 中实现 读取数据库二进制 下载

    实现思路 首先从数据库中把二进制 写入到服务器上 生成临时文件 然后再从服务器上 进行下载 具体代码如下 string filename test jpg 这个就是要存放到服务器的文件名 Response ContentType appli
  • Jenkins自动化测试

    学习 Jenkins 自动化测试的系列文章 Robot Framework 概念 Robot Framework 安装 Pycharm Robot Framework 环境搭建 Robot Framework 介绍 Jenkins 自动化测
  • mariadb主从复制

    1 准备两台服务器 一台设置为master服务器 一台设置为slave服务器 两台服务器先关闭防火墙 关闭selinux systemctl stop firewalld setenforce 0 两台服务器都需要安装mariadb 这里用
  • google c++代码规范-中文翻译

    头文件 lt Header Files gt The define Guard 所有的头文件都应该使用 define等来防止头文件重复包含 宏的格式应该为
  • Python实现二叉搜索树的删除功能

    Python实现二叉搜索树的删除功能 二叉搜索树 二叉查找树 Binary Search Tree 又称为排序二叉树 有序二叉树 二叉搜索树的实现可以参考 https blog csdn net weixin 43790276 articl