(第十步) STL: stl_binary_search_tree容器实现

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;
		}

	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值