Python实现红黑树的插入操作
Python实现红黑树的插入操作
本专栏中的上一篇文章介绍了什么是红黑树,以及红黑树的旋转和变色。
参考:https://blog.csdn.net/weixin_43790276/article/details/106042360
本文使用Python实现红黑树的插入操作。
先将红黑树的5条特性列出来:
1. 节点是红色或黑色。
2. 根节点是黑色。
3. 所有叶子节点都是黑色的空节点。(叶子节点是NIL节点或NULL节点)
4. 每个红色节点的两个子节点都是黑色节点。(从每个叶子节点到根的所有路径上不能有两个连续的红色节点)
5. 从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点。
一、代码准备
红黑树是一种特殊的二叉搜索树,所以先写好二叉搜索树的代码,这部分不详细介绍,后面直接使用。
# coding=utf-8
class RBNode(object):"""节点类"""def __init__(self, data, left_child=None, right_child=None, color='red'):self.data = dataself.parent = Noneself.left_child = left_childself.right_child = right_childself.color = colorclass RBBinaryTree(object):"""红黑树类"""def __init__(self):self.__root = Noneself.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@propertydef root(self):return self.__root@root.setterdef root(self, value):self.__root = value if isinstance(value, RBNode) else RBNode(value)def insert(self, root, value):"""二叉搜索树插入节点-递归"""node = value if isinstance(value, RBNode) else RBNode(value)if self.is_empty():self.root = nodereturnif root is None:root = nodeelif node.data < root.data:root.left_child = self.insert(root.left_child, value)root.left_child.parent = rootelif node.data > root.data:root.right_child = self.insert(root.right_child, value)root.right_child.parent = rootreturn rootdef search(self, root, data):"""二叉搜索树的查询操作"""if root is None:returnif root.data == data:return rootelif data < root.data:return self.search(root.left_child, data)elif data > root.data:return self.search(root.right_child, data)def show_tree(self):if self.is_empty():print('空二叉树')returnprint('-' * 20)print("\033[31m{}\033[0m".format(str(self.root.data))) if self.root.color is 'red' else print(str(self.root.data))self.__print_tree(self.__root)print('-' * 20)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).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:if node.right_child.color is 'red':print(prefix + self.prefix_branch + self.prefix_right + "\033[31m{}\033[0m".format(str(node.right_child.data)))else: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:if node.left_child.color is 'red':print(prefix + self.prefix_leaf + self.prefix_left + "\033[31m{}\033[0m".format(str(node.left_child.data)))else: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
1. 定义了一个节点类 RBNode ,用于创建新节点,添加到红黑树中,节点中定义了节点的颜色属性 color 。
color 默认为 red,即默认插入的节点为红节点,这样可以降低破坏红黑树特性的可能性。不管新节点是什么颜色,特性3都不可能被破坏,特性1、2、4都有可能被破坏。如果插入的节点是黑色,则一定会破坏特性5,需要进行调整,如果插入的节点是红色,则一定不会破坏特性5。
2. 定义了红黑树类 RBBinaryTree ,类中实现了按树形结构打印红黑树的方法 show_tree(),并且根据红黑树的节点颜色,打印值时打印对应的颜色。还有二叉搜索树的插入方法 insert(root, value) 和搜索方法 search(root, data) 。
二、实现红黑树的旋转方法
红黑树的旋转分为左旋和右旋。
1. 红黑树的左旋
左旋:以某个节点作为支点(旋转节点),其右子节点变为旋转节点的父节点,右子节点的左子节点变为旋转节点的右子节点,旋转节点的左子节点保持不变。右子节点的左子节点相当于从右子节点上“断开”,重新连接到旋转节点上。
def left_rotate(self, node):"""红黑树左旋"""parent_node, right_node = node.parent, node.right_childif not right_node:return# 1.node是旋转节点,将旋转节点的右子节点的左子节点变为旋转节点的右子节点node.right_child = right_node.left_childif node.right_child:node.right_child.parent = node# 2.将旋转节点修改为右子节点的左子节点right_node.left_child, node.parent = node, right_node# 3.将右子节点替换旋转节点的位置,作为旋转节点父节点的子节点if not parent_node:self.root = right_nodeelse:if parent_node.left_child == node:parent_node.left_child = right_nodeelse:parent_node.right_child = right_noderight_node.parent = parent_node
left_rotate(node): 以node为旋转节点对红黑树进行左旋操作。
左旋的代码分三步实现:
1. 将旋转节点的右子节点的左子节点变为旋转节点的右子节点。
2. 将旋转节点变为右子节点的左子节点。
3. 将右子节点替换旋转节点的位置,作为旋转节点父节点的子节点。
现在先用二叉搜索树的插入方法生成一棵二叉搜索树。
if __name__ == '__main__':tree = RBBinaryTree()data = [50, 77, 55, 29, 10, 30, 66, 18, 80, 51, 90]for i in data:tree.insert(tree.root, i)tree.show_tree()
运行结果:
插入数据后的二叉搜索树结构如下图,因为节点默认都是红色的,所以现在节点全是红节点。这里只是为了展示左旋功能,后面实现红黑树的插入方法后,就可以生成正常的红黑树了。(本文中了为了简洁,结构图中忽略了NIL或NULL节点)
如以节点77作为旋转节点,对这棵二叉搜索树进行左旋。
node = tree.search(tree.root, 77)tree.left_rotate(node)tree.show_tree()
运行结果:
左旋后的二叉搜索树结构如下图:
2. 红黑树的右旋
右旋:以某个节点作为支点(旋转节点),其左子节点变为旋转节点的父节点,左子节点的右子节点变为旋转节点的左子节点,旋转节点的右子节点保持不变。左子节点的右子节点相当于从左子节点上“断开”,重新连接到旋转节点上。
def right_rotate(self, node):"""红黑树右旋"""parent_node, left_node = node.parent, node.left_childif not left_node:return# 1.node是旋转节点,将旋转节点的左子节点的右子节点变为旋转节点的左子节点node.left_child = left_node.right_childif node.left_child:node.left_child.parent = node# 2.将旋转节点修改为左子节点的右子节点left_node.right_child, node.parent = node, left_node# 3.将左子节点替换旋转节点的位置,作为旋转节点父节点的子节点if not parent_node:self.root = left_nodeelse:if parent_node.left_child == node:parent_node.left_child = left_nodeelse:parent_node.right_child = left_nodeleft_node.parent = parent_node
right_rotate(node): 以node为旋转节点对红黑树进行右旋操作。
右旋的代码分三步实现:
1. 将旋转节点的左子节点的右子节点变为旋转节点的左子节点。
2. 将旋转节点变为左子节点的右子节点。
3. 将左子节点替换旋转节点的位置,作为旋转节点父节点的子节点。
以节点80作为旋转节点,对上一步左旋后的二叉搜索树进行右旋。左旋和右旋是互逆的,右旋后二叉搜索树又回到了最初的结构。
node = tree.search(tree.root, 80)tree.right_rotate(node)tree.show_tree()
三、实现红黑树的变色方法
变色:将节点的颜色由红变黑或由黑变红。
def change_color(self, node):"""红黑树变色"""if node.color is 'red':node.color = 'black'elif node.color is 'black':node.color = 'red'
change_color(node): 修改节点node的颜色。红变黑,黑变红。
如修改节点10和节点50的颜色。
tree.change_color(tree.search(tree.root, 50))tree.change_color(tree.search(tree.root, 10))tree.show_tree()
运行结果:
变色后的二叉搜索树结构如下图。
四、实现红黑树的插入方法
一棵红黑树,一开始是满足5条特性的,插入新节点后,如果特性被破坏了,就要进行调整,使红黑树重新满足5条特性。
可以将这个过程分解成两个大步骤,第一步是按二叉搜索树将节点插入到对应的位置,这里直接调用已经实现的 insert() 方法即可。第二步是判断是否破坏了红黑树的特性,如果破坏了,就使用旋转和变色来对红黑树进行调整。
为了方便理解,先申明几个需要使用到的术语:
因素节点:因为这个节点的变化,使红黑树的结构发生了变化,用F(factor_node)表示。
父节点:因素节点的父节点,用P(parent_node)表示。
祖父节点:因素节点的父节点的父节点,用G(grandparent_node)表示。
叔节点:因素节点的父节点的兄弟节点,用U(uncle_node)表示。
插入新节点后,是否需要对红黑树进行调整,以及怎么调整,分为如下几种情况:
1. 如果红黑树是一棵空树,则将新节点添加到根节点的位置,并将节点的颜色修改为黑色。
2. 如果新节点的父节点是黑节点,则插入新节点后,不需要做调整。
3. 如果新节点的父节点是红节点(不满足特性4),根据叔节点的颜色,分为两类。
3.1 叔节点为黑色,叔节点为黑色包含了叔节点为空的情况,因为红黑树的空节点(叶子节点)一定是黑色的。
叔节点为黑色时,根据节点的结构关系,可以分为四种情况。
3.1.1 新节点是父节点的左子节点,父节点也是祖父节点的左子节点(左左结构)。将父节点红变黑,祖父节点黑变红,然后以祖父节点作为旋转节点右旋。
这里要注意两点:
(1). 新节点的父节点的另一个子节点一定是叶子节点。因为插入新节点前红黑树是满足5条特性的,假设父节点还有一个非空子节点,如果这个节点红节点,则不满足特性4,如果这个节点是黑节点,则不满足特性5。
(2). 在插入新节点时,如果新节点的父节点是红色,祖父节点是黑色,则叔节点一定不会是非空黑节点,要么是叶子节点要么是红节点。因为插入新节点前红黑树是满足5条特性的,如果叔节点是一个非空黑节点,则红黑树不满足特性5。
在后面的3.2中,叔节点是红节点时,进行第一次调整后,还不一定能调整完成,祖父节点成为新的因素节点,可能会出现因素节点F为红、父节点P为红、祖父节点G为黑、叔节点U为黑的情况。所以这种状态其实是调整过程中产生的中间状态,3.1中先给处理方式,等介绍完叔节点为红节点的情况,就可以连贯到一起了。
3.1.2 新节点是父节点的右子节点,父节点是祖父节点的左子节点(左右结构)。先以父节点作为旋转节点左旋,变成3.1.1的结构,再按3.1.1的方式处理。
3.1.3 新节点是父节点的右子节点,父节点也是祖父节点的右子节点(右右结构)。将父节点红变黑,祖父节点黑变红,然后以祖父节点作为旋转节点左旋。
3.1.4 新节点是父节点的左子节点,父节点是祖父节点的右子节点(右左结构)。先以父节点作为旋转节点右旋,变成3.1.3的结构,再按3.1.3的方式处理。
3.2 叔节点为红色,这种情况将父节点和叔节点红变黑,将祖父节点黑变红。
祖父节点由黑变红后,因为不知道祖父节点的父节点是什么颜色,所以还需要进行判断,将祖父节点作为新的因素节点,递归进入下一次调整,可以分为如下四种情况。
3.2.1 如果祖父节点是根节点(不满足特性1),要将祖父节点重新变成黑色,并且调整结束。
3.2.2 如果其父节点是黑色,则不需再次调整。
3.2.3 如果其父节点是红色,叔节点是黑色,则符合上面3.1的情况,则递归调用3.1处理。
3.2.4 如果其父节点是红色,叔节点也是红色,则符合当前3.2的情况,递归再进行一次3.2处理。如果处理完成后,新的因素节点还符合3.2的情况,则继续递归,直到退出循环。
根据上面的分析,代码实现如下:
def rb_insert(self, value):"""红黑树插入"""node = value if isinstance(value, RBNode) else RBNode(value)if self.search(self.root, node.data):returnif self.is_empty():node.color = 'black'self.root = nodereturnself.insert(self.root, node)factor_node = nodewhile True:parent_node = factor_node.parentif parent_node.color is 'red':grandparent_node = parent_node.parentif parent_node is grandparent_node.left_child:uncle_node = grandparent_node.right_childelse:uncle_node = grandparent_node.left_child# 如果父节点为红节点且叔节点为黑节点if uncle_node is None or uncle_node and uncle_node.color is 'black':if parent_node == grandparent_node.left_child:# 先左旋为左左结果,然后父节点和祖父节点变色,再右旋if factor_node == parent_node.right_child:self.left_rotate(parent_node)self.change_color(factor_node)else:self.change_color(parent_node)self.change_color(grandparent_node)self.right_rotate(grandparent_node)elif parent_node == grandparent_node.right_child:# 先右旋为右右结构,然后父节点和祖父节点变色,再左旋if factor_node == parent_node.left_child:self.right_rotate(parent_node)self.change_color(factor_node)else:self.change_color(parent_node)self.change_color(grandparent_node)self.left_rotate(grandparent_node)break# 如果父节点为红节点且叔节点也为红节点elif uncle_node and uncle_node.color is 'red':# 父节点和叔节点变色,祖父节点变色(祖父节点是根节点除外)self.change_color(parent_node)self.change_color(uncle_node)if grandparent_node != self.root:self.change_color(grandparent_node)# 祖父节点变成红节点后,将祖父节点作为新的因素节点,判断其父节点,避免不满足特性4factor_node = grandparent_nodeelse:break
rb_insert(value): 红黑树的插入操作,分析了插入操作的所有情况及每种情况的处理方式,代码的实现就相对简单了。
还是一开始的数据,使用红黑树的插入方式依次插入。
if __name__ == '__main__':tree = RBBinaryTree()data = [50, 77, 55, 29, 10, 30, 66, 18, 80, 51, 90]for i in data:# tree.insert(tree.root, i)tree.rb_insert(i)tree.show_tree()
运行结果如下:
得到的红黑树结构如下图:
由于插入操作分的情况比较多,所以在看插入操作的分析时,一定要先理解旋转和变色操作。
实现红黑树的代码后,可以看出,每插入一个新节点,红黑树都是满足5条特性的,而有一些红黑树不一定是一个节点一个节点地添加得到的。
五、完整代码
# coding=utf-8
class RBNode(object):"""节点类"""def __init__(self, data, left_child=None, right_child=None, color='red'):self.data = dataself.parent = Noneself.left_child = left_childself.right_child = right_childself.color = colorclass RBBinaryTree(object):"""红黑树类"""def __init__(self):self.__root = Noneself.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@propertydef root(self):return self.__root@root.setterdef root(self, value):self.__root = value if isinstance(value, RBNode) else RBNode(value)def left_rotate(self, node):"""红黑树左旋"""parent_node, right_node = node.parent, node.right_childif not right_node:return# 1.node是旋转节点,将旋转节点的右子节点的左子节点变为旋转节点的右子节点node.right_child = right_node.left_childif node.right_child:node.right_child.parent = node# 2.将旋转节点修改为右子节点的左子节点right_node.left_child, node.parent = node, right_node# 3.将右子节点替换旋转节点的位置,作为旋转节点父节点的子节点if not parent_node:self.root = right_nodeelse:if parent_node.left_child == node:parent_node.left_child = right_nodeelse:parent_node.right_child = right_noderight_node.parent = parent_nodedef right_rotate(self, node):"""红黑树右旋"""parent_node, left_node = node.parent, node.left_childif not left_node:return# 1.node是旋转节点,将旋转节点的左子节点的右子节点变为旋转节点的左子节点node.left_child = left_node.right_childif node.left_child:node.left_child.parent = node# 2.将旋转节点修改为左子节点的右子节点left_node.right_child, node.parent = node, left_node# 3.将左子节点替换旋转节点的位置,作为旋转节点父节点的子节点if not parent_node:self.root = left_nodeelse:if parent_node.left_child == node:parent_node.left_child = left_nodeelse:parent_node.right_child = left_nodeleft_node.parent = parent_nodedef change_color(self, node):"""红黑树变色"""if node.color is 'red':node.color = 'black'elif node.color is 'black':node.color = 'red'def rb_insert(self, value):"""红黑树插入"""node = value if isinstance(value, RBNode) else RBNode(value)if self.search(self.root, node.data):returnif self.is_empty():node.color = 'black'self.root = nodereturnself.insert(self.root, node)factor_node = nodewhile True:parent_node = factor_node.parentif parent_node.color is 'red':grandparent_node = parent_node.parentif parent_node is grandparent_node.left_child:uncle_node = grandparent_node.right_childelse:uncle_node = grandparent_node.left_child# 如果父节点为红节点且叔节点为黑节点if uncle_node is None or uncle_node and uncle_node.color is 'black':if parent_node == grandparent_node.left_child:# 先左旋为左左结果,然后父节点和祖父节点变色,再右旋if factor_node == parent_node.right_child:self.left_rotate(parent_node)self.change_color(factor_node)else:self.change_color(parent_node)self.change_color(grandparent_node)self.right_rotate(grandparent_node)elif parent_node == grandparent_node.right_child:# 先右旋为右右结构,然后父节点和祖父节点变色,再左旋if factor_node == parent_node.left_child:self.right_rotate(parent_node)self.change_color(factor_node)else:self.change_color(parent_node)self.change_color(grandparent_node)self.left_rotate(grandparent_node)break# 如果父节点为红节点且叔节点也为红节点elif uncle_node and uncle_node.color is 'red':# 父节点和叔节点变色,祖父节点变色(祖父节点是根节点除外)self.change_color(parent_node)self.change_color(uncle_node)if grandparent_node != self.root:self.change_color(grandparent_node)# 祖父节点变成红节点后,将祖父节点作为新的因素节点,判断其父节点,避免不满足特性4factor_node = grandparent_nodeelse:breakdef insert(self, root, value):"""二叉搜索树插入节点-递归"""node = value if isinstance(value, RBNode) else RBNode(value)if self.is_empty():self.root = nodereturnif root is None:root = nodeelif node.data < root.data:root.left_child = self.insert(root.left_child, value)root.left_child.parent = rootelif node.data > root.data:root.right_child = self.insert(root.right_child, value)root.right_child.parent = rootreturn rootdef search(self, root, data):"""二叉搜索树的查询操作"""if root is None:returnif root.data == data:return rootelif data < root.data:return self.search(root.left_child, data)elif data > root.data:return self.search(root.right_child, data)def show_tree(self):if self.is_empty():print('空二叉树')returnprint('-' * 20)print("\033[31m{}\033[0m".format(str(self.root.data))) if self.root.color is 'red' else print(str(self.root.data))self.__print_tree(self.__root)print('-' * 20)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).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:if node.right_child.color is 'red':print(prefix + self.prefix_branch + self.prefix_right + "\033[31m{}\033[0m".format(str(node.right_child.data)))else: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:if node.left_child.color is 'red':print(prefix + self.prefix_leaf + self.prefix_left + "\033[31m{}\033[0m".format(str(node.left_child.data)))else: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 Noneif __name__ == '__main__':tree = RBBinaryTree()data = [50, 77, 55, 29, 10, 30, 66, 18, 80, 51, 90]for i in data:# tree.insert(tree.root, i)tree.rb_insert(i)tree.show_tree()# node = tree.search(tree.root, 77)# tree.left_rotate(node)# tree.show_tree()# node = tree.search(tree.root, 80)# tree.right_rotate(node)# tree.show_tree()# tree.change_color(tree.search(tree.root, 50))# tree.change_color(tree.search(tree.root, 10))# tree.show_tree()
Python实现红黑树的插入操作相关推荐
- Python实现红黑树的删除操作
Python实现红黑树的删除操作 本专栏的上一篇文章使用Python实现了红黑树的插入操作.参考:https://blog.csdn.net/weixin_43790276/article/detai ...
- 数据结构-----红黑树的插入操作
红黑树是一棵二叉搜索树:树种每一个节点的颜色不是黑色就是红色.本篇中只实现用节点的颜色来描述红黑树,性质如下: RB1:根节点和所有外部节点都是黑色: RB2:在根至外部节点路径上,没有连续两个节点是 ...
- 红黑树的删除_Python实现红黑树的删除操作
上一篇文章使用Python实现了红黑树的插入操作.参考:Python实现红黑树的插入操作本篇文章使用Python实现红黑树的删除操作.先将红黑树的5条特性列出来:1. 节点是红色或黑色.2. 根节点是 ...
- 彻底理解面试难点之rb-tree(红黑树)续--对红黑树的插入和删除操作的一些理解!!!
这里主要讲一下对红黑树的插入和删除操作的一些理解 对于红黑树的一些相关性质的介绍,上篇已经讲了,这里不再介绍,有需要了解的,可以翻前面的博客看看. 1.红黑树的插入操作 对于红黑树的元素插入,我们首先 ...
- 红黑树检索/插入/删除
正文 红黑树也是二叉查找树,我们知道,二叉查找树这一数据结构并不难,而红黑树之所以难是难在它是自平衡的二叉查找树,在进行插入和删除等可能会破坏树的平衡的操作时,需要重新自处理达到平衡状态.现在在脑海想 ...
- 红黑树及其插入、删除操作
在二叉搜索树中,基本操作如结点的插入.删除.查找的性能上界都得不到保证,原因在于二叉搜索树的构造依赖于其结点值的插入顺序,最坏情况下二叉搜索树会退化为单链表(如下图所示).因此我们需要对二叉搜索树做出 ...
- Python实现红黑树
红黑树是一颗二叉搜索树,他在每个节点上增加了一个存储位来表示节点的颜色,可以是RED或者是BLACK,树中的每个节点包括5个属性:color.key.left.right.parent,如果一个节点没 ...
- 红黑树详解(二)红黑树的插入(附动图和案例)
红黑树详解(二)红黑树的插入(附动图和案例) 摘要: 在很多源码涉及到大量数据处理的时候,通常都是用红黑树这一数据结构.红黑树是一种自平衡的二叉查找树,它能在进行插入和删除操作时通过特定操作保持二叉查 ...
- 红黑树的插入与验证——附图详解
文章目录 红黑树 性质 红黑树的插入 前言 寻找插入位置 情况 1.0 情况 1.1 情况 1.2 情况 1.3 情况 2.0 情况 2.1 情况 2.2 情况 2.3 完整代码 红黑树的检验 验证代 ...
最新文章
- linux实践-弱密码导致服务器被黑
- 基于ARP的网络扫描工具netdiscover常用命令集合大学霸IT达人
- python读取文件多行内容-使用python读取.text文件特定行的数据方法
- 解决Android Studio内代码乱码
- 串口协议的制定以及串口中怎样接收一个完整数据包的解析
- Java基础--成员变量和局部变量(区别、重名问题)
- VS2008的C++TR1库已经支持正则表达式
- 重磅!华为方舟编译器招募 2000 程序员!
- 长度短点的uuid_UUID不失精度,长度改进
- php 设置页面最大执行时间 set_time_limit max_execution_time
- 2018最新老男孩Linux架构师实战课程14期视频
- 点击谷歌浏览器安装包没有反应
- Linux 开发环境搭建与使用——SlickEdit 的安装与配置
- 脉冲计数器单片机c语言编程,基于单片机的光电计数器
- 建立企业统一即时通讯平台
- Elasticsearch:理解 Elasticsearch 中的 Percolator 数据类型及 Percolate 查询
- 桌面文件夹不见了怎么恢复?4招教你找回消失的文件夹
- crontab指定时间
- C++ OpenCV特征提取之KAZE和AKAZE的匹配
- JZOJ 3158 【JSOI2013】丢番图
热门文章
- 阿里云Freeswtich部署
- Myeclipse8.5 反编译插件 jad 安装(转)
- aix Mysql-Rpm puppet puppetAgent
- extjs 中登录保存用户名
- 面试官系统精讲Java源码及大厂真题 - 22 ArrayBlockingQueue 源码解析
- GitHub开源项目 - Jeecg-Boot开始开发平台介绍
- C语言,利用函数调用统计输出素数并统计素数和
- ASP.NET操作Excel
- java 多线程同步 通过实现Runnable的示例
- Python: PyCharm中导入matplotlib时报错:“Backend Qt5Agg is interactive backend”的解决方案...