- STL將node分爲兩層,父類base記錄節點顏色以及父子指針,子類記錄節點的值(感受這樣設計是爲了不模板帶來的代碼冗餘)。
#ifndef STL_RB_TREE
#define STL_RB_TREE
#include<cstddef>
#include "../allocator/stl_alloc.h"
#include "../allocator/stl_construct.h"
typedef bool __rb_tree_color_type;
const __rb_tree_color_type __rb_tree_red=false;
const __rb_tree_color_type __rb_tree_black=false;
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;
static base_ptr minimum(base_ptr x) {
while(x->left!=nullptr) x=x->left;
return x;
}
static base_ptr maximum(base_ptr x) {
while (x->right!=nullptr) x=x->right;
return x;
}
};
template<typename Value>
struct __rb_tree_node:public __rb_tree_node_base
{
typedef __rb_tree_node<Value>* link_type;
Value value_field;
};
複製代碼
- 一樣迭代器的設計也分爲兩層
struct __rb_tree_base_iterator {
typedef __rb_tree_node_base::base_ptr base_ptr;
typedef bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
base_ptr node;
void increment(){
if (node->right!=nullptr) {
node=node->right;
while(node->left != nullptr) node=node->left;
} else {
base_ptr y=node->parent;
while (node == y->right) {
node = y;
y=y->parent;
}
if (node->right !=y) node=y; //通常狀況下都是不等於的,可是當node爲hearder時等於,見下圖
}
}
void decrement(){
// 當node 爲 end()時
if (node->color == __rb_tree_red && node->parent->parent == node) node=node->right; //和迭代器實現的臨界值(header)有關
else if (node->left!=0){
base_ptr y=node->left;
while(y->right!=0) y=y->right;
node=y;
} else {
base_ptr y=node->parent;
while (node ==y->left){
node = y;
y=y->parent;
}
node = y;
}
}
};
template <typename Value, typename Ref, typename Ptr>
struct __rb_tree_iterator:public __rb_tree_base_iterator{
typedef Value value_type;
typedef Ref reference;
typedef Ptr pointer;
typedef __rb_tree_iterator<Value, Value&, Value*> iterator;
typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator;
typedef __rb_tree_iterator<Value, Ref, Ptr> self;
typedef __rb_tree_node<Value>* link_type;
__rb_tree_iterator(){}
__rb_tree_iterator(link_type x) {node=x;}
__rb_tree_iterator(const iterator& it) {node=it.node;}
reference operator*() const {return link_type(node)->value_field;}
pointer operator->() const {return &(operator*());}
self& operator++() {increment(); return *this;}
self operator++(int) {
self tmp = *this;
increment();
return tmp;
}
};
複製代碼
一個空的rb_tree如左圖,插入第一個節點以後如右圖,
header->parent==root;root->parent==header
node![]()
template<typename Key, typename Value, typename KeyOfValue, typename Compare, typename Alloc=alloc> // keyOfValue 做用是在Value中提取Key值, 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; //第二章空間配置相關的,分配node內存
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();
try {
construct(&tmp->value_field, x);
} catch (...) {
put_node(tmp);
throw;
}
}
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 x) {
destroy(&x->value_field);
put_node(x);
}
protected:
size_type node_count; // 只維護這三個屬性
link_type header; // 插入節點須要保證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;}
static color_type& color(base_ptr x) {
return (color_type&) (link_type(x)->color); //一種強制轉換指針寫法?
}
static link_type minimum(link_type x) {
return (link_type) __rb_tree_node_base::minimum(x);
}
public:
typedef __rb_tree_iterator<value_type, reference, pointer> iterator;
private:
void init() {
header = get_node();
color(header) = __rb_tree_red;
root() = 0;
leftmost() = header;
rightmost() = header;
}
rb_tree(const Compare& comp=Compare()):node_count(0), key_compare(comp) {init();}
~rb_tree() {
clear();
put_node(header);
}
public:
iterator begin() {return leftmost();}
iterator end() {return header;}
bool empty() const {return node_count==0;}
size_type max_size() const {return size_type(-1);}
};
複製代碼
- rb_tree提供兩種插入操做
- insert_unique, key值若是已經存在,插入操做不會進行
- insert_equal, key能夠重複
- 這兩種操做世界都是依賴於__insert方法,__insert實現以下
template<class Key, class Value, class KeyOfValue, class Compare, class Alloc> typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__insert(base_ptr x_, base_ptr y_, const Value& v){
link_type x = (link_type) x_;
link_type y = (link_type) y_;
link_type z;
if (y==header || x!=0 || key_compare(KeyOfValue()(v), key(y))) {//x應該一直==0
z = create_node(v);
left(y) = z;
if (y==header){
root() = z;
rightmost() == z;
}
else if (y==leftmost())
leftmost() = z;
} else {
z = create_node(v);
right(y) = z;
if (y==rightmost())
rightmost() = z;
}
parent(z) = y;
left(z) = 0;
right(z) = 0;
__rb_tree_rebalance(z, header->parent); //調節rb_tree
++node_count;
return iterator(z);
}
inline void
_rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base* &root){
x->color = __rb_tree_red; //新節點爲紅
while(x!=root && x->parent->color == __rb_tree_red) {
if (x->parent == x->parent->parent->left) {
__rb_tree_node_base *y=x->parent->parent->right;
if (y && y->color == __rb_tree_red) { // 伯父節點爲紅時向上變色,一直到上層某節點的伯父節點爲黑,使用伯父節點爲黑的調整策略
x->parent->color = __rb_tree_black;
y->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
x = x->parent->parent;
} else {
if (x==x->parent->right) {
x = x->parent;
__rb_tree_rotate_left(x, root);
}
x->parent->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_black;
__rb_tree_rotate_right(x->parent->parent, root);
}
} else {
__rb_tree_node_base* y = x->parent->left;
if (y && y->color == __rb_tree_red) {
x->parent->color = __rb_tree_black;
y->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
x = x->parent->parent;
} else {
if (x==x->parent->left) {
x = x->parent;
__rb_tree_rotate_right(x, root);
}
x->parent->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_black;
__rb_tree_rotate_left(x->parent->parent, root);
}
}
}
root->color = __rb_tree_black;
}
inline void
__rb_tree_rotate_left(__rb_tree_node_base *x, __rb_tree_node_base*& root){
__rb_tree_node_base* y = x->right;
x->right = y->left;
if (y->left!=0) y->left->parent = x;
y->parent = x->parent;
if (x==root) root=y;
else if (x==x->parent->left) {
x->parent->left = y;
}else x->parent->right = y;
y->left = x;
x->parent = y;
}
inline void
__rb_tree_rotate_right(__rb_tree_node_base *x, __rb_tree_node_base*& root){
__rb_tree_node_base * y = x->left;
x->left = y->right;
if (y->right != 0) {
y->right->parent = x;
}
y->parent = x->parent;
if (x==root) y=root;
else if (x==x->parent->right) x->parent->right = y;
else x->parent->left = y;
y->right = x;
x->parent = y;
}
複製代碼
#ifndef STL_SET
#define STL_SET
#include "stl_rb_tree.h"
template <class Key, class Compare = less<Key>, class Alloc=alloc> class set{
public:
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
private:
typedef rb_tree<key_type, value_type, identity<value_type>, key_compare, Alloc> rep_type;
rep_type t;
public:
typedef typename rep_type::const_pointer pointer;
typedef typename rep_type::const_pointer const_pointer;
typedef typename rep_type::const_reference reference;
typedef typename rep_type::const_reference const_reference;
typedef typename rep_type::const_iterator iterator;
// ...
};
#endif
複製代碼
- set 的實現都是基於 rep_type t
- 其插入操做均是經過insert_unique 實現
- multiset其餘和set一致,除了插入操做是經過insert_equal
#ifndef STL_MAP
#define STL_MAP
#include "stl_rb_tree.h"
template <class Key, class T, class Compare = less<Key>, class Alloc=alloc> class map{
public:
typedef Key key_type;
typedef T data_type;
typedef T mapped_type;
typedef pair<const Key, T> value_type;
typedef Compare key_compare;
class value_compare: public binary_function<value_type, value_type, bool> {
friend class map<Key, T, Compare, Alloc>;
protected:
Compare comp;
value_compare(Compare c): comp(c) {}
public:
bool operator() (const value_type &x, const value_type& y) const {
return comp(x.first, y.first);
}
};
private:
typedef rb_tree<key_type, value_type, select1st<value_type>, key_compare, Alloc> rep_type;
rep_type t;
複製代碼
- map和set 相似,只是value_type 傳的會是const Key 和 T的pair
STL也提供了hashtable做爲關聯容器的底層容器,而後使用開鏈策略c++
- hashtable buckets使用vector,vector保存的是node的指針。
// node 實現,鏈表
template<class Value> struct __hashtable_node{
__hashtable_node *next;
Value val;
};
複製代碼
// 迭代器實現
template<class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc> struct __hashtable_iterator{
typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> hashtable;
typedef __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> iterator;
typedef __hashtable_node<Value> node;
typedef forward_iterator_tag iterator_category;
typedef Value value_type;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
typedef Value& reference;
typedef Value* pointer;
node* cur; //迭代器目前指向節點
hashtable* ht;//爲了保持從bucket跳轉bucket
__hashtable_iterator(node* n, hashtable* tab): cur(n), ht(tab) {}
__hashtable_iterator(){}
reference operator*() const {return cur->val;}
pointer operator->() const {return &(operator*());} //注意必定會是表現的value的指針,而不是node
iterator operator++() {
const node* old = cur;
cur =cur->next;
if (!cur) {
size_type bucket = ht->bkt_num(old->val);
while (!cur && ++bucket < ht->buckets.size()){
cur = ht->buckets[bucket];
}
}
return *this;
}
};
複製代碼
//hashtable 實現
template<class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
class hashtable{
public:
typedef HashFcn hasher;
typedef EqualKey key_equal;
typedef size_t size_type;
private:
hasher hash;
key_equal equals;
ExtractKey get_key;
typedef __hashtable_node<Value> node;
typedef simple_alloc<node, Alloc> node_allocator;
vector<node*, Alloc> buckets;
size_type num_elements;
public:
size_type bucket_count() const {return buckets.size();}
node *new_node(const value_type& obj) {
node* n = node_allocator::allcocate();
n->next = 0;
try{
construct(&n->val, obj);
return n;
} catch (...){}
}
void delete_node(node* n);
pair<iterator, bool> insert_unique(const value_type& obj){
resize(num_elements+1);
return insert_unique_noresize(obj);
}
size_type bkt_num(const value_type& obj, size_t n) const{ //決定這個值在哪一個bucket上
return bkt_num_key(get_key(obj), n);
}
size_type bkt_num_key(const key_type& key) const {
return bkt_num_key(key, buckets.size();)
}
size_type bkt_num_key(const key_type& key, size_t n) const {
return hash(key) % n;
}
void reseize(size_type num_elements_hint){
const size_type old_n = buckets.size();
if (num_elements_hint > old_n) {
const size_type n = next_size(num_elements_hint); // next_size 是找出大於hint的下一個質數
if (n>old_n){
vector<node*, Alloc> tmp(n, (node*) 0);
for (size_type bucket=0; bucket< old_n; ++buckets){
node* first = buckets[bucket];
while(first){
size_type new_bucket = bkt_num(first->val, n);
buckets[bucket] = first->next; //替換原先bucket的first
first->next = tmp[new_bucket]; //將first加到新的bucket的第一位作準備(加上下面一行邏輯)
tmp[new_bucket] = first;
first = buckets[bucket];
}
}
buckets.swap(tmp);
}
}
}
pair<iterator, bool> insert_unique_noresize(const value_type& obj){
const size_type n = bkt_num(obj);
node* first = buckets[n];
for (node *cur=first;cur;cur=cur->next) {
if equals(get_key(cur->val), get_key(obj)) {
return pair<iterator, bool> (iterator(cur, this), false);
}
}
node* tmp = new_node(obj);
tmp->next = first;
buckets[n] = tmp; // 新的節點將插入到第一位
++num_elements;
return pair<iterator, bool> (iterator(tmp. this), true);
}
複製代碼