diff --git a/TinySTL/AVLTree.h b/TinySTL/AVLTree.h index 042dfe3..af1a027 100644 --- a/TinySTL/AVLTree.h +++ b/TinySTL/AVLTree.h @@ -8,7 +8,7 @@ #include namespace TinySTL{ - namespace { + namespace Detail{ template class avl_iter; } @@ -17,7 +17,7 @@ namespace TinySTL{ class avl_tree{ private: template - friend class avl_iter; + friend class Detail::avl_iter; private: struct node{ T data_; @@ -30,7 +30,7 @@ namespace TinySTL{ typedef TinySTL::allocator dataAllocator; public: typedef T value_type; - typedef avl_iter const_iterator; + typedef Detail::avl_iter const_iterator; typedef const T& const_reference; typedef size_t size_type; private: @@ -40,7 +40,7 @@ namespace TinySTL{ avl_tree() :root_(0), size_(0){} avl_tree(const avl_tree&) = delete; avl_tree& operator = (const avl_tree&) = delete; - ~avl_tree(){ destroyAndDeallocateAllNodes(root_); } + ~avl_tree(); void insert(const T& val); template @@ -50,235 +50,37 @@ namespace TinySTL{ size_t height()const{ return getHeight(root_); } size_t size()const{ return size_; } bool empty()const{ return root_ == 0; } - const_iterator root(){ return const_iterator(root_, this); } + const_iterator root()const{ return const_iterator(root_, this); } - const_iterator cbegin(){ return find_min(); } - const_iterator cend(){ return const_iterator(0, this); } + const_iterator cbegin()const{ return find_min(); } + const_iterator cend()const{ return const_iterator(0, this); } - const_iterator find_min(); - const_iterator find_max(); - const_iterator find(const T& val); + const_iterator find_min()const; + const_iterator find_max()const; + const_iterator find(const T& val)const; void print_preorder(const string& delim = " ", std::ostream& os = std::cout)const; void print_inorder(const string& delim = " ", std::ostream& os = std::cout)const; void print_postorder(const string& delim = " ", std::ostream& os = std::cout)const; void print_levelorder(const string& delim = " ", std::ostream& os = std::cout)const; private: - node *singleLeftLeftRotate(node *k2){ - auto k1 = k2->left_; - k2->left_ = k1->right_; - k1->right_ = k2; - k2->height_ = max(getHeight(k2->left_), getHeight(k2->right_)) + 1; - k1->height_ = max(getHeight(k1->left_), k2->height_) + 1; - return k1; - } - node *doubleLeftRightRotate(node * k3){ - k3->left_ = singleRightRightRotate(k3->left_); - return singleLeftLeftRotate(k3); - } - node *doubleRightLeftRotate(node * k3){ - k3->right_ = singleLeftLeftRotate(k3->right_); - return singleRightRightRotate(k3); - } - node *singleRightRightRotate(node * k2){ - auto k1 = k2->right_; - k2->right_ = k1->left_; - k1->left_ = k2; - k2->height_ = max(getHeight(k2->left_), getHeight(k2->right_)) + 1; - k1->height_ = max(k2->height_, getHeight(k1->right_)) + 1; - return k1; - } + node *singleLeftLeftRotate(node *k2); + node *doubleLeftRightRotate(node * k3); + node *doubleRightLeftRotate(node * k3); + node *singleRightRightRotate(node * k2); private: void insert_elem(const T& val, node *&p); void erase_elem(const T& val, node *&p); - void destroyAndDeallocateAllNodes(node *p){ - if (p != 0){ - destroyAndDeallocateAllNodes(p->left_); - destroyAndDeallocateAllNodes(p->right_); - dataAllocator::destroy(p); - dataAllocator::deallocate(p); - } - } + void destroyAndDeallocateAllNodes(node *p); size_t getHeight(const node *p)const{ return p == 0 ? 0 : p->height_; } - const_iterator find_min_aux(const node *ptr); - const_iterator find_max_aux(const node *ptr); - const_iterator find_aux(const T& val, const node *ptr); + const_iterator find_min_aux(const node *ptr)const; + const_iterator find_max_aux(const node *ptr)const; + const_iterator find_aux(const T& val, const node *ptr)const; void print_preorder_aux(const string& delim, std::ostream& os, const node *ptr)const; void print_inorder_aux(const string& delim, std::ostream& os, const node *ptr)const; void print_postorder_aux(const string& delim, std::ostream& os, const node *ptr)const; };// end of avl_tree - template - void avl_tree::erase_elem(const T& val, node *&p){ - if (p == 0) - return; - if (p->data_ < val){ - erase_elem(val, p->right_); - }else if (p->data_ > val){ - erase_elem(val, p->left_); - }else{// found - if (p->left_ != 0 && p->right_ != 0){//has two children - size_t choose = size_ % 2; - //随机选择删除左右,使得删除操作更平衡 - auto pos = (choose == 0 ? - const_cast(find_min_aux(p->right_).ptr_) : const_cast(find_max_aux(p->left_).ptr_)); - p->data_ = pos->data_; - (choose == 0 ? erase_elem(pos->data_, p->right_) : erase_elem(pos->data_, p->left_)); - }else{ //has one or no child - auto temp = p; - if (p->left_ == 0) - p = p->right_; - else - p = p->left_; - dataAllocator::deallocate(temp); - --size_; - } - } - if (p != 0){//最后更新p的节点高度信息和旋转维持平衡 - p->height_ = max(getHeight(p->left_), getHeight(p->right_)) + 1; - if (getHeight(p->left_) - getHeight(p->right_) == 2){ - if (p->left_->right_ == 0) - singleLeftLeftRotate(p); - else - doubleLeftRightRotate(p); - }else if (getHeight(p->right_) - getHeight(p->left_) == 2){ - if (p->right_->left_ == 0) - singleRightRightRotate(p); - else - doubleRightLeftRotate(p); - } - } - } - template - void avl_tree::erase(const T& val){ - return erase_elem(val, root_); - } - template - void avl_tree::insert_elem(const T& val, node *&p){ - if (p == 0){ - p = dataAllocator::allocate(); - //p->data_ = val; - construct(&(p->data_), val); - p->left_ = p->right_ = 0; - p->height_ = 1; - ++size_; - }else if (p->data_ < val){ - insert_elem(val, p->right_); - if (getHeight(p->right_) - getHeight(p->left_) == 2){ - if (val > p->right_->data_) - p = singleRightRightRotate(p); - else - p = doubleRightLeftRotate(p); - } - }else{ - insert_elem(val, p->left_); - if (getHeight(p->left_) - getHeight(p->right_) == 2){ - if (val < p->left_->data_) - p = singleLeftLeftRotate(p); - else - p = doubleLeftRightRotate(p); - } - } - p->height_ = max(getHeight(p->left_), getHeight(p->right_)) + 1; - } - template - void avl_tree::insert(const T& val){ - return insert_elem(val, root_); - } - template - template - void avl_tree::insert(Iterator first, Iterator last){ - for (; first != last; ++first) - insert(*first); - } - template - void avl_tree::print_preorder_aux(const string& delim, std::ostream& os, const node *ptr)const{ - if (ptr != 0){ - os << ptr->data_ << delim; - print_preorder_aux(delim, os, ptr->left_); - print_preorder_aux(delim, os, ptr->right_); - } - } - template - void avl_tree::print_preorder(const string& delim, std::ostream& os)const{ - print_preorder_aux(delim, os, root_); - } - template - void avl_tree::print_inorder_aux(const string& delim, std::ostream& os, const node *ptr)const{ - if (ptr != 0){ - print_inorder_aux(delim, os, ptr->left_); - os << ptr->data_ << delim; - print_inorder_aux(delim, os, ptr->right_); - } - } - template - void avl_tree::print_inorder(const string& delim, std::ostream& os)const{ - print_inorder_aux(delim, os, root_); - } - template - void avl_tree::print_postorder_aux(const string& delim, std::ostream& os, const node *ptr)const{ - if (ptr != 0){ - print_postorder_aux(delim, os, ptr->left_); - print_postorder_aux(delim, os, ptr->right_); - os << ptr->data_ << delim; - } - } - template - void avl_tree::print_postorder(const string& delim, std::ostream& os)const{ - print_postorder_aux(delim, os, root_); - } - template - void avl_tree::print_levelorder(const string& delim, std::ostream& os)const{ - auto temp = root_; - if (temp != 0){ - std::deque q; - q.push_back(temp); - while (!q.empty()){ - temp = q.front(); - q.pop_front(); - os << temp->data_ << delim; - if (temp->left_ != 0) q.push_back(temp->left_); - if (temp->right_ != 0) q.push_back(temp->right_); - } - } - } - template - typename avl_tree::const_iterator avl_tree::find_aux(const T& val, const node *ptr){ - while (ptr != 0){ - if (ptr->data_ < val) - ptr = ptr->right_; - else if (ptr->data_ > val) - ptr = ptr->left_; - else - break; - } - return const_iterator(ptr, this); - } - template - typename avl_tree::const_iterator avl_tree::find(const T& val){ - return find_aux(val, root_); - } - template - typename avl_tree::const_iterator avl_tree::find_max_aux(const node *ptr){ - while (ptr != 0 && ptr->right_ != 0) - ptr = ptr->right_; - return const_iterator(ptr, this); - } - template - typename avl_tree::const_iterator avl_tree::find_max(){ - return find_max_aux(root_); - } - template - typename avl_tree::const_iterator avl_tree::find_min_aux(const node *ptr){ - while (ptr != 0 && ptr->left_ != 0) - ptr = ptr->left_; - return const_iterator(ptr, this); - } - template - typename avl_tree::const_iterator avl_tree::find_min(){ - return find_min_aux(root_); - } - - namespace{ + namespace Detail{ //class of avl tree iterator template//T = node class avl_iter{ @@ -289,104 +91,33 @@ namespace TinySTL{ typedef typename avl_tree::value_type value_type; typedef typename avl_tree::const_reference const_reference; typedef typename const T::value_type *const_pointer; - typedef avl_tree * cntrPtr; + typedef const avl_tree * cntrPtr; private: const T *ptr_; cntrPtr container_; stack parent_;//保存从root到ptr_的父节点的路径 - std::set visited_; + std::set visited_;//当前节点是否被访问过(此node被访问说明其左子树已被访问了) public: - avl_iter(const T *ptr, cntrPtr container) - :ptr_(ptr), container_(container){ - auto temp = container_->root_; - while (temp &&ptr_ && temp != ptr_ && temp->data_ != ptr_->data_){ - parent_.push(temp); - if (temp->data_ < ptr_->data_) - temp = temp->right_; - else if (temp->data_ > ptr_->data_) - temp = temp->left_; - } - } + avl_iter(const T *ptr, cntrPtr container); - operator const T*(){ return ptr_; } - const_reference operator*(){ return ptr_->data_; } - const_pointer operator ->(){ return &(operator*()); } + operator const T*()const{ return ptr_; } + const_reference operator*()const{ return ptr_->data_; } + const_pointer operator ->()const{ return &(operator*()); } avl_iter left()const{ return avl_iter(ptr_->left_, container_); } avl_iter right()const{ return avl_iter(ptr_->right_, container_); } avl_iter& operator ++(); avl_iter operator ++(int); - avl_iter& operator --(); - avl_iter operator --(int); public: template friend bool operator ==(const avl_iter& it1, const avl_iter& it2); template friend bool operator !=(const avl_iter& it1, const avl_iter& it2); };//end of avl_iter - template - avl_iter& avl_iter::operator ++(){ - visited_.insert(ptr_);//设为已访问 - if (ptr_->right_ != 0){ - parent_.push(ptr_); - ptr_ = ptr_->right_; - while (ptr_ != 0 && ptr_->left_ != 0){ - parent_.push(ptr_); - ptr_ = ptr_->left_; - } - } - else{ - if (!parent_.empty() && visited_.count(parent_.top()) == 0){//父节点未访问 - ptr_ = parent_.top(); - parent_.pop(); - } - else{ - ptr_ = 0; - } - } - return *this; - } - template - avl_iter avl_iter::operator ++(int){ - auto res = *this; - ++*this; - return res; - } - template - avl_iter& avl_iter::operator --(){ - visited_.erase(ptr_);//设为未访问 - if (ptr_->left_ != 0){ - parent_.push(ptr_); - ptr_ = ptr_->left_; - while (ptr_ && ptr_->right_){ - parent_.push(ptr_); - ptr_ = ptr_->right_; - } - } - else{ - if (!parent_.empty() && visited_.count(parent_.top()) == 1){//父节点已经访问了 - ptr_ = parent_.top(); - parent_.pop(); - } - } - return *this; - } - template - avl_iter avl_iter::operator --(int){ - auto res = *this; - --*this; - return res; - } - template - bool operator ==(const avl_iter& it1, const avl_iter& it2){ - return it1.ptr_ == it2.ptr_; - } - template - bool operator !=(const avl_iter& it1, const avl_iter& it2){ - return !(it1 == it2); - } } } + +#include "Detail\AVLTree.impl.h" #endif \ No newline at end of file diff --git a/TinySTL/Detail/AVLTree.impl.h b/TinySTL/Detail/AVLTree.impl.h new file mode 100644 index 0000000..94c7579 --- /dev/null +++ b/TinySTL/Detail/AVLTree.impl.h @@ -0,0 +1,285 @@ +#ifndef _AVL_TREE_IMPL_H_ +#define _AVL_TREE_IMPL_H_ + +namespace TinySTL{ + namespace Detail{ + template + avl_iter::avl_iter(const T *ptr, cntrPtr container) + :ptr_(ptr), container_(container){ + if (!ptr_) + return; + auto temp = container_->root_; + while (temp && temp != ptr_ && temp->data_ != ptr_->data_){ + parent_.push(temp); + if (temp->data_ < ptr_->data_){ + //temp向右走说明temo指向的父节点不需要再次访问了 + visited_.insert(temp);//add 2015.01.14 + temp = temp->right_; + } + else if (temp->data_ > ptr_->data_){ + temp = temp->left_; + } + } + } + template + avl_iter& avl_iter::operator ++(){ + visited_.insert(ptr_);//此node被访问 + if (ptr_->right_){//此node还有右子树 + //rvisited_.insert(ptr_); + parent_.push(ptr_); + ptr_ = ptr_->right_; + while (ptr_ && ptr_->left_){ + parent_.push(ptr_); + ptr_ = ptr_->left_; + } + } + else{//node无右子树则只能向父节点路径移动 + ptr_ = 0;//add 2015.01.14 + while (!parent_.empty()){ + ptr_ = parent_.top(); + parent_.pop(); + if (visited_.count(ptr_) == 0){//父节点尚未访问,此时ptr_指向此节点 + visited_.insert(ptr_); + break; + } + ptr_ = 0;//设为哨兵 + }//end of while + }//end of if + return *this; + } + template + avl_iter avl_iter::operator ++(int){ + auto res = *this; + ++*this; + return res; + } + template + bool operator ==(const avl_iter& it1, const avl_iter& it2){ + return it1.ptr_ == it2.ptr_; + } + template + bool operator !=(const avl_iter& it1, const avl_iter& it2){ + return !(it1 == it2); + } + }//end of Detail namespace + + template + typename avl_tree::node *avl_tree::singleLeftLeftRotate(node *k2){ + auto k1 = k2->left_; + k2->left_ = k1->right_; + k1->right_ = k2; + k2->height_ = max(getHeight(k2->left_), getHeight(k2->right_)) + 1; + k1->height_ = max(getHeight(k1->left_), k2->height_) + 1; + return k1; + } + template + typename avl_tree::node *avl_tree::doubleLeftRightRotate(node * k3){ + k3->left_ = singleRightRightRotate(k3->left_); + return singleLeftLeftRotate(k3); + } + template + typename avl_tree::node *avl_tree::doubleRightLeftRotate(node * k3){ + k3->right_ = singleLeftLeftRotate(k3->right_); + return singleRightRightRotate(k3); + } + template + typename avl_tree::node *avl_tree::singleRightRightRotate(node * k2){ + auto k1 = k2->right_; + k2->right_ = k1->left_; + k1->left_ = k2; + k2->height_ = max(getHeight(k2->left_), getHeight(k2->right_)) + 1; + k1->height_ = max(k2->height_, getHeight(k1->right_)) + 1; + return k1; + } + template + void avl_tree::destroyAndDeallocateAllNodes(node *p){ + if (p != 0){ + destroyAndDeallocateAllNodes(p->left_); + destroyAndDeallocateAllNodes(p->right_); + dataAllocator::destroy(p); + dataAllocator::deallocate(p); + } + } + template + avl_tree::~avl_tree(){ + destroyAndDeallocateAllNodes(root_); + } + template + void avl_tree::erase_elem(const T& val, node *&p){ + if (p == 0) + return; + if (p->data_ < val){ + erase_elem(val, p->right_); + } + else if (p->data_ > val){ + erase_elem(val, p->left_); + } + else{// found + if (p->left_ != 0 && p->right_ != 0){//has two children + size_t choose = size_ % 2; + //随机选择删除左右,使得删除操作更平衡 + auto pos = (choose == 0 ? + const_cast(find_min_aux(p->right_).ptr_) : const_cast(find_max_aux(p->left_).ptr_)); + p->data_ = pos->data_; + (choose == 0 ? erase_elem(pos->data_, p->right_) : erase_elem(pos->data_, p->left_)); + } + else{ //has one or no child + auto temp = p; + if (p->left_ == 0) + p = p->right_; + else + p = p->left_; + dataAllocator::deallocate(temp); + --size_; + } + } + if (p != 0){//最后更新p的节点高度信息和旋转维持平衡 + p->height_ = max(getHeight(p->left_), getHeight(p->right_)) + 1; + if (getHeight(p->left_) - getHeight(p->right_) == 2){ + if (p->left_->right_ == 0) + singleLeftLeftRotate(p); + else + doubleLeftRightRotate(p); + } + else if (getHeight(p->right_) - getHeight(p->left_) == 2){ + if (p->right_->left_ == 0) + singleRightRightRotate(p); + else + doubleRightLeftRotate(p); + } + } + } + template + void avl_tree::erase(const T& val){ + return erase_elem(val, root_); + } + template + void avl_tree::insert_elem(const T& val, node *&p){ + if (p == 0){ + p = dataAllocator::allocate(); + //p->data_ = val; + construct(&(p->data_), val); + p->left_ = p->right_ = 0; + p->height_ = 1; + ++size_; + } + else if (p->data_ < val){ + insert_elem(val, p->right_); + if (getHeight(p->right_) - getHeight(p->left_) == 2){ + if (val > p->right_->data_) + p = singleRightRightRotate(p); + else + p = doubleRightLeftRotate(p); + } + } + else if (p->data_ > val){ + insert_elem(val, p->left_); + if (getHeight(p->left_) - getHeight(p->right_) == 2){ + if (val < p->left_->data_) + p = singleLeftLeftRotate(p); + else + p = doubleLeftRightRotate(p); + } + } + p->height_ = max(getHeight(p->left_), getHeight(p->right_)) + 1; + } + template + void avl_tree::insert(const T& val){ + return insert_elem(val, root_); + } + template + template + void avl_tree::insert(Iterator first, Iterator last){ + for (; first != last; ++first) + insert(*first); + } + template + void avl_tree::print_preorder_aux(const string& delim, std::ostream& os, const node *ptr)const{ + if (ptr != 0){ + os << ptr->data_ << delim; + print_preorder_aux(delim, os, ptr->left_); + print_preorder_aux(delim, os, ptr->right_); + } + } + template + void avl_tree::print_preorder(const string& delim, std::ostream& os)const{ + print_preorder_aux(delim, os, root_); + } + template + void avl_tree::print_inorder_aux(const string& delim, std::ostream& os, const node *ptr)const{ + if (ptr != 0){ + print_inorder_aux(delim, os, ptr->left_); + os << ptr->data_ << delim; + print_inorder_aux(delim, os, ptr->right_); + } + } + template + void avl_tree::print_inorder(const string& delim, std::ostream& os)const{ + print_inorder_aux(delim, os, root_); + } + template + void avl_tree::print_postorder_aux(const string& delim, std::ostream& os, const node *ptr)const{ + if (ptr != 0){ + print_postorder_aux(delim, os, ptr->left_); + print_postorder_aux(delim, os, ptr->right_); + os << ptr->data_ << delim; + } + } + template + void avl_tree::print_postorder(const string& delim, std::ostream& os)const{ + print_postorder_aux(delim, os, root_); + } + template + void avl_tree::print_levelorder(const string& delim, std::ostream& os)const{ + auto temp = root_; + if (temp != 0){ + std::deque q; + q.push_back(temp); + while (!q.empty()){ + temp = q.front(); + q.pop_front(); + os << temp->data_ << delim; + if (temp->left_ != 0) q.push_back(temp->left_); + if (temp->right_ != 0) q.push_back(temp->right_); + } + } + } + template + typename avl_tree::const_iterator avl_tree::find_aux(const T& val, const node *ptr)const{ + while (ptr != 0){ + if (ptr->data_ < val) + ptr = ptr->right_; + else if (ptr->data_ > val) + ptr = ptr->left_; + else + break; + } + return const_iterator(ptr, this); + } + template + typename avl_tree::const_iterator avl_tree::find(const T& val)const{ + return find_aux(val, root_); + } + template + typename avl_tree::const_iterator avl_tree::find_max_aux(const node *ptr)const{ + while (ptr != 0 && ptr->right_ != 0) + ptr = ptr->right_; + return const_iterator(ptr, this); + } + template + typename avl_tree::const_iterator avl_tree::find_max()const{ + return find_max_aux(root_); + } + template + typename avl_tree::const_iterator avl_tree::find_min_aux(const node *ptr)const{ + while (ptr != 0 && ptr->left_ != 0) + ptr = ptr->left_; + return const_iterator(ptr, this); + } + template + typename avl_tree::const_iterator avl_tree::find_min()const{ + return find_min_aux(root_); + } +} + +#endif \ No newline at end of file