binary search tree
二叉搜索树性质挺简单的就不多说, 解决小问题,为后面的红黑树做个小铺垫
不过这里用到了string容器,之前设计的string存在点问题,就先拿std::string压压惊先了
binary search tree设计
- empty() 树是否为空
- erase(val) 删除指定元素
- insert(val) 添加指定元素
- size() 树上结点数量
- depth() 返回树的深度
- cbegin() 返回树的最小值迭代器
- cend() 返回树的末尾迭代器
- find(val) 寻找值
- find_min() 寻找最小值
- find_max() 寻找最大值
- print_inorder() 打印中序遍历
迭代器相关:
重点是运算符的重载,这里实现了迭代器自加功能++it、it++,自减功能可以模仿写一个
binary_search_tree.h
#ifndef _BINARY_SEARCH_TREE_H_
#define _BINARY_SEARCH_TREE_H_
#include "../Includes/Allocator.h"
#include "../Includes/Iterator.h"
#include "../Includes/Algorithm.h"
#include "stl_queue.h"
#include "stl_stack.h"
#include <string>
#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;
value_type 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) {}
// 禁用copy构造
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_ == nullptr; }
size_t size()const { return size_; }
size_t depth()const { return depth_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_inorder(const std::string& delim = " ", std::ostream& os = std::cout)const;
private:
void deallocateAllNodes(node* ptr);
size_t depth_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_inorder_aux(const std::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 ::mySTL::binary_search_tree<typename T::value_type>::value_type> {
private:
template<class T>
friend class ::mySTL::binary_search_tree;
private:
typedef typename ::mySTL::binary_search_tree<typename T::value_type>::const_reference const_reference;
typedef const typename 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*> 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_); }
// ++iter iter++
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/stl_binary_search_tree.impl.h"
#endif
binary_search_tree.impl.h
#ifndef _BINARY_SEARCH_TREE_IMPL_H_
#define _BINARY_SEARCH_TREE_IMPL_H_
//#include "../p2_STL_Source/stl_binary_search_tree.h"
namespace mySTL {
namespace detail {
template<class T>
bst_iter<T>::bst_iter(const T* ptr, cntrPtr container)
:ptr(ptr), container_(container)
{
if (ptr == nullptr) return;
auto temp = container_->root_; // 记录根节点
// 没有找到对应结点
// parent保存从root到ptr父节点的路径
while (temp && temp->data_ != ptr->data_)
{
parent.push(temp); // 储存节点
// 搜索树,大往右子树,小往左子树
// visited保存比ptr->data_值小的结点
if (temp->data_ < ptr->data_)
{
//temp向右走说明temp指向的父节点不需要再次访问了
visited.insert(temp);
temp = temp->right_;
}
else if (temp->data_ > ptr->data_)
{
temp = temp->left_;
}
}
}
template<class T>
bst_iter<T>& bst_iter<T>::operator++()
{
visited.insert(this->ptr);//此node被访问
if (this->ptr->right_) // 有右节点
{
parent.push(ptr);
ptr = ptr->right_;
// 寻找右子树的最左结点,根据二叉搜索树性质可知
// 即寻找在排序中,在ptr结点后的节点(后续结点)
while (ptr != nullptr && ptr->left_ != nullptr)
{
parent.push(ptr);
ptr = ptr->left_;
}
}
else //node无右子树则只能向父节点路径移动
{
ptr = nullptr;
while (!parent.empty())
{
ptr = parent.top();
parent.pop();
if (visited.count(ptr) == 0)// 父节点尚未访问,此时ptr指向此节点
{
visited.insert(ptr);
break;
}
ptr = nullptr; // 设为哨兵
}
}
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 != nullptr)
{
deallocateAllNodes(ptr->left_);
deallocateAllNodes(ptr->right_);
nodeAllocator::destroy(ptr);
nodeAllocator::deallocate(ptr);
}
}
// 插入和擦除
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>::erase(const T& val)
{
erase_elem(val, root_);
}
// 查找函数
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() const
{
return find_max_aux(root_);
}
template<class T>
typename binary_search_tree<T>::const_iterator binary_search_tree<T>::find(const T& val) const
{
return find_aux(val, root_);
}
// 遍历 中序
template<class T>
void binary_search_tree<T>::print_inorder(const std::string& delim, std::ostream& os) const
{
print_inorder_aux(delim, os, root_);
}
// 辅助函数
template<class T>
size_t binary_search_tree<T>::depth_aux(node* p) const
{
if (p == nullptr) return 0;
auto leftDepth = depth_aux(p->left_);
auto rightDepth = depth_aux(p->right_);
return 1 + max(leftDepth, rightDepth);
}
template<class T>
void binary_search_tree<T>::insert_elem(const T& val, node*& ptr)
{
if (ptr == nullptr)
{
ptr = nodeAllocator::allocate();
nodeAllocator::construct(ptr);
ptr->data_ = val;
ptr->left_ = ptr->right_ = nullptr;
++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>::erase_elem(const T& val, node*& ptr)
{
// 在删除结点中,并没有涵盖所有可能,存在一些问题
if (ptr == nullptr)
return;
if (ptr->data_ != val)
{
if (val < ptr->data_)
return erase_elem(val, ptr->left_);
else
return erase_elem(val, ptr->right_);
}
else
{
if (ptr->left_ != 0 && ptr->right_ != 0)
{ // 有两个子节点时
size_t choose = size_ % 2;
// 随机选择,选择1前继结点,0后继结点
// 左子数最大为前继,右子树最小为后继
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
{ // 有一个或没有子节点
auto temp = ptr;
if (ptr->left_ == nullptr)
ptr = ptr->right_;
else
ptr = ptr->left_;
nodeAllocator::destroy(temp);
nodeAllocator::deallocate(temp);
--size_;
}
}
}
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_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_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>
void binary_search_tree<T>::print_inorder_aux(const std::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_);
}
}
}
#endif
binary_search_tree_test.h
#ifndef _BINARY_SEARCH_TREE_TEST_H_
#define _BINARY_SEARCH_TREE_TEST_H_
#include "../p2_STL_Source/stl_binary_search_tree.h"
#include <algorithm>
#include <cassert>
#include <random>
#include <string>
#include <vector>
namespace mySTL {
namespace binarySearchTreeTest {
template<class T>
using tsBst = mySTL::binary_search_tree < T >;
void test01();
void test02();
void test03();
void test04();
void test05();
}
}
#endif
binary_search_tree_test.cpp
#include "stl_binary_search_tree_test.h"
using namespace std;
#include <time.h>
namespace mySTL {
namespace binarySearchTreeTest {
template<class Container1, class Container2>
bool container_equal(const Container1& con1, const Container2& con2) {
auto first1 = con1.cbegin(), last1 = con1.cend();
auto first2 = con2.cbegin(), last2 = con2.cend();
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (*first1 != *first2)
return false;
}
return (first1 == last1 && first2 == last2);
}
void test01()
{
tsBst<std::string> bst;
cout << "tree is empty: " << boolalpha << bst.empty() << endl;
cout << "tree size is : " << bst.size() << endl;
bst.insert("1");
assert(!bst.empty());
cout << "tree is empty: " << boolalpha << bst.empty() << endl;
cout << "tree size is : " << bst.size() << endl;
}
void test02()
{
tsBst<int> bst;
for (auto i = 0; i != 100; ++i)
bst.insert(i);
cout << "tree depth is :" << bst.depth() << endl;
}
void test03()
{
srand(time(NULL));
tsBst<int> bst;
for (auto i = 0; i != 10; ++i)
bst.insert(rand() % 50);
bst.insert(5);
cout << "中序遍历:";
bst.print_inorder();
cout << endl;
cout << "查找5:" << *bst.find(5) << endl;
cout << "查找最小:" << *bst.find_min() << endl;
cout << "查找最大:" << *bst.find_max() << endl;
}
void test04()
{
tsBst<int> bst;
std::vector<int> v;
std::random_device rd;
for (auto i = 0; i != 20; ++i) {
auto r = rd() % 65536;
bst.insert(r);
v.push_back(r);
}
std::sort(v.begin(), v.end());
v.erase(std::unique(v.begin(), v.end()), v.end());
cout << "vector sort: \t";
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
cout << "binary search tree :";
bst.print_inorder();
cout << endl;
cout << "-----------erase---------------" << endl;
for (auto i = 0; i != 5; ++i) {
bst.erase(*bst.cbegin());
v.erase(v.begin());
}
cout << "vector sort: \t";
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
cout << "binary search tree :";
bst.print_inorder();
cout << endl;
}
void test05()
{
std::random_device rd;
tsBst<int> bst;
for (int i = 0; i != 10; ++i)
{
bst.insert(rd() % 100);
}
cout << "binary search tree :";
bst.print_inorder();
cout << endl;
cout << "bst begin node:" << *bst.cbegin() << endl;
cout << "test it++ func:";
for (auto it = bst.cbegin(); it != bst.cend(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
}
}