红黑树数据结构剖析

红黑树数据结构剖析

 

红黑树是计算机科学内比较常用的一种数据结构,它使得对数据的搜索,插入和删除操作都能保持在O(lgn)的时间复杂度。然而,相比于一般的数据结构,红黑树的实现的难度有所增加。网络上关于红黑树的实现资料汗牛充栋,但是乏于系统介绍红黑树实现的资料。本文通过一个自己实现的红黑树数据结构以及必要的搜索,插入和删除操作算法,为大家更系统地剖析红黑树数据结构的实现。

对于大部分数据结构,一般都会使用抽象数据类型的方式实现,C++提供的模板机制可以做到数据结构与具体数据类型无关,就像STL实现的那样。不过本文并非去实现STL中的红黑树,更重要的是透过红黑树的实现学习相关的算法和思想。当然,我们还是会借鉴STL中关于红黑树实现部分有价值内容。

一、基本概念

在具体实现红黑树之前,必须弄清它的基本含义。红黑树本质上是一颗二叉搜索树,它满足二叉搜索树的基本性质——即树中的任何节点的值大于它的左子节点,且小于它的右子节点。

1 二叉搜索树

按照二叉搜索树组织数据,使得对元素的查找非常快捷。比如图1中的二叉搜索树,如果查询值为48的节点,只需要遍历4个节点即可完成。理论上,一颗平衡的二叉搜索树的任意节点平均查找效率为树的高度h,即O(lgn)。但是如果二叉搜索树的失去平衡(元素全在一侧),搜索效率就退化为O(n),因此二叉搜索树的平衡是搜索效率的关键所在。为了维护树的平衡性,数据结构内出现了各种各样的树,比如AVL树通过维持任何节点的左右子树的高度差不大于1保持树的平衡,而红黑树使用颜色的概念维持树的平衡,使二叉搜索树的左右子树的高度差保持在固定的范围。相比于其他二叉搜索树树,红黑树对二叉搜索树的平衡性维持有着自身的优势。

顾名思义,红黑树的节点是有颜色概念的,即非红即黑。通过颜色的约束,红黑树维持着二叉搜索树的平衡性。一颗红黑树必须满足以下几点条件:

规则1、根节点必须是黑色。

规则2、任意从根到叶子的路径不包含连续的红色节点。

规则3、任意从根到叶子的路径的黑色节点总数相同。

如图2所示,为一颗合法的红黑树,可以发现红黑树在维持二叉搜索树的基本性质的前提下,并满足了红黑树的颜色条件,整体上保持了二叉搜索树的平衡性。(构造如下红黑树的数据序列为:(503578275690454048),读者可以自行验证。)

2 红黑树

二、数据结构设计

和一般的数据结构设计类似,我们用抽象数据类型表示红黑树的节点,使用指针保存节点之间的相互关系。

作为红黑树节点,其基本属性有:节点的颜色、左子节点指针、右子节点指针、父节点指针、节点的值。

3 红黑树节点基本属性

为了方便红黑树关键算法的实现,还定义了一些简单的操作(都是内联函数)。

//红黑树节点
template<class T>
class rb_tree_node
{
    typedef rb_tree_node_color node_color;
    typedef rb_tree_node<T> node_type;
public:
    node_color color;//颜色
    node_type*parent;//父节点
    node_type*left;//左子节点
    node_type*right;//右子节点
    T value;//
    rb_tree_node(T&v);//构造函数
    inline node_type*brother();//获取兄弟节点
    inline bool on_left();//自身是左子节点
    inline bool on_right();//自身是右子节点
    inline void set_left(node_type*node);//设置左子节点
    inline void set_right(node_type*node);//设置左子节点
};

为了表示红黑树节点的颜色,我们定义一个简单的枚举类型。

//红黑树节点颜色
enum rb_tree_node_color
{
    red=false,
    black=true
};

有了节点,剩下的就是实现红黑树的构造、插入、搜索、删除等关键算法了。

 

//红黑树
template<class T>
class rb_tree
{
public:
    typedef rb_tree_node<T> node_type;
    rb_tree();
    ~rb_tree();
    void clear();
    void insert(T v);//添加节点
    bool insert_unique(T v);//添加唯一节点
    node_type* find(T v);//查询节点
    bool  remove(T v);//删除节点
    inline node_type* maximum();//最大值
    inline node_type* minimum();//最小值
    inline node_type* next(node_type*node);//下一个节点
    inline node_type* prev(node_type*node);//上一个节点
    void print();//输出
    int height();//高度
    unsigned count();//节点数
    bool validate();//验证
    unsigned get_rotate_times();//获取旋转次数
private:
    node_type*root;//树根
    unsigned rotate_times;//旋转的次数
    unsigned node_count;//节点数
    void __clear(node_type*sub_root);//清除函数
    void __insert(node_type*&sub_root,node_type*parent,node_type*node);//内部节点插入函数
    node_type* __find(node_type*sub_root,T v);//查询
    inline node_type* __maximum(node_type*sub_root);//最大值
    inline node_type* __minimum(node_type*sub_root);//最小值
    void __rebalance(node_type*node);//新插入节点调整平衡
    void __fix(node_type*node,node_type*parent,bool direct);//删除节点调整平衡
    void __rotate(node_type*node);//自动判断类型旋转
    void __rotate_left(node_type*node);//左旋转    
    void __rotate_right(node_type*node);//右旋转
    void __print(node_type*sub_root);//输出
    int  __height(node_type*&sub_root);//高度
    bool __validate(node_type*&sub_root,int& count);//验证红黑树的合法性
};

在红黑树类中,定义了树根(root)和节点数(count),其中还记录红黑树在插入删除操作时执行的旋转次数rotate_times。其中核心操作有插入操作(insert),搜索操作(find),删除操作(remove),递减操作(prev)——寻找比当前节点较小的节点,递增操作(next)——寻找比当前节点较大的节点,最大值(maximum)和最小值(minimum)操作等。其中验证操作(__ validate)通过递归操作红黑树,验证红黑树的三个基本颜色约束,用于操纵红黑树后验证红黑树是否保持平衡。

由于插入和删除操作是红黑树的关键所在,下边重点介绍这两个操作。其他的操作一般通过对树进行递归操作都可以轻松的完成,这里不再赘述。

三、红黑树的插入操作

红黑树的插入操作和查询操作有些类似,它按照二分搜索的方式递归寻找插入点。不过这里需要考虑边界条件——当树为空时需要特殊处理(这里未采用STL对树根节点实现的特殊技巧)。如果插入第一个节点,我们直接用树根记录这个节点,并设置为黑色,否则作递归查找插入(__insert操作)。

默认插入的节点颜色都是红色,因为插入黑色节点会破坏根路径上的黑色节点总数,但即使如此,也会出现连续红色节点的情况。因此在一般的插入操作之后,出现红黑树约束条件不满足的情况(称为失去平衡)时,就必须要根据当前的红黑树的情况做相应的调整(__rebalance操作)。和AVL树的平衡调整通过旋转操作的实现类似,红黑树的调整操作一般都是通过旋转结合节点的变色操作来完成的。

红黑树插入节点操作产生的不平衡来源于当前插入点和父节点的颜色冲突导致的(都是红色,违反规则2)。

4 插入冲突

如图4所示,由于节点插入之前红黑树是平衡的,因此可以断定祖父节点g必存在(规则1:根节点必须是黑色),且是黑色(规则2:不会有连续的红色节点),而叔父节点u颜色不确定,因此可以把问题分为两大类:

1、叔父节点是黑色(若是空节点则默认为黑色)

这种情况下通过旋转和变色操作可以使红黑树恢复平衡。但是考虑当前节点n和父节点p的位置又分为四种情况:

Anp左子节点,pg的左子节点。

Bnp右子节点,pg的右子节点。

Cnp左子节点,pg的右子节点。

Dnp右子节点,pg的左子节点。

情况AB统一称为外侧插入,CD统一称为内侧插入。之所以这样分类是因为同类的插入方式的解决方式是对称的,可以通过镜像的方法相似完成。

首先考虑情况Anp左子节点,pg的左子节点。针对该情况可以通过一次右旋转操作,并将p设为黑色,g设为红色完成重新平衡。

5 左外侧插入调整

右旋操作的步骤是:将p挂接在g节点原来的位置(如果g原是根节点,需要考虑边界条件),将p的右子树x挂到g的左子节点,再把g挂在p的右子节点上,完成右旋操作。这里将最终旋转结果的子树的根节点作为旋转轴(p节点),也就是说旋转轴在旋转结束后称为新子树的根节点!这里需要强调一下和STL的旋转操作的区别,STL的右旋操作的旋转轴视为旋转之前的子树根节点(g节点),不过这并不影响旋转操作的效果。

类比之下,情况B则需要使用左单旋操作来解决平衡问题,方法和情况A类似。

6 右外侧插入

接下来,考虑情况Cnp左子节点,pg的右子节点。针对该情况通过一次左旋,一次右旋操作(旋转轴都是n,注意不是p),并将n设为黑色,g设为红色完成重新平衡。

7 左内侧插入

需要注意的是,由于此时新插入的节点是n,它的左右子树xy都是空节点,但即使如此,旋转操作的结果需要将xy新的位置设置正确(如果不把pg的对应分支设置为空节点的话,就会破坏树的结构)。在之后的其他操作中,待旋转的节点n的左右子树可能就不是空节点了。

类比之下,情况D则需要使用一次右单旋,一次左单旋操作来解决平衡问题,方法和情况C类似。

8 右内侧插入

2、叔父节点是红色

当叔父节点是红色时,则不能直接通过上述方式处理了(把前边的所有情况的u节点看作红色,会发现节点ug是红色冲突的)。但是我们可以交换gpu节点的颜色完成当前冲突的解决。

9 叔父节点为红的插入

但是仅仅这样做颜色交换是不够的,因为祖父节点g的父节点(记作gp)如果也是红色的话仍然会有冲突(ggp是连续的红色,违反规则2)。为了解决这样的冲突,我们需要从当前插入点n向根节点root回溯两次。

第一次回溯时处理所有拥有两个红色节点的节点,并按照图9中的方式交换父节点g与子节点pu的颜色,并暂时忽略gpp的颜色冲突。如果根节点的两个子节点也是这种情况,则在颜色交换完毕后重新将根节点设置为黑色。

第二次回溯专门处理连续的红色节点冲突。由于经过第一遍的处理,在新插入点n的路径上一定不存在同为红色的兄弟节点了。而仍出现gpp的红色冲突时,gp的兄弟节点(gu)可以断定为黑色,这样就回归前边讨论的叔父节点为黑色时的情况处理。

10 消除连续红色节点

由于发生冲突的两个红色节点位置可能是任意的,因此会出现上述的四种旋转情况。不过我们把靠近叶子的红色节点(g)看作新插入的节点,这样面对AB情况则把p的父节点gp作为旋转轴,旋转后gp会是新子树的根,而面对CD情况时把p作为旋转轴即可,旋转后p为新子树的根(因此可以把四种旋转方式封装起来)。

在第二次回溯时,虽然每次遇到红色冲突旋转后都会提升ggp节点的位置(与根节点的距离减少),但是无论ggp谁是新子树的根都不会影响新插入节点n到根节点root路径的回溯,而且一旦新子树的根到达根节点(parent指针为空)就可以停止回溯了。

通过以上的树重新平衡策略可以完美地解决红黑树插入节点的平衡问题。

四、红黑树的删除操作

相比于插入操作,红黑树的删除操作显得更加复杂。很多资料都没有将红黑树的删除解释清楚,清华的数据结构教材对红黑树删除的描述也十分混乱,《STL源码剖析》中侯sir对红黑树的删除更是闭口不谈。这里参考了STL对红黑树删除操作的实现方式,并做了适当的修改(红黑树使用哨兵节点表示空节点,而这里使用空指针的方式,因此要杜绝空指针的引用问题)。

由于红黑树就是二叉搜索树,因此节点的删除方式和二叉搜索树相同。不过红黑树删除操作的难点不在于节点的删除,而在于删除节点后的调整操作。因此红黑树的删除操作分为两步,首先确定被删除节点的位置,然后调整红黑树的平衡性。

先考虑删除节点的位置,如果待删除节点拥有唯一子节点或没有子节点,则将该节点删除,并将其子节点(或空节点)代替自身的位置。如果待删除节点有两个子节点,则不能将该节点直接删除。而是从其右子树中选取最小值节点(或左子树的最大值节点)作为删除节点(该节点一定没有两个子节点了,否则还能取更小的值)。当然在删除被选取的节点之前,需要将被选取的节点的数据拷贝到原本需要删除的节点中。选定删除节点位置的情况如图11所示,这和二叉搜索树的节点删除完全相同。

11 删除点的选定

11中用红色标记的节点表示被选定的真正删除的节点(节点y)。其中绿色节点(yold)表示原本需要删除的节点,而由于它有两个子节点,因此删除y代替它,并且删除y之前需要将y的值拷贝到yold,注意这里如果是红黑树也不会改变yold的颜色!通过上述的方式,将所有的节点删除问题简化为独立后继(或者无后继)的节点删除问题。然后再考虑删除y后的红黑树平衡调整问题。由于删除y节点后,y的后继节点n会作为y的父节点p的孩子。因此在进行红黑树平衡调整时,np的子节点。

下边考虑平衡性调整问题,首先考虑被删除节点y的颜色。如果y为红色,删除y后不会影响红黑树的平衡性,因此不需要做任何调整。如果y为黑色,则y所在的路径上的黑色节点总数减少1,红黑树失去平衡,需要调整。

y为黑色时,再考虑节点n的颜色。如果n为红色,因为ny的唯一后继,如果把n的颜色设置为黑色,那么就能恢复y之前所在路径的黑色节点的总数,调整完成。如果n也是黑色,则需要按照以下四个步骤来考虑。

pn的父节点,wn节点的兄弟节点。假定np的左子节点,np的右子节点情况可以镜像对称考虑。

步骤1:若w为红色,则断定w的子节点(如果存在的话或者为空节点)和节点p必是黑色(规则2)。此时将wp的颜色交换,并以w为旋转轴进行左旋转操作,最后将w设定为n的新兄弟节点(原来w的左子树x)。

通过这样的转换,将原本红色的w节点情况转换为黑色w节点情况。若w原本就是黑色(或者空节点),则直接进入步骤2

12 节点删除情况1

步骤2:无论步骤1是否得到处理,步骤2处理的总是黑色的w节点,此时再考虑w的两个子节点xy的颜色情况。如果xy都是黑色节点(或者是空节点,如果父节点w为空节点,认为xy也都是空节点),此时将w的颜色设置为红色,并将n设定为n的父节点p。此时,如果n为红色,则直接设定n为黑色,调整结束。否则再次回到步骤1做相似的处理。注意节点n发生变化后需要重新设定节点wp

考虑由于之前黑色节点删除导致n的路径上黑色节点数减1,因此可以把节点n看作拥有双重黑色的节点。通过此步骤将n节点上移,使得n与根节点距离减少,更极端的情况是当n成为根节点时,树就能恢复平衡了(因为根节点不在乎多一重黑色)。另外,在n的上移过程中可能通过后续的转换已经让树恢复平衡了。

13 节点删除情况2

步骤3:如果步骤2中的w的子节点不是全黑色,而是左红(x红)右黑(y黑)的话,将x设置为黑色,w设置为红色,并以节点x为旋转轴右旋转,最后将w设定为n的新兄弟(原来的x节点)。

通过这样的转换,让原本w子节点左红右黑的情况转化为左黑右红的情况。若w的右子节点原本就是红色(左子节点颜色可黑可红),则直接进入步骤4

14 节点删除情况3

步骤4:该步骤处理w右子节点y为红色的情况,此时w的左子节点x可黑可红。这时将w的右子节点y设置为黑色,并交换w与父节点p的颜色(w原为黑色,p颜色可黑可红),再以w为旋转轴左旋转,红黑树调整算法结束。

通过该步骤的转换,可以彻底解决红黑树的平衡问题!该步骤的实质是利用左旋恢复节点n上的黑色节点总数,虽然pw虽然交换了颜色,但它们都是n的祖先,因此n路径上的黑色节点数增加1。同时由于左旋,使得y路径上的黑色节点数减1,恰巧的是y的颜色为红,将y设置为黑便能恢复y节点路径上黑色节点的总数。

15 节点删除情况4

总结以上步骤,对红黑树节点删除的平衡性调整归纳为如下流程。

16 节点删除调整流程

通过上述的调整策略,可以完美解决红黑树节点删除时平衡性问题。

五、随机测试

对数据结构准确性的测试主要考察以下操作:插入,删除,查询,遍历和验证。插入和删除操作前边做了充分的介绍,由insetremove实现,查询操作在插入和删除操作时会间接调用,由find实现,遍历操作分为正序(由minimumnext实现)和逆序遍历(由maximimprev实现),验证操作主要是验证插入和删除后红黑树的合法性(规则123),由validate实现。至于其他和红黑树统计特性相关的操作,比如获取树高、节点数和累计的旋转次数等可以很容易实现。

我们使用随机数产生器随机产生一批数据插入到红黑树内,然后再随机产生一批数据作为删除操作的参数。其中每次插入和删除时都会对树的合法性进行验证,并且在插入后删除数据结束后以正序和逆序的方式输出红黑树的节点以及其他统计信息。测试代码如下:

 

#include"rb_tree.h"
#include <time.h> 
#include <windows.h>

int main()
{
    srand((unsigned)GetCurrentTime());
    int times=10,len=30;
    while(times--)
    {
        rb_tree<int> tree;
        for(int i=0;i<len;i++)
        {
            int num=rand()%len;
            tree.insert_unique(num);
            if(!tree.validate())cout<<"插入时失去平衡"<<endl;
        }
        cout<<"正序:";
        for(rb_tree<int>::node_type*node=tree.minimum();node;node=tree.next(node))
        {
            cout<<node->value<<" ";
        }
        cout<<"\n旋转次数-黑高-节点数:"<<tree.get_rotate_times()
            <<" "<<tree.height()<<" "<<tree.count()<<endl;
        cout<<"删除:";
        for(int i=0;i<len;i++)
        {
            int num=rand()%len;
            if(tree.remove(num))cout<<num<<" ";
            if(!tree.validate())cout<<"删除时失去平衡"<<endl;
        }
        cout<<endl;
        cout<<"逆序:";
        for(rb_tree<int>::node_type*node=tree.maximum();node;node=tree.prev(node))
        {
            cout<<node->value<<" ";
        }
        cout<<"\n旋转次数-黑高-节点数:"<<tree.get_rotate_times()
            <<" "<<tree.height()<<" "<<tree.count()<<endl;
        cout<<"________________________________________________________________________________"<<endl;
    }
    return 0;
}

经过大量的循环随机测试,可以验证红黑树数据结构的稳定性以及平衡性调整算法的正确性,下边是测试结果的部分截图。

本文构造的红黑树数据结构源代码下载地址为:https://github.com/fanzhidongyzby/RBTree

读者感兴趣的话可以下载验证。

17 测试结果

综上所述,我们对红黑树数据结构有了更充分地了解,尤其是复杂的红黑树的插入删除平衡性调整算法,最后进行的测试验证了红黑树的核心算法的正确性。通过对红黑树数据结构的详尽剖析,相信大家对数据结构在计算机学科的重要性有了更充分地认识,希望本文对你有所帮助。

转载于:https://www.cnblogs.com/fanzhidongyzby/p/3187912.html

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

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

相关文章

python 多分类情感_python 文本情感分类

对于一个简单的文本情感分类来说&#xff0c;其实就是一个二分类&#xff0c;这篇博客主要讲述的是使用scikit-learn来做文本情感分类。分类主要分为两步&#xff1a;1)训练&#xff0c;主要根据训练集来学习分类模型的规则。2)分类&#xff0c;先用已知的测试集评估分类的准确…

.NET GC 实时监控工具 dotnet gcmon 介绍

今天介绍一个新的诊断工具 dotnet-gcmon, 也是全局 .NET CLI 工具, 它可以监控到 .NET 程序的 GC, 能获取到的信息也很详细, 另外 maoni 大佬也是其中的开发者之一。安装 gcmon和其他的 dotnet 诊断工具一样, 你可以使用以下命令&#xff0c;进行全局安装dotnet tool install -…

js封装map

js封装map 在大三的时候&#xff0c;做电子商务网站的时候&#xff0c;前端页面打包过来的数据都是json格式&#xff0c;为了更好的体验&#xff0c;有的时候我们需要封装url,需要我点击回退的时候&#xff0c;url地址栏目不变&#xff0c;其实我们在Android或者java里面通常也…

NYOJ-45 棋盘覆盖

棋盘覆盖 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述在一个2k2k&#xff08;1<k<100&#xff09;的棋盘中恰有一方格被覆盖&#xff0c;如图1&#xff08;k2时&#xff09;&#xff0c;现用一缺角的22方格&#xff08;图2为其中…

你绝对干过的15件傻事儿

全世界只有3.14 % 的人关注了爆炸吧知识首先来看你绝对干过的15件傻事儿&#xff0c;别不承认&#xff01;把树叶弄成这样喝酸奶舔盖子吃完棒冰继续含着棍子咬拉链尝试用笔写一首歌比如《生日快乐》对着电风扇说话或喊叫刮墙壁上的油漆过斑马线只踩白色部分猫打哈欠时伸手指进去…

Python logging模块详解

1.简单的将日志打印到屏幕 import logginglogging.debug(This is debug message) logging.info(This is info message) logging.warning(This is warning message)屏幕上打印: WARNING:root:This is warning message默认情况下&#xff0c;logging将日志打印到屏幕&#xff0c;…

java什么时候可能产生内存溢出_哪些场景会产生OOM?怎么解决?

Java技术栈www.javastack.cn关注阅读更多优质文章这个面试题是一个朋友在面试的时候碰到的&#xff0c;什么时候会抛出OutOfMemery异常呢&#xff1f;初看好像挺简单的&#xff0c;其实深究起来考察的是对整个JVM的了解&#xff0c;而且这个问题从网上可以翻到一些乱七八糟的答…

如何通过 Linq 将集合拆成多个块?

咨询区 BlakeH&#xff1a;请问是否可以用 linq 按序生成带有多个固定 size 的块&#xff1f;我的理想情况下还可以对这些 块 进行操作。回答区 Sergey Berezovskiy&#xff1a;说实话&#xff0c;你不需要写任何代码&#xff0c;使用 MoreLINQ 中的批次方法即可&#xff0c;它…

解决WP7的32位图像渐变色色阶问题

做游戏时发现背景图色阶现象严重&#xff0c;想了想会不会是显卡色深问题&#xff0c;于是加了下面一段代码&#xff0c;结果解决这个问题。 graphics.PreferredBackBufferFormat Microsoft.Xna.Framework.Graphics.SurfaceFormat.Color; 调试时发现PreferredBackBufferFormat…

年仅53岁,因连续工作、过度劳累,这位抗疫幕后的科研专家去世

全世界只有3.14 % 的人关注了爆炸吧知识本文来源&#xff1a;募格学术综合整理新华社、科技日报 记者 张佳星、长江日报-长江网据新华社报道&#xff0c;在抗击新冠肺炎疫情期间&#xff0c;因连续工作、过度劳累&#xff0c;中国医学科学院病原生物学研究所研究员赵振东教授因…

智能流控

关键应用太慢&#xff0c;带宽用不好&#xff1f;AppEx 智能流控帮你轻松搞定&#xff01; 现代企业和机构的运转越来越依赖网络的畅通。而网络应用的日益繁杂经常让有限的带宽难以招架。企业和机构经常面临的一个问题是员工上网流量导致网络出口拥塞&#xff0c;从而严重影响企…

vim相关

2019独角兽企业重金招聘Python工程师标准>>> 跟我一起学Vim http://feihu.me/blog/2014/intro-to-vim/ 浅显易懂 #Vim学习笔记 http://mturing.com/wiki/wikihtml/Vim%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.html Vim基本操作,排版不错 #简明Vim练级攻略 http://cool…

php生成vcf,详解PHP如何实现生成vcf vcard文件

PHP如何实现生成vcf vcard文件&#xff1f;本文主要介绍了PHP实现生成vcf vcard文件功能类定义与使用方法&#xff0c;结合具体实例形式分析了vcf vcard功能类的具体定义与使用方法&#xff0c;并附带VCardIFL.class.php类文件源码供读者下载参考。需要的朋友可以参考下&#x…

Github怎么删除之前的项目

Github怎么删除之前的项目 对于github的好奇,在上面新建了一个项目,如下图 我想把上面的项目删掉,但是发现找了很久没有找到删除的地方,我勒个插,后来终于找到地方了,首先,我们点击进去这个项目,然后看到settings如图, 点击进…

HTTP1.1 Keep-Alive到底算不算长连接?

✎ 码甲说 在基础架构部浸润了半年&#xff0c;有一些认知刷新想和童靴们交代一下&#xff0c; 不一定全面&#xff0c;仅代表此时的认知&#xff0c; 也欢迎筒靴们提出看法。本文聊一聊口嗨用语&#xff1a;“长连接、短连接”&#xff0c; 文章会按照下面的思维导图来讲述&…

rabbitmq学习:

消息队列&#xff08;消息中间件&#xff09;常见的有三种&#xff1a;RabbitMQ、ActiveMQ、ZeroMQ 这里要说的是RabbitMQ。 需要明确的几个概念&#xff1a; Broker: 翻译为中文应该是“经纪人”、“中间人”吧&#xff0c;就是指RbbitMQ服务本身 vhost: 虚拟主机&#xff0c;…

磁盘与目录的容量(转)

磁盘与目录的容量 现在我们知道磁盘的整体数据是在 superblock 区块中&#xff0c;但是每个各别文件的容量则在 inode 当中记载的。 那在文字接口底下该如何叫出这几个数据呢&#xff1f;底下就让我们来谈一谈这两个命令&#xff1a; df&#xff1a;列出文件系统的整体磁盘使用…

酸了!第一名+第三名的学霸情侣,分别直博清华、人大…

全世界只有3.14 % 的人关注了爆炸吧知识本文授权转载自公众号&#xff1a;学术志&#xff08;ID&#xff1a;xueshuzhi001&#xff09;作者&#xff1a;青小小&#xff08;ID&#xff1a;zqwqxx&#xff09;综合自武汉大学在武汉大学数学与统计学院2017级数学基地班第一名和第三…

UVA10972 - RevolC FaeLoN(双连通分量)

题目链接 题意&#xff1a; 给定一个无向图&#xff0c;问最少加入多少条边&#xff0c;使得这个图成为连通图 思路&#xff1a;首先注意题目给出的无向图可能是非连通的&#xff0c;即存在孤立点。处理孤立点之后。其它就能够当作连通块来处理。事实上跟POJ3352非常像&#xf…

php返回一个变量,PHP从另一个文件获取变量

有许多不同的方法可以做到这个&#xff0c;我会和你分享2。INCLUDE可以在事实上include()它使用第三文件&#xff0c;但我不建议作为会议是容易得多。但是&#xff0c;如果你想要一个配置类型文件&#xff0c;这也很有用。顶部的login.php的&#xff1a;include(global.php);新…