282 lines
7.9 KiB
C++
282 lines
7.9 KiB
C++
#ifndef _AVL_TREE_IMPL_H_
|
|
#define _AVL_TREE_IMPL_H_
|
|
|
|
namespace TinySTL{
|
|
namespace Detail{
|
|
template<class T>
|
|
avl_iter<T>::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<class T>
|
|
avl_iter<T>& avl_iter<T>::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<class T>
|
|
avl_iter<T> avl_iter<T>::operator ++(int){
|
|
auto res = *this;
|
|
++*this;
|
|
return res;
|
|
}
|
|
template<class T>
|
|
bool operator ==(const avl_iter<T>& it1, const avl_iter<T>& it2){
|
|
return it1.ptr_ == it2.ptr_;
|
|
}
|
|
template<class T>
|
|
bool operator !=(const avl_iter<T>& it1, const avl_iter<T>& it2){
|
|
return !(it1 == it2);
|
|
}
|
|
}//end of Detail namespace
|
|
|
|
template<class T>
|
|
typename avl_tree<T>::node *avl_tree<T>::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<class T>
|
|
typename avl_tree<T>::node *avl_tree<T>::doubleLeftRightRotate(node * k3){
|
|
k3->left_ = singleRightRightRotate(k3->left_);
|
|
return singleLeftLeftRotate(k3);
|
|
}
|
|
template<class T>
|
|
typename avl_tree<T>::node *avl_tree<T>::doubleRightLeftRotate(node * k3){
|
|
k3->right_ = singleLeftLeftRotate(k3->right_);
|
|
return singleRightRightRotate(k3);
|
|
}
|
|
template<class T>
|
|
typename avl_tree<T>::node *avl_tree<T>::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<class T>
|
|
void avl_tree<T>::destroyAndDeallocateAllNodes(node *p){
|
|
if (p != 0){
|
|
destroyAndDeallocateAllNodes(p->left_);
|
|
destroyAndDeallocateAllNodes(p->right_);
|
|
dataAllocator::destroy(p);
|
|
dataAllocator::deallocate(p);
|
|
}
|
|
}
|
|
template<class T>
|
|
avl_tree<T>::~avl_tree(){
|
|
destroyAndDeallocateAllNodes(root_);
|
|
}
|
|
template<class T>
|
|
void avl_tree<T>::erase_elem(const T& val, node *&p){
|
|
if (p == 0)
|
|
return;
|
|
if (p->data_ != val){
|
|
if (val < p->data_)
|
|
return erase_elem(val, p->left_);
|
|
else
|
|
return erase_elem(val, p->right_);
|
|
}else{ // found
|
|
if (p->left_ != 0 && p->right_ != 0){// has two children
|
|
size_t choose = size_ % 2;
|
|
//随机选择删除左右,使得删除操作更平衡
|
|
auto pos = (choose == 0 ?
|
|
const_cast<node *>(find_min_aux(p->right_).ptr_) : const_cast<node *>(find_max_aux(p->left_).ptr_));
|
|
p->data_ = pos->data_;
|
|
return (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::destroy(temp);
|
|
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<class T>
|
|
void avl_tree<T>::erase(const T& val){
|
|
return erase_elem(val, root_);
|
|
}
|
|
template<class T>
|
|
void avl_tree<T>::insert_elem(const T& val, node *&p){
|
|
if (p == 0){
|
|
p = dataAllocator::allocate();
|
|
dataAllocator::construct(p);
|
|
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<class T>
|
|
void avl_tree<T>::insert(const T& val){
|
|
return insert_elem(val, root_);
|
|
}
|
|
template<class T>
|
|
template<class Iterator>
|
|
void avl_tree<T>::insert(Iterator first, Iterator last){
|
|
for (; first != last; ++first)
|
|
insert(*first);
|
|
}
|
|
template<class T>
|
|
void avl_tree<T>::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<class T>
|
|
void avl_tree<T>::print_preorder(const string& delim, std::ostream& os)const{
|
|
print_preorder_aux(delim, os, root_);
|
|
}
|
|
template<class T>
|
|
void avl_tree<T>::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<class T>
|
|
void avl_tree<T>::print_inorder(const string& delim, std::ostream& os)const{
|
|
print_inorder_aux(delim, os, root_);
|
|
}
|
|
template<class T>
|
|
void avl_tree<T>::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<class T>
|
|
void avl_tree<T>::print_postorder(const string& delim, std::ostream& os)const{
|
|
print_postorder_aux(delim, os, root_);
|
|
}
|
|
template<class T>
|
|
void avl_tree<T>::print_levelorder(const string& delim, std::ostream& os)const{
|
|
auto temp = root_;
|
|
if (temp != 0){
|
|
std::deque<node *> 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<class T>
|
|
typename avl_tree<T>::const_iterator avl_tree<T>::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<class T>
|
|
typename avl_tree<T>::const_iterator avl_tree<T>::find(const T& val)const{
|
|
return find_aux(val, root_);
|
|
}
|
|
template<class T>
|
|
typename avl_tree<T>::const_iterator avl_tree<T>::find_max_aux(const node *ptr)const{
|
|
while (ptr != 0 && ptr->right_ != 0)
|
|
ptr = ptr->right_;
|
|
return const_iterator(ptr, this);
|
|
}
|
|
template<class T>
|
|
typename avl_tree<T>::const_iterator avl_tree<T>::find_max()const{
|
|
return find_max_aux(root_);
|
|
}
|
|
template<class T>
|
|
typename avl_tree<T>::const_iterator avl_tree<T>::find_min_aux(const node *ptr)const{
|
|
while (ptr != 0 && ptr->left_ != 0)
|
|
ptr = ptr->left_;
|
|
return const_iterator(ptr, this);
|
|
}
|
|
template<class T>
|
|
typename avl_tree<T>::const_iterator avl_tree<T>::find_min()const{
|
|
return find_min_aux(root_);
|
|
}
|
|
}
|
|
|
|
#endif |