经过长时间的学习终于可以开始tinystl的仿(chao)写工作了,本文参考了这位大神的github,坦白讲我只是补充了注释,因为tinystl的代码真的非常经典而我又没什么这种大型项目的经验,所以只能这样做,不过相信能够有助于大家的学习
#强烈建议按顺序阅读本专栏
二叉搜索树这一经典数据结构的实现很多,在stl中的设计也非常简洁明了,尤其是其中的深度获取值得学习
.h文件
#pragma once
#ifndef _BINARY_SEARCH_TREE_H_
#define _BINARY_SEARCH_TREE_H_
#include "Allocator.h"
#include "Iterator.h"
#include "Queue.h"
#include "Stack.h"
#include "String.h"
#include <set>
namespace mySTL {
namespace Detail {
template<class T>
class bst_iter;
}
//class of binary_search_tree
template<class T>
class binary_search_tree {
private:
template<class T>
friend class Detail::bst_iter;
private:
struct node {
typedef T value_type;
T data_;
node *left_;
node *right_;
explicit node(T d = T(), node *l = 0, node *r = 0)
:data_(d), left_(l), right_(r) {}
};
typedef mySTL::allocator<node> nodeAllocator;
public:
typedef T value_type;
typedef Detail::bst_iter<node> const_iterator;
typedef const T& const_reference;
typedef size_t size_type;
private:
node *root_;
size_t size_;
public:
binary_search_tree() :root_(0), size_(0) {}
//禁用复制构造函数
binary_search_tree(const binary_search_tree&) = delete;
binary_search_tree& operator=(const binary_search_tree&) = delete;
~binary_search_tree();
void insert(const T& val);
template<class Iterator>
void insert(Iterator first, Iterator last);
void erase(const T& val);
bool empty()const { return root_ == 0; }
size_t size()const { return size_; }
size_t height()const { return height_aux(root_); }
const_iterator root()const { return const_iterator(root_, this); }
const_iterator cbegin()const { return find_min(); }
const_iterator cend()const { return const_iterator(0, this); }
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:
void deallocateAllNodes(node *ptr);
size_t height_aux(node *p)const;
void erase_elem(const T& val, node *&ptr);
void insert_elem(const T& val, 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 bst class
namespace Detail {
//class of bst iterator
template<class T>//T = node
class bst_iter :
public iterator<forward_iterator_tag, typename ::TinySTL::binary_search_tree<typename T::value_type>::value_type> {
private:
template<class T>
friend class ::mySTL::binary_search_tree;
private:
//typedef typename ::TinySTL::binary_search_tree<typename T::value_type>::value_type value_type;
typedef typename ::mySTL::binary_search_tree<typename T::value_type>::const_reference const_reference;
typedef typename const T::value_type *const_pointer;
typedef const ::mySTL::binary_search_tree<typename T::value_type> * cntrPtr;
private:
const T *ptr_;
cntrPtr container_;
stack<const T *> parent_;//保存从root到ptr_的父节点的路径
//std::set<const T *> rvisited_;//当前节点的右子树是否被访问过
std::set<const T *> visited_;//当前节点是否被访问过(此node被访问说明其左子树已被访问了)
public:
bst_iter(const T *ptr, cntrPtr container);
operator const T*() { return ptr_; }
const_reference operator*()const { return ptr_->data_; }
const_pointer operator ->()const { return &(operator*()); }
bst_iter left()const { return bst_iter(ptr_->left_, container_); }
bst_iter right()const { return bst_iter(ptr_->right_, container_); }
bst_iter& operator ++();
bst_iter operator ++(int);
public:
template<class T>
friend bool operator ==(const bst_iter<T>& it1, const bst_iter<T>& it2);
template<class T>
friend bool operator !=(const bst_iter<T>& it1, const bst_iter<T>& it2);
};//end of bst_iter
}
}
#include "Detail\BinarySearchTree.impl.h"
#endif
impl.h文件
#pragma once
#ifndef _BINARY_SEARCH_TREE_IMPL_H_
#define _BINARY_SEARCH_TREE_IMPL_H_
namespace mySTL {
namespace Detail {
template<class T>
bst_iter<T>::bst_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>
//访问下一个可以是往下查找,也有可能是往上,这就是为什么我们需要visit和parent
bst_iter<T>& bst_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>
bst_iter<T> bst_iter<T>::operator ++(int) {
auto res = *this;
++*this;
return res;
}
template<class T>
bool operator ==(const bst_iter<T>& it1, const bst_iter<T>& it2) {
return it1.ptr_ == it2.ptr_;
}
template<class T>
bool operator !=(const bst_iter<T>& it1, const bst_iter<T>& it2) {
return !(it1 == it2);
}
}
//析构
template<class T>
binary_search_tree<T>::~binary_search_tree() {
deallocateAllNodes(root_);
}
template<class T>
void binary_search_tree<T>::deallocateAllNodes(node *ptr) {
if (ptr) {
deallocateAllNodes(ptr->left_);
deallocateAllNodes(ptr->right_);
nodeAllocator::destroy(ptr);
nodeAllocator::deallocate(ptr);
}
}
//数深度和层序遍历类似,但是用了两个queue来分别当前层和下一层
template<class T>
size_t binary_search_tree<T>::height_aux(node *p)const {
mySTL::queue<node *> q/*存放下一层的node*/, level/*存放当前层的node*/;
size_t nlevel = 0;
if (p != 0) {
level.push(p);
++nlevel;
while (!(q.empty() && level.empty())) {
if (level.empty()) {
++nlevel;
while (!q.empty()) {//当前层为空,将下一层的node全部转移至当前层
level.push(q.front());
q.pop();
}
}
auto temp = level.front();
level.pop();
if (temp->left_ != 0) q.push(temp->left_);
if (temp->right_ != 0) q.push(temp->right_);
}
}
return nlevel;
}
//删除指定元素
template<class T>
void binary_search_tree<T>::erase_elem(const T& val, node *&ptr) {
if (ptr == 0)
return;
if (ptr->data_ != val) {
if (val < ptr->data_)
return erase_elem(val, ptr->left_);
else
return erase_elem(val, ptr->right_);
}
else { // found
if (ptr->left_ != 0 && ptr->right_ != 0) {// has two children
size_t choose = size_ % 2;
//随机选择删除左右,使得删除操作更平衡(这个操作简直了)
auto pos = (choose == 0 ?
const_cast<node *>(find_min_aux(ptr->right_).ptr_) : const_cast<node *>(find_max_aux(ptr->left_).ptr_));
ptr->data_ = pos->data_;//将左子树最大值或右子树最小值移动到当前节点,然后再去删除左子树最大值或右子树最小值
return (choose == 0 ? erase_elem(pos->data_, ptr->right_) : erase_elem(pos->data_, ptr->left_));
}
else { //has one or no child
auto temp = ptr;
if (ptr->left_ == 0)
ptr = ptr->right_;
else
ptr = ptr->left_;
nodeAllocator::destroy(temp);
nodeAllocator::deallocate(temp);
--size_;
}
}
}
template<class T>
void binary_search_tree<T>::erase(const T& val) {
erase_elem(val, root_);
}
//
template<class T>
void binary_search_tree<T>::insert_elem(const T& val, node *&ptr) {//重复的元素不插入
if (ptr == 0) {
ptr = nodeAllocator::allocate();
nodeAllocator::construct(ptr);
ptr->data_ = val;
ptr->left_ = ptr->right_ = 0;
++size_;
}
else {
if (val < ptr->data_) {
return insert_elem(val, ptr->left_);
}
else if (val > ptr->data_) {
return insert_elem(val, ptr->right_);
}
}
}
template<class T>
void binary_search_tree<T>::insert(const T& val) {
insert_elem(val, root_);
}
template<class T>
template<class Iterator>
void binary_search_tree<T>::insert(Iterator first, Iterator last) {
for (; first != last; ++first)
insert(*first);
}
//各种遍历
template<class T>
void binary_search_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();
if (temp->left_ != 0) q.push_back(temp->left_);
if (temp->right_ != 0) q.push_back(temp->right_);
os << temp->data_ << delim;
}
}
}
template<class T>
void binary_search_tree<T>::print_preorder_aux(const string& delim, std::ostream& os, const node *ptr)const {
if (ptr) {
os << ptr->data_ << delim;
print_preorder_aux(delim, os, ptr->left_);
print_preorder_aux(delim, os, ptr->right_);
}
}
template<class T>
void binary_search_tree<T>::print_preorder(const string& delim, std::ostream& os)const {
print_preorder_aux(delim, os, root_);
}
template<class T>
void binary_search_tree<T>::print_inorder_aux(const string& delim, std::ostream& os, const node *ptr)const {
if (ptr) {
print_inorder_aux(delim, os, ptr->left_);
os << ptr->data_ << delim;
print_inorder_aux(delim, os, ptr->right_);
}
}
template<class T>
void binary_search_tree<T>::print_inorder(const string& delim, std::ostream& os)const {
print_inorder_aux(delim, os, root_);
}
template<class T>
void binary_search_tree<T>::print_postorder_aux(const string& delim, std::ostream& os, const node *ptr)const {
if (ptr) {
print_postorder_aux(delim, os, ptr->left_);
print_postorder_aux(delim, os, ptr->right_);
os << ptr->data_ << delim;
}
}
template<class T>
void binary_search_tree<T>::print_postorder(const string& delim, std::ostream& os)const {
print_postorder_aux(delim, os, root_);
}
//寻找对应节点及其子节点中的最大/最小值
template<class T>
typename binary_search_tree<T>::const_iterator binary_search_tree<T>::find_min_aux(const node *ptr)const {
while (ptr && ptr->left_ != 0) {
ptr = ptr->left_;
}
return const_iterator(ptr, this);
}
template<class T>
typename binary_search_tree<T>::const_iterator binary_search_tree<T>::find_min()const {
return find_min_aux(root_);
}
template<class T>
typename binary_search_tree<T>::const_iterator binary_search_tree<T>::find_max_aux(const node *ptr)const {
while (ptr && ptr->right_ != 0) {
ptr = ptr->right_;
}
return const_iterator(ptr, this);
}
template<class T>
typename binary_search_tree<T>::const_iterator binary_search_tree<T>::find_max()const {
return find_max_aux(root_);
}
//查找函数
template<class T>
typename binary_search_tree<T>::const_iterator binary_search_tree<T>::find_aux(const T& val, const node *ptr)const {
while (ptr) {
if (val == ptr->data_)
break;
else if (val < ptr->data_)
ptr = ptr->left_;
else
ptr = ptr->right_;
}
return const_iterator(ptr, this);
}
template<class T>
typename binary_search_tree<T>::const_iterator binary_search_tree<T>::find(const T& val)const {
return find_aux(val, root_);
}
}
#endif