5 关联式容器——预备知识

5.1 树

1、二叉搜索树

任何节点的键值一定大于其左子树的每一个节点的键值,并小于其右子树的每一个节点的键值。

插入:插入新元素时,从根节点开始,遇键值较大就向左,遇到键值较小者就向右,一直到尾端,即为插入点。

删除:分两种情况。如果A只有一个子节点,就直接将A的子节点连至A的父节点,并将A删除。如果A有两个子节点,就以右子树内的最小节点取代A(右子树的最小节点为:从右子节点开始,一直向左走到底即是)。


2、平衡二叉搜索树有AVL-tree、RB-tree、AA-tree等。


3、AVL tree

要求任何节点的左右子树高度相差最多1

(1)插入:分四种情况,为两类。

对于外侧插入,采用单旋转:


对于内侧插入,采用双旋转:


5.2 RB-tree(红黑树)

每个节点不是红色就是黑色;根节点是黑色;如果节点是红色,其子节点必须是黑色;任一节点至NULL(树尾端)的任何路径,所含黑节点树必须相同。

根据规则4,新增节点必须为红;根据规则3,新增节点之父节点必须为黑。


1、插入节点(根据插入位置和外围节点颜色分类)

状况1:S(伯父节点)为黑且为外侧插入。单旋转并改变P(父亲)、G(祖父)颜色。


状况2:S为黑且X为内侧插入。先对P、X做一次单旋转并更改G、X颜色,在对G做一次单旋转。


状况3:S为红。先将P、S变为黑,G变为红(注意G的父亲GG也是红,需要向上不断进行),转化为状况1或2。


2、RB-tree的节点设计

typedef bool __rb_tree_color_type;
const __rb_tree_color_type __rb_tree_red = false;
const __rb_tree_color_type __rb_tree_black = true;

struct __rb_tree_node_base
{
	typedef __rb_tree_color_type color_type;
	typedef __rb_tree_node_base* base_ptr;

	color_type color;
	base_ptr parent;
	base_ptr left;
	base_ptr right;
}

template <class Value>
struct __rb_tree_node : public __rb_tree_node_base
{
	typedef __rb_tree_node<Value>* link_type;
	Value value_field;
}

4、RB-tree的迭代器


void increment()
{
	if (node->right != 0) {
		node = node -> right;
		while (node->right != 0) {
			node = node -> left;
		}
	} else {
		base_ptr y = node -> parent;
		while (node == y->right) {  //可以看到没有判断y是否为NULL,这是因为class rb_tree中link_type header的存在。parent一定存在。
			node = y;
			y = y->parent;
		}
		if (node->right != y)   //可以考虑RB树中只有一个根节点和header节点的情况。
			node = y;       //注意end()即为header。
	}
}

5、RB-tree的数据结构

template <class Key, class Value, class KeyOfValue, class Compare,
           class Alloc = alloc>  //KeyOfValue和Compare应当是一个仿函数
class rb_tree {
protected:
  typedef void* void_pointer;
  typedef __rb_tree_node_base* base_ptr;
  typedef __rb_tree_node<Value> rb_tree_node;
  typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator;
  typedef __rb_tree_color_type color_type;
public:
  typedef Key key_type;
  typedef Value value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type& reference;
  typedef const value_type& const_reference;
  typedef rb_tree_node* link_type;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
protected:
  link_type get_node() { return rb_tree_node_allocator::allocate(); }
  void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); }
 
  link_type create_node(const value_type& x) {
    link_type tmp = get_node();
    __STL_TRY {
      construct(&tmp->value_field, x);
    }
    __STL_UNWIND(put_node(tmp));
    return tmp;
  }

  link_type clone_node(link_type x) {
    link_type tmp = create_node(x->value_field);
    tmp->color = x->color;
    tmp->left = 0;
    tmp->right = 0;
    return tmp;
  }

  void destroy_node(link_type p) {
    destroy(&p->value_field);
    put_node(p);
  }

protected:
  size_type node_count; // keeps track of size of tree
  link_type header;  
  Compare key_compare;

  link_type& root() const { return (link_type&) header->parent; }
  link_type& leftmost() const { return (link_type&) header->left; }
  link_type& rightmost() const { return (link_type&) header->right; }  //返回值是一个指针的引用,这样可以使我们能直接修改这个指针的值,而header->right本身可能为NULL。
  ...
};

关于header:其实就是根节点的父节点,以简化边界情况处理。( header和root互为对方的父节点!

void init() {
  header = get_node();
  color(header) = __rb_tree_red; // used to distinguish header from 
                                 // root, in iterator.operator++
  root() = 0;
  leftmost() = header;
  rightmost() = header;
}
iterator begin() { return leftmost(); } //RB树的起头为最左(最小)节点处
iterator end() { return header; }     //RB树的终点为header所指处

6、RB-tree的构造与内存管理


7、RB-tree的元素操作

(1)元素的插入

insert_unique():被插入节点的键值在整棵树中必须独一无二;

insert_equal():键值可以重复。



(2)元素的搜索


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值