前两天看了stl源码剖析关于红黑树的部分,自己合上书仿写了一个,作为检验自己是否真的搞懂了红黑树。当然主要的思路和写法和书上的一样,这里将红黑书删除部分也扩写了一下。如果有什么bug欢迎各位留言指出。
因为写的比较仓促,以后有时间会将代码重构一下,并说明关于删除部分的思路。
allocator.h 这个头文件是包装了malloc和free的简单空间配置器,本来一直想写一个内存池的奈何懒癌上身。。留坑以后填。
#pragma once;
#include<cstddef>
#include<cstdlib>
namespace MyStl
{
template<class T>
inline void destroy(T* pointer)
{
pointer->~T();
}
template<class ForwardIterator>
inline void destroy(ForwardIterator first, ForwardIterator last)
{
for (; first < last; ++first)
{
destroy(&*first);
}
}
inline void destroy(char*, char*) {}
inline void destroy(wchar_t*, wchar_t*) {}
template<class T1, class T2>
inline void construct(T1* p, const T2& value)
{
new (p) T1(value);
}
template<class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)
{
;
}
class alloc
{
public:
typedef void(*func)();
static void *oom_malloc(size_t);
static void *oom_realloc(void *, size_t);
static func __malloc_alloc_oom_handler;
static void *allocate(size_t n)
{
void *result = malloc(n);
if (result == nullptr)
result = oom_malloc(n);
return result;
}
static void deallocate(void *p)
{
free(p);
}
static void *reallocate(void *p, size_t new_size)
{
void *result = realloc(p, new_size);
if (result == nullptr)
result = oom_realloc(p, new_size);
return result;
}
static func set_malloc_handler(func f)
{
func old = __malloc_alloc_oom_handler;
__malloc_alloc_oom_handler = f;
return old;
}
};
void(*alloc::__malloc_alloc_oom_handler)() = 0;
void *alloc::oom_malloc(size_t n)
{
func my_malloc_handler;
void *result;
for (;;)
{
my_malloc_handler = __malloc_alloc_oom_handler;
if (my_malloc_handler == 0)
exit(1);
(*my_malloc_handler)();
result = malloc(n);
if (result)
return result;
}
}
void *alloc::oom_realloc(void *p, size_t n)
{
func my_malloc_handler;
void *result;
for (;;)
{
my_malloc_handler = __malloc_alloc_oom_handler;
if (my_malloc_handler == 0)
exit(1);
(*my_malloc_handler)();
result = realloc(p, n);
if (result)
return result;
}
}
template<class T,class Alloc = alloc>
class simple_alloc
{
public:
static void *allocate(size_t n = 1)
{
return Alloc::allocate(sizeof(T) * n);
}
static void deallocate(void *p)
{
return Alloc::deallocate(p);
}
static void *reallocate(void *p, size_t new_size)
{
return Alloc::reallocate(p, new_size);
}
};
}
rb_tree_.h 这个头文件是红黑树的实现部分,写的挺繁琐的。。if else一大堆。
#pragma once
#include"allocater.h"
#include<initializer_list>
#include<utility>
/*今天要扩展的内容,rb__tree的拷贝赋值,拷贝构造,移动赋值,移动构造,完美转发等等功能,swap资源交换函数。*/
namespace MyStl
{
typedef bool __rb_tree_color_type;
const __rb_tree_color_type __rb_tree_red = true;
const __rb_tree_color_type __rb_tree_black = false;
template<class T>
struct __rb_tree_node
{
typedef __rb_tree_color_type color_type;
typedef T value_type;
typedef __rb_tree_node<T>* ptr_node;
typedef __rb_tree_node<T> node;
value_type Value;
ptr_node parent;
ptr_node left;
ptr_node right;
color_type color;
template<class T2>
__rb_tree_node(T2&& n):Value(std::forward<T2>(n)) {}
ptr_node& ptr_son(ptr_node son_node)
{
if (left == son_node)
return left;
else if (right == son_node)
return right;
else
throw;
}
ptr_node& ptr_the_other_son(ptr_node son_node)
{
if (left == son_node)
return right;
if (right == son_node)
return left;
throw;
}
};
template<class T>
class __rb_tree_iterator
{
public:
typedef __rb_tree_iterator<T> iterator;
typedef typename __rb_tree_node<T>::value_type value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef typename __rb_tree_node<T>::ptr_node ptr_node;
typedef typename __rb_tree_node<T>::color_type color_type;
public:
ptr_node ptrnode;
public:
__rb_tree_iterator(const ptr_node& p = nullptr):ptrnode(p){}
__rb_tree_iterator(const iterator& it)
{
ptrnode = it.ptrnode;
}
iterator& operator++()
{
if (ptrnode->right != nullptr)
{
ptrnode = ptrnode->right;
while (ptrnode->left != nullptr)
{
ptrnode = ptrnode->left;
}
}
else
{
ptr_node y = ptrnode->parent;
while (ptrnode == y->right)
{
ptrnode = y;
y = y->parent;
}
if (ptrnode->right != y)
ptrnode = y;
}
return *this;
}
iterator& operator--()
{
if (ptrnode->color == __rb_tree_red && ptrnode->parent->parent == ptrnode)
{/*if语句中的==又写错了,天哪*/
ptrnode = ptrnode->right;
}
else if (ptrnode->left != nullptr)
{
ptrnode = ptrnode->left;
while (ptrnode->right != nullptr)
{
ptrnode = ptrnode->right;
}
}
else
{
ptr_node y = ptrnode->parent;
while (y->left == ptrnode)
{
ptrnode = y;
y = y->parent;
}
ptrnode = y;
}
return *this;
}
iterator operator++(int)
{
iterator tmp = *this;
++(*this);
return tmp;
}
iterator operator--(int)
{
iterator tmp = *this;
--(*this);
return tmp;
}
reference operator*()
{
return ptrnode->Value;
}
pointer operator->()
{
return &(operator*());
}
iterator& operator=(const iterator& it)
{
ptrnode = it.ptrnode;
return *this;
}
bool operator!=(const iterator& it)
{
if (ptrnode != it.ptrnode)
return true;
else
return false;
}
bool operator==(const iterator& it)
{
if (ptrnode == it.ptrnode)
return true;
else
return false;
}
};
template<class T>
class __rb_tree_const_iterator
{
public:
typedef __rb_tree_const_iterator<T> const_iterator;
typedef typename __rb_tree_node<T>::value_type value_type;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef typename __rb_tree_node<T>::ptr_node ptr_node;
typedef typename __rb_tree_node<T>::color_type color_type;
public:
ptr_node ptrnode;
public:
__rb_tree_const_iterator(const ptr_node& p = nullptr) :ptrnode(p) {}
__rb_tree_const_iterator(const const_iterator& it)
{
ptrnode = it.ptrnode;
}
const_iterator& operator++()
{
if (ptrnode->right != nullptr)
{
ptrnode = ptrnode->right;
while (ptrnode->left != nullptr)
{
ptrnode = ptrnode->left;
}
}
else
{
ptr_node y = ptrnode->parent;
while (ptrnode == y->right)
{
ptrnode = y;
y = y->parent;
}
if (ptrnode->right != y)
ptrnode = y;
}
return *this;
}
const_iterator& operator--()
{
if (ptrnode->color == __rb_tree_red && ptrnode->parent->parent == ptrnode)
{/*if语句中的==又写错了,天哪*/
ptrnode = ptrnode->right;
}
else if (ptrnode->left != nullptr)
{
ptrnode = ptrnode->left;
while (ptrnode->right != nullptr)
{
ptrnode = ptrnode->right;
}
}
else
{
ptr_node y = ptrnode->parent;
while (y->left == ptrnode)
{
ptrnode = y;
y = y->parent;
}
ptrnode = y;
}
return *this;
}
const_iterator operator++(int)
{
const_iterator tmp = *this;
++(*this);
return tmp;
}
const_iterator operator--(int)
{
const_iterator tmp = *this;
--(*this);
return tmp;
}
const_reference operator*() const
{
return ptrnode->Value;
}
pointer operator->()
{
return &(operator*());
}
const_iterator& operator=(const const_iterator& it)
{
ptrnode = it.ptrnode;
return *this;
}
bool operator!=(const const_iterator& it)
{
if (ptrnode != it.ptrnode)
return true;
else
return false;
}
bool operator==(const const_iterator& it)
{
if (ptrnode == it.ptrnode)
return true;
else
return false;
}
};
/*Compare是进行Key值比较的仿函数,KeyOfValue对象可以通过value值获取对应key值。*/
template<class Key,class Value,class Compare,class KeyOfValue,class Alloc = MyStl::alloc>
class rb_tree
{
public:
typedef Value value_type;
typedef Key key_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef Compare compare;
typedef KeyOfValue keyofvalue;
typedef typename __rb_tree_iterator<Value>::iterator iterator;
typedef typename __rb_tree_const_iterator<Value>::const_iterator const_iterator;
typedef typename __rb_tree_node<Value>::node node;
typedef typename __rb_tree_node<Value>::ptr_node ptr_node;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef MyStl::simple_alloc<node, MyStl::alloc> __rb_tree_allocator;
private:
ptr_node header;
compare comp;
keyofvalue kov;
size_type count;
protected:
//辅助函数
void _erase_balance_right(ptr_node x_node)
{
while (x_node != header->parent)
{
ptr_node parent = x_node->parent;
ptr_node y = parent->left;
if (y->color == __rb_tree_red)
{
y->color = __rb_tree_black;
parent->color = __rb_tree_red;
__rb_tree_rotate_right(parent, header->parent);
}
else if (y->left->color == __rb_tree_black && y->right->color == __rb_tree_black)
{
y->color = __rb_tree_red;
x_node = parent;
}
else if (y->right->color == __rb_tree_red && y->left->color == __rb_tree_black)
{
y->color = __rb_tree_red;
y->right->color = __rb_tree_black;
__rb_tree_rotate_left(y, header->parent);
}
else
{
y->color = parent->color;
parent->color = __rb_tree_black;
y->left->color = __rb_tree_black;
__rb_tree_rotate_right(parent, header->parent);
x_node = header->parent;
}
}
}
void _erase_balance_left(ptr_node x_node)
{
//x_node是一个附加颜色值得节点,不断上溯,将这个颜色在某个地方修改。
while (x_node != header->parent)
{
ptr_node parent = x_node->parent;
ptr_node y = parent->right;
if (y->color == __rb_tree_red)
{
y->color = __rb_tree_black;
parent->color = __rb_tree_red;
__rb_tree_rotate_left(parent, header->parent);
}
else if (y->left->color == __rb_tree_black && y->right->color == __rb_tree_black)
{
y->color = __rb_tree_red;
x_node = parent;
}
else if (y->left->color == __rb_tree_red && y->right->color == __rb_tree_black)
{
y->color = __rb_tree_red;
y->left->color = __rb_tree_black;
__rb_tree_rotate_right(y, header->parent);
}
else
{
y->color = parent->color;
parent->color = __rb_tree_black;
y->right->color = __rb_tree_black;
__rb_tree_rotate_left(parent, header->parent);
x_node = header->parent;
}
}
}
bool _erase(ptr_node node)
{
if (_has_no_child(node) && node->color == __rb_tree_red)
{
_erase_one(node);
//这个删除函数处理无儿子的红色节点
}
else if (_has_no_child(node) && node->color == __rb_tree_black)
{
_erase_two(node);
//这个删除函数处理无儿子的黑色节点
}
else if (_has_only_one_child(node) /*&& node->color == __rb_tree_black*/)
{
_erase_three(node);
//这个删除函数处理只有一个儿子的节点,事实上这个节点不可能是红色的。
}
else
{
_erase_four(node);
//这个删除函数处理有两个儿子的节点。
}
header->left = getmin(header->parent);
header->right = getmax(header->parent);
return true;
}
void _erase_one(ptr_node node)
{
/*这个节点不可能是根节点。不用处理这个情况*/
ptr_node parent = node->parent;
parent->ptr_son(node) = nullptr;
destroy_node(node);
}
void _erase_two(ptr_node node)
{
//待删除节点为黑色,没有儿子。
/*如果删除的是根节点*/
if (node == header->parent)
{
clear(header->parent);
destroy_node(header);
init();
return;
}
ptr_node parent = node->parent;
if (parent->color == __rb_tree_red)
{
//待删除节点的父节点为红色。
if (parent->left == node)
{
//待删除节点是父节点的左儿子。
__rb_tree_rotate_left(parent,header->parent);
parent->left = nullptr;
destroy_node(node);
if (parent->right)
{
__rb_tree_rebalance(parent->right, header->parent);
}
}
else
{
//待删除节点是父节点的右儿子。
__rb_tree_rotate_right(parent,header->parent);
parent->right = nullptr;
destroy_node(node);
if (parent->left)
{
__rb_tree_rebalance(parent->left, header->parent);
}
}
}
else
{
//待删除节点的父节点为黑色。
if (parent->left == node)
{
//待删除节点是父节点的左儿子。
ptr_node y = parent->right;
if (y->color == __rb_tree_red)
{
//待删除节点的兄弟节点是红色的。
__rb_tree_rotate_left(y,header->parent);
parent->color = __rb_tree_red;
y->color = __rb_tree_black;
parent->left = nullptr;
destroy_node(node);
}
else
{
//待删除节点的兄弟节点是黑色的。
if (_has_no_child(y))
{
//兄弟节点没有儿子。
y->color = __rb_tree_red;
parent->left = nullptr;
destroy_node(node);
_erase_balance_left(parent);
}
else if (y->right)
{
//兄弟节点右子节点(肯定为红色)存在
__rb_tree_rotate_left(parent, header->parent);
y->right->color = __rb_tree_black;
parent->left = nullptr;
destroy_node(node);
}
else
{
//兄弟节点左子节点(肯定为红色)存在,且右子节点不存在。
__rb_tree_rotate_right(y, header->parent);
__rb_tree_rotate_left(parent, header->parent);
parent->left = nullptr;
destroy_node(node);
}
}
}
else
{
//待删除节点是父节点的右儿子。
ptr_node y = parent->left;
if (y->color == __rb_tree_red)
{
//待删除节点的兄弟节点是红色的
__rb_tree_rotate_right(y, header->parent);
parent->color = __rb_tree_red;
y->color = __rb_tree_black;
parent->right = nullptr;
destroy_node(node);
}
else
{
//待删除节点的兄弟节点是黑色的。
if (_has_no_child(y))
{
//兄弟节点没有儿子。
y->color = __rb_tree_red;
parent->right = nullptr;
destroy_node(node);
_erase_balance_right(parent);
}
else if (y->left)
{
//兄弟节点左子节点(肯定为红色)存在
__rb_tree_rotate_right(parent, header->parent);
y->left->color = __rb_tree_black;
parent->right = nullptr;
destroy_node(node);
}
else
{
//兄弟节点右子节点(肯定为红色)存在,且左子节点不存在。
__rb_tree_rotate_left(y, header->parent);
__rb_tree_rotate_right(parent, header->parent);
parent->right = nullptr;
destroy_node(node);
}
}
}
}
}
void _erase_three(ptr_node node)
{
/*对于一颗红黑树来说,单节点情况只可能是父:黑,子:红。*/
ptr_node red_child = node->right ? node->right : node->left;
red_child->parent = node->parent;
if (node == header->parent)
{
header->parent = red_child;
}
if (node->parent->right == node)
{
node->parent->right = red_child;
}
if (node->parent->left == node)
{
node->parent->left = red_child;
}
if (node == header->right)
header->right = red_child;
if (node == header->left)
header->left = red_child;
red_child->color = __rb_tree_black;
destroy_node(node);
}
void _erase_four(ptr_node node)
{
ptr_node left_max = getmax(node->left);
node->Value = left_max->Value;
_erase(left_max);
}
bool _has_only_one_child(ptr_node node)
{
if (node && node->left == nullptr && node->right)
return true;
if (node && node->right == nullptr && node->left)
return true;
return false;
}
bool _has_no_child(ptr_node node)
{
if (node && node->right == nullptr && node->left == nullptr)
return true;
return false;
}
ptr_node get_node()
{
return (ptr_node)__rb_tree_allocator::allocate();
}
template<class T>
ptr_node create_node(T&& x)
{
ptr_node newnode = get_node();
MyStl::construct(newnode, std::forward<T>(x));
newnode->left = newnode->right = nullptr;
return newnode;
}
void put_node(ptr_node oldnode)
{
__rb_tree_allocator::deallocate(oldnode);
}
void destroy_node(ptr_node oldnode)
{
MyStl::destroy(oldnode);
put_node(oldnode);
}
void init()
{
header = get_node();
header->color = __rb_tree_red;
header->left = header->right = header;
header->parent = nullptr;
}
ptr_node getmax(ptr_node node)
{
if (node == nullptr)
return header;
while (node->right != nullptr)
node = node->right;
return node;
}
ptr_node getmin(ptr_node node)
{
if (node == nullptr)
return header;
while (node->left != nullptr)
node = node->left;
return node;
}
iterator __insert(ptr_node y, const value_type& v)
{
ptr_node newnode = create_node(v);
if (y == header)
{
header->parent = header->right = header->left = newnode;
newnode->parent = header;
newnode->color = __rb_tree_black;
}
else
{
if (comp(kov(v), kov(y->Value)))
{
y->left = newnode;
newnode->color = __rb_tree_red;
newnode->parent = y;
if (header->left == y)
{
header->left = newnode;
}
}
else
{
y->right = newnode;
newnode->color = __rb_tree_red;
newnode->parent = y;
if (header->right == y)
{
header->right = newnode;
}
}
}
++count;
__rb_tree_rebalance(newnode, header->parent);
return iterator(newnode);
}
void __rb_tree_rebalance(ptr_node newnode, ptr_node& root)
{
newnode->color = __rb_tree_red;
while (newnode != root && newnode->parent->color == __rb_tree_red)
{/*错误记录:while循环退出有问题*/
if (newnode->parent == newnode->parent->parent->left)
{
ptr_node y = newnode->parent->parent->right;
if (y && y->color == __rb_tree_red)
{
y->color = __rb_tree_black;
newnode->parent->color = __rb_tree_black;
newnode->parent->parent->color = __rb_tree_red;
newnode = newnode->parent->parent;
}
else
{
if (newnode == newnode->parent->right)
{
newnode = newnode->parent;
__rb_tree_rotate_left(newnode, root);
}
newnode->parent->color = __rb_tree_black;
newnode->parent->parent->color = __rb_tree_red;
__rb_tree_rotate_right(newnode->parent->parent, root);
}
}
else
{
ptr_node y = newnode->parent->parent->left;
if (y && y->color == __rb_tree_red)
{
newnode->parent->parent->color = __rb_tree_red;
y->color = __rb_tree_black;
newnode->parent->color = __rb_tree_black;
}
else
{
if (newnode == newnode->parent->left)
{
newnode = newnode->parent;
__rb_tree_rotate_right(newnode, root);
}
newnode->parent->color = __rb_tree_black;
newnode->parent->parent->color = __rb_tree_red;
__rb_tree_rotate_left(newnode->parent->parent, root);
}
}
}
root->color = __rb_tree_black;
}
void __rb_tree_rotate_left(ptr_node newnode, ptr_node& root)
{
ptr_node tmp = newnode->right;
ptr_node parent = newnode->parent;
/**/
if (root == newnode)
root = tmp;
else if (newnode == parent->left)
parent->left = tmp;
else
parent->right = tmp;
tmp->parent = parent;
/**/
newnode->right = tmp->left;
if (tmp->left != nullptr)
tmp->left->parent = newnode;
/**/
newnode->parent = tmp;
tmp->left = newnode;
}
void __rb_tree_rotate_right(ptr_node newnode, ptr_node& root)
{
ptr_node tmp = newnode->left;
ptr_node parent = newnode->parent;
/**/
if (root == newnode)
root = tmp;
else if (newnode == parent->left)
parent->left = tmp;
else
parent->right = tmp;
tmp->parent = parent;
/**/
newnode->left = tmp->right;
if (tmp->right != nullptr)
tmp->right->parent = newnode;
/**/
newnode->parent = tmp;
tmp->right = newnode;
}
public:
//构造函数
rb_tree(const compare& Comp = compare()) :header(nullptr), comp(Comp), kov(keyofvalue()), count(0) { init(); }
//析构函数
~rb_tree()
{
clear(header->parent);
destroy_node(header);
}
//接口函数
void clear(ptr_node node)
{
if (node == nullptr)
return;
if (node->left != nullptr)
clear(node->left);
if (node->right != nullptr)
clear(node->right);
destroy_node(node);
}
std::pair<iterator, bool> insert_unique(const value_type& v)
{
ptr_node y = header;
ptr_node x = header->parent;
while (x != nullptr && y->Value != v)
{
y = x;
//comp第一个参数小于第二个时为真。第一个参数大于等于第二个时为假。
x = comp(kov(v), kov(x->Value)) ? x->left : x->right;
}
if (y->Value == v)
{
return std::pair<iterator, bool>(iterator(y), false);
}
return std::pair<iterator, bool>(__insert(y, v), true);
}
iterator insert_equal(const value_type& v)
{
ptr_node y = header;
ptr_node x = header->parent;
while (x != nullptr)
{
y = x;
x = comp(kov(v), kov(x->Value)) ? x->left : x->right;
}
return __insert(y, v);
}
iterator find(const value_type& v)
{
ptr_node y = header;
ptr_node x = header->parent;
while (x != nullptr && y->Value != v)
{
y = x;
x = comp(kov(v), kov(x->Value)) ? x->left : x->right;
}
if (y!=header && y->Value == v)
{
return iterator(y);
}
return end();
}
bool erase(const value_type& v)
{
iterator it = find(v);
if (it == end())
return false;
else
return _erase(it.ptrnode);
}
iterator begin()
{
return iterator(header->left);
}
const_iterator rbegin()
{
return const_iterator(header->left);
}
const_iterator rend()
{
return const_iterator(header);
}
iterator end()
{
return iterator(header);
}
size_type size()
{
return count;
}
bool empty()
{
return count == 0;
}
compare& key_comp() const
{
return comp;
}
};
}
stl_rb_tree.cpp这个源文件供简单测试使用。
#include"rb_tree_.h"
#include<iostream>
using namespace MyStl;
int main()
{
rb_tree<int, std::less<int>, std::identity<int> > test{ 2,3,4,5,6,3 };
for (auto it = test.begin(); it != test.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
test.erase(2);
for (auto it = test.begin(); it != test.end(); ++it)
{
std::cout << *it << " ";
}
system("pause");
return 0;
}