红黑树的基本操作



template<class K, class V>
class RBTree
{
    typedef RBTreeNode<K, V> Node;

public:

    RBTree()
        :_pRoot(NULL)
    {}

    //插入
    bool Insert(const K& key, const V& value)
    {
        return _Insert(_pRoot,key,value);
    }

    void InOrder()
    {
        _InOrder(_pRoot);
        cout << endl;
    }

    bool CkeckBRTree()
    {
        return _CheckRBTree(_pRoot);
    }
protected:

    //插入
    bool _Insert(Node*& pRoot, const K& key, const V& value)
    {
        if (NULL == pRoot)
        {
            _pRoot = new Node(key, value, BLACK);
            return false;
        }
        else
        {
            //找插入位置
            Node* pCur = _pRoot;
            Node* pParent = NULL;
            while (pCur)
            {
                if (key < pCur->_key)
                {
                    pParent = pCur;
                    pCur = pCur->_pLeft;
                }
                else if (key > pCur->_key)
                {
                    pParent = pCur;
                    pCur = pCur->_pRight;
                }
                else
                    return false;
            }
            //插入节点
            pCur = new Node(key, value);
            if (key < pParent->_key)
                pParent->_pLeft = pCur;
            else
                pParent->_pRight = pCur;

            pCur->_pParent = pParent;

            //用性质来跟新颜色
            while (pCur != pRoot && RED == pParent->_color)//存在pParent结点,且pParent结点存在双亲结点
            {
                Node* pGrandparent = pParent->_pParent;
                if (pParent == pGrandparent->_pLeft)
                {
                    Node* pUncle = pGrandparent->_pRight;
                    if (pUncle && RED == pUncle->_color)             //叔叔结点存在,且为红色
                    {
                        pUncle->_color = pParent->_color = BLACK;
                        pGrandparent->_color = RED;

                        pCur = pGrandparent;
                        pParent = pCur->_pParent;
                    }
                    else //pCur为红色,且pParent为红色,叔叔结点可以存在,且为黑色,或者不存在  //右单旋,或者左右双旋
                    {
                        if (pCur == pParent->_pRight) //情况五,先左单选,再右单选  //先改变为情况四
                        {
                            _RotateLeft(pParent);
                            swap(pParent, pCur);//旋转之后,pcur和pparent的位置发生过改变,需要再次进行交换,以方便后面该颜色
                        }

                        _RotateRight(pGrandparent); //改变双亲结点为黑色,祖父结点为红色
                        pParent->_color = BLACK;
                        pGrandparent->_color = RED;
                    }
                }
                else  //和上面的情况相反的方向
                {
                    Node* pUncle = pGrandparent->_pLeft;
                    if (pUncle && RED == pUncle->_color)
                    {
                        pUncle->_color = pParent->_color = BLACK;
                        pGrandparent->_color = RED;

                        pCur = pGrandparent;  //继续向上跟新
                        pParent = pCur->_pParent;
                    }
                    else  //情况四和情况五
                    {

                        if (pCur == pParent->_pLeft)
                        {
                            _RotateRight(pParent); //右单旋
                            swap(pParent, pCur);   //交换指针
                        }

                        _RotateLeft(pGrandparent);
                        pParent->_color = BLACK;
                        pGrandparent->_color = RED;
                    }
                }
                _pRoot->_color = BLACK;
                return true;
            }
        }
    }

    bool _CheckRBTree(Node* pRoot)
    {
        //1.每个根结点都是黑色的
        if (pRoot->_color == RED)
            return false;

        int count = 0;
        Node* pCur = pRoot;
        while (pCur)
        {
            if (BLACK == pCur->_color)
                count++;
            pCur = pCur->_pLeft;
        }

        int k = 0;
        return _CheckRBTree(pRoot, count, k);
    }

protected:

    void _RotateRight(Node*& pParent)
    {
        Node* pSubL = pParent->_pLeft;
        Node* pSubLR = pSubL->_pRight;
        pParent->_pLeft = pSubLR;
        pSubL->_pRight = pParent;
        if (pSubLR)
            pSubLR->_pParent = pParent;

        Node* pPParent = pParent->_pParent;
        pSubL->_pParent = pPParent;
        if (pPParent)
        {
            if (pPParent->_pLeft == pParent)
                pPParent->_pLeft = pSubL;
            else
                pPParent->_pRight = pSubL;
        }
        else
            _pRoot = pSubL;

        pParent->_pParent = pSubL;
    }

    void _RotateLeft(Node*& pParent)
    {
        Node* pSubR = pParent->_pRight;
        Node* pSubRL = pSubR->_pLeft;
        pParent->_pRight = pSubRL;
        pSubR->_pLeft = pParent;
        if (pSubRL)
            pSubRL->_pParent = pParent;

        Node* pPParent = pParent->_pParent;
        pSubR->_pParent = pPParent;
        if (pPParent)
        {
            if (pPParent->_pLeft == pParent)
                pPParent->_pLeft = pSubR;

            else
                pPParent->_pRight = pSubR;

        }
        else
            _pRoot = pSubR;

        pParent->_pParent = pSubR;
    }

    void _InOrder(Node*& pRoot)
    {
        if (pRoot)
        {
            _InOrder(pRoot->_pLeft);
            cout << pRoot->_key << " color:" << pRoot->_color << endl;;
            _InOrder(pRoot->_pRight);
        }
    }

    bool _CheckRBTree(Node* pRoot, int count, int k)
    {
        if (NULL == pRoot)
            return true;

        if (RED == pRoot->_color && RED == pRoot->_pParent->_color)
            return false;
        if (BLACK == pRoot->_color)
            k++;
        if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
        {
            if (k == count)
                return true;
            else
                return false;
        }
        return _CheckRBTree(pRoot->_pLeft, count, k) && _CheckRBTree(pRoot->_pRight, count, k);
    }

protected:
    Node* _pRoot;
};
<think>嗯,用户想了解红黑树基本操作以及如何用Python实现插入、删除和搜索。首先,我需要回忆一下红黑树的基本概念和规则。红黑树是一种自平衡的二叉查找树,每个节点有颜色属性,红色或黑色,需要满足几个性质:根节点是黑色,叶子节点(NIL)是黑色,红色节点的子节点必须是黑色,从任一节点到其每个叶子节点的所有路径都包含相同数量的黑色节点。这些性质确保了红黑树在插入和删除时能保持相对平衡,从而保证操作的时间复杂度为O(log n)。 接下来,用户需要Python的实现。红黑树的主要操作包括插入、删除和搜索。搜索和普通二叉查找树类似,但插入和删除后需要调整颜色和旋转来维持红黑树的性质。我得先考虑节点的结构,每个节点应该包含颜色、值、子节点和父节点。颜色可以用布尔值表示,比如True代表红色,False代表黑色。 插入操作分为两步:首先按照二叉查找树的方式插入节点,并着色为红色,然后调整颜色和结构。插入后可能破坏红黑树的性质,比如出现连续的红色节点,这时候需要通过旋转和变色来修复。插入的情况可能有多种,比如父节点是红色,叔节点是红色,这时候需要变色并将问题上移;如果叔节点是黑色,可能需要旋转,比如旋或旋,然后变色。 删除操作更复杂,因为删除节点后可能会破坏黑高。删除时需要考虑被删除节点的子节点情况,以及替换节点的颜色。如果被删除节点是红色,可能不需要调整;如果是黑色,则需要通过旋转和变色来修复。删除后的调整需要考虑兄弟节点的颜色及其子节点的颜色,进行相应的旋转和变色操作。 在Python中实现这些操作时,需要注意指针的调整,特别是父节点、子节点、子节点的引用。例如,插入时可能需要更新父节点的子节点指向,旋转操作需要调整各个节点的和父指针。此外,处理NIL节点时需要特别小心,可能需要将叶子节点用NIL哨兵节点表示,以简化逻辑。 搜索操作相对简单,和普通的二叉搜索树一样,递归或迭代地比较值的大小,决定向子树还是子树查找。 现在,需要将这些逻辑转化为Python代码。首先定义节点类,包含颜色、值、子节点和父节点。然后定义红黑树类,包含根节点和NIL节点。插入方法需要找到合适的位置插入新节点,然后进行修复。删除方法需要找到节点,处理子节点情况,然后进行修复。旋转操作需要处理旋和旋的逻辑,确保指针正确调整。 在实现过程中,可能会遇到指针处理错误,导致树的结构不正确。需要仔细检查旋转和父节点更新的步骤。此外,处理颜色调整时,要确保不违反红黑树的性质,例如修复插入后的连续红色节点,或者删除后的黑高不一致。 最后,测试代码的正确性,可以通过插入和删除一系列节点,检查树是否保持平衡,颜色是否符合规则。也可以参考已有的红黑树实现,对比逻辑是否正确。 总结来说,实现红黑树的关键在于正确维护颜色和结构,处理插入和删除后的调整步骤,确保所有操作后仍满足红黑树的性质。Python实现需要注意指针操作和递归或迭代的逻辑,同时使用NIL节点简化边界条件处理。</think>### 红黑树基本操作及Python实现 红黑树是一种自平衡二叉搜索树,通过颜色标记和旋转操作维持平衡,保证插入、删除、搜索的时间复杂度为 $O(\log n)$[^3]。以下是核心操作及实现逻辑: --- #### 一、红黑树基本性质 1. 节点颜色为红或黑,根节点为黑 2. 叶子节点(NIL)为黑 3. 红节点的子节点必须为黑 4. 从任意节点到其所有叶子节点的路径包含相同数量黑节点(黑高一致) --- #### 二、Python实现框架 ```python class Node: def __init__(self, value, color=True, left=None, right=None, parent=None): self.value = value self.color = color # True=红,False=黑 self.left = left self.right = right self.parent = parent class RedBlackTree: def __init__(self): self.NIL = Node(None, False) # 哨兵节点 self.root = self.NIL ``` --- #### 三、关键操作实现 ##### 1. 插入操作 **步骤:** - 按二叉搜索树规则插入新节点,初始颜色为红色 - 修复颜色冲突(连续红节点): - **情况1**:叔节点为红 → 父、叔、祖父变色,递归处理祖父节点 - **情况2**:叔节点为黑,节点与父方向不一致 → 父节点旋转调整方向 - **情况3**:叔节点为黑且方向一致 → 祖父节点旋转并变色 **代码片段:** ```python def insert_fixup(self, node): while node.parent.color: if node.parent == node.parent.parent.left: uncle = node.parent.parent.right if uncle.color: # 情况1 node.parent.color = False uncle.color = False node.parent.parent.color = True node = node.parent.parent else: if node == node.parent.right: # 情况2 node = node.parent self.left_rotate(node) # 情况3 node.parent.color = False node.parent.parent.color = True self.right_rotate(node.parent.parent) else: # 对称处理子树 # ...类似子树逻辑 self.root.color = False ``` ##### 2. 删除操作 **步骤:** - 按二叉搜索树规则删除节点 - 若删除节点为黑色,需修复黑高: - **情况1**:兄弟节点为红 → 旋转父节点并重新染色 - **情况2**:兄弟节点为黑且其子节点全黑 → 兄弟变红,递归处理父节点 - **情况3**:兄弟节点为黑且存在红色子节点 → 通过旋转调整结构[^2] **代码片段:** ```python def delete_fixup(self, node): while node != self.root and not node.color: if node == node.parent.left: sibling = node.parent.right if sibling.color: # 情况1 sibling.color = False node.parent.color = True self.left_rotate(node.parent) sibling = node.parent.right # 处理情况2和3 # ...具体旋转和变色逻辑 else: # 对称处理子树 # ...类似子树逻辑 node.color = False ``` ##### 3. 搜索操作 与普通二叉搜索树一致: ```python def search(self, value): current = self.root while current != self.NIL: if value == current.value: return True elif value < current.value: current = current.left else: current = current.right return False ``` --- #### 四、旋转操作示例(旋) ```python def left_rotate(self, x): y = x.right x.right = y.left if y.left != self.NIL: y.left.parent = x y.parent = x.parent if x.parent == self.NIL: self.root = y elif x == x.parent.left: x.parent.left = y else: x.parent.right = y y.left = x x.parent = y ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值