算法导论第十三章

红黑树是一种较为平衡的搜索树, 当然满足所有搜索树应该具有的特点.

红黑树的几个性质:

1. 节点或红或黑 2. 根是黑的 3. 叶是黑的(叶均为nil, 是所谓的外节点, 而有值的节点均为内节点)

4. 如果一个节点是红的,则它的子女均为黑的 5. 对于任何节点, 从该节点到该节点的子孙叶节点的所有路径上所包含的黑节点数量相同。

从定义可以得到定理:一颗n个内节点的红黑树高度最多2lg(n+1).

一个完全2叉树的高度是lg(n+1), 所以可见红黑树的平衡性是相当不错的。

红黑树和普通的搜索树相比,主要的区别在于,红黑树进行插入删除之后,很可能会导致树破坏了上述5个性质,因而需要作一些调整: 为了做调整,有两个基础操作,分别是针对一个节点进行左旋或者右旋操作, 这两个操作都不会影响树本身的性质。

下面是我自己写的一些code. 都是根据书中思路所写,书中用数组来表示树, 我用节点来表示,有一些差别。 leftRotate, rightRotate.  除去insert和delete之外,红黑树和搜索树的行为均相同, 其中m_null表示空节点,属于黑节点。

 template<class Ty>
 class TreeNode
 {
 public:
  typedef Ty value_type;
  TreeNode() : m_parent(0), m_left(0), m_right(0) {}
  TreeNode(const Ty& __x, TreeNode<Ty>* leftChild, TreeNode<Ty>* rightChild, TreeNode<Ty>* parent)
   : m_parent(parent), m_left(leftChild), m_right(rightChild), m_value(__x), m_black(false) {}
  TreeNode(const Ty& __x) : m_parent(0), m_left(0), m_right(0), m_black(false) {}
  
  bool m_black;
  Ty m_value;
  TreeNode<Ty>* m_parent;
  TreeNode<Ty>* m_left;
  TreeNode<Ty>* m_right;

  TreeNode<Ty>* left() {
   return m_left; 
  }
  TreeNode<Ty>* right() {
   return m_right;
  }
  TreeNode<Ty>* parent() {
   return m_parent;
  }
  
  Ty& value() {
   return m_value;
  }
  
  static TreeNode<Ty>* makeNode(const Ty& __x, TreeNode<Ty>* leftChild = 0, TreeNode<Ty>* rightChild = 0, TreeNode<Ty>* parent = 0)
  {
   return new TreeNode<Ty>(__x, leftChild, rightChild, parent);
  }
  
  bool isRed() const {return !m_black;}
  bool isBlack() const {return m_black;}
  void setRed() {m_black = false;}
  void setBlack() {m_black = true;}
 };

 typedef TreeNode<Ty> node_type;

 void leftRotate(node_type* node)
 {
  assert(node != m_null);
  assert(node->right() != m_null);
  node_type* parent = node->parent();
  node_type* rightNode = node->right();
  node_type* rightNode_leftNode = rightNode->left();

  node->m_parent = rightNode;
  node->m_right = rightNode_leftNode;
  rightNode_leftNode->m_parent = node;
  rightNode->m_left = node;
  if (parent == m_null) // 如果node是根节点
  {
   m_root = rightNode;
   rightNode->m_parent = m_null;
  }  
  else
  {
   rightNode->m_parent = parent;
   if (parent->left() == node)
   {
    parent->m_left = rightNode;
   }
   else
   {
    parent->m_right = rightNode;
   }
  }
 }

 void rightRotate(node_type* node)
 {
  assert(node != m_null);
  assert(node->left() != m_null);
  node_type* parent = node->parent();
  node_type* leftNode = node->left();
  node_type* leftNode_rightNode = leftNode->right();

  node->m_parent = leftNode;
  node->m_left = leftNode_rightNode;
  leftNode_rightNode->m_parent = node;
  leftNode->m_right = node;
  if (parent == m_null) // 如果node是根节点
  {
   m_root = leftNode;
   leftNode->m_parent = m_null;
  }  
  else
  {
   leftNode->m_parent = parent;
   if (parent->left() == node)
   {
    parent->m_left = leftNode;
   }
   else
   {
    parent->m_right = leftNode;
   }
  }
 }

插入和搜索树插入相仿,只是加入了一些影响红黑的校正部分:

void insert(const value_type& __x)
 {
  node_type* curNode = m_root;
  node_type* node = TreeNode<Ty>::makeNode(__x, m_null, m_null, m_null);
  if (!m_root)
  {
   m_root = node;
   m_root->setBlack();
   return;
  }
  while(curNode != m_null)
  {
   if (m_function(node->value(), curNode->value()))
   {
    if (curNode->left() != m_null)
    {
     curNode = curNode->left();
    }
    else
    {
     curNode->m_left = node;
     node->m_parent = curNode;
     break;
    }
   }
   else
   {
    if (curNode->right() != m_null)
    {
     curNode = curNode->right();
    }
    else
    {
     curNode->m_right = node;
     node->m_parent = curNode;
     break;
    }
   }
  }
  node->setRed();
  insertFixup(node);
 }

 void insertFixup(node_type* node)
 {
  assert(node != m_null);
  assert(node->isRed());
  node_type* parent;
  node_type* parent_brother;
  node_type* grandParent;
  while(node->parent()->isRed())
  {
   parent = node->parent();
   grandParent = parent->parent();
   if (grandParent->left() == parent) // parent是parentparent的左子女
   {
    parent_brother = grandParent->right();
    if (parent_brother->isRed())  // 叔叔的颜色是红
    {
     parent->setBlack();
     grandParent->setRed();
     parent_brother->setBlack();
     node = grandParent;
    }
    else // 叔叔的颜色是黑
    {
     if (parent->right() == node)
     {
      leftRotate(parent);
      node = parent;
     }
     parent = node->parent();
     rightRotate(grandParent);
     grandParent->setRed();
     node->parent()->setBlack();
    }
   }
   else
   {
    parent_brother = grandParent->left();
    if (parent_brother->isRed())  // 叔叔的颜色是红
    {
     parent->setBlack();
     grandParent->setRed();
     parent_brother->setBlack();
     node = grandParent;
    }
    else // 叔叔的颜色是黑
    {
     if (parent->left() == node)
     {
      node = parent;
      rightRotate(parent);
     }
     leftRotate(grandParent);
     grandParent->setRed();
     node->parent()->setBlack();
    }
   }
  }
  m_root->setBlack();
 }
删除:

 void erase(const value_type& __x)
 {
  node_type* node = find(__x);
  if (node == m_null)
  {
   return;
  }
  if (node->left() == m_null || node->right() == m_null)
  {
   
  }
  else
  {
   node_type* nextNode = next(node);
   std::swap(node->m_value, nextNode->m_value);
   node = nextNode;
  }
  node_type** parent;
  if (node->parent() == m_null)
  {
   parent = &m_root;
  }
  else
  {
   if (node->parent()->left() == node)
   {
    parent = &(node->m_parent->m_left);
   }
   else
   {
    parent = &(node->m_parent->m_right);
   }
  }
  node_type* fixPara;
  if (node->left() != m_null)
  {
   fixPara = node->left();
   *parent = node->left();
   node->m_left->m_parent = node->parent(); // ? node->parent() : m_null;
  }
  else
  {
   fixPara = node->right();
   *parent = node->right();
//   if (node->right() != m_null)
   node->m_right->m_parent = node->parent(); // ? node->parent() : m_null;
  }
  if (node->isBlack())
  {
   eraseFixup(fixPara);
  }
  m_null->m_parent = 0;
  delete node; 

}

 void eraseFixup(node_type* node)
 {
  
  while (node != m_root && node->isBlack())
  {
   node_type* parent = node->parent();
   if (node == parent->left()) // node是左子女
   {
    node_type* sibling = parent->right();
    if (sibling->isRed()) // 如果兄弟是红, 转为黑
    {
     sibling->setBlack();
     parent->setRed();
     leftRotate(parent);
     sibling = parent->right();
    }
    if (sibling->left()->isBlack() && sibling->right()->isBlack())
    {
     node = parent;
     sibling->setRed();
    }
    else
    {
     if (sibling->right()->isBlack())
     {
      sibling->left()->setBlack();
      sibling->setRed();
      rightRotate(sibling);
      sibling = parent->right();
     }
     sibling->m_black = parent->m_black;
     parent->setBlack();
     sibling->right()->setBlack();
     leftRotate(parent);
     node = m_root;
    }
   }
   else // node是右子女
   {
    node_type* sibling = parent->left();
    if (sibling->isRed()) //
    {
     sibling->setBlack();
     parent->setRed();
     rightRotate(parent);
     sibling = parent->left();
    }
    if (sibling->right()->isBlack() && sibling->left()->isBlack())
    {
     node = parent;
     sibling->setRed();
    }
    else
    {
     if (sibling->left()->isBlack())
     {
      sibling->right()->setBlack();
      sibling->setRed();
      leftRotate(sibling);
      sibling = parent->left();
     }
     sibling->m_black = parent->m_black;
     parent->setBlack();
     sibling->left()->setBlack();
     rightRotate(parent);
     node = m_root;
    }
   }
  }
  node->setBlack();
 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值