tinystl实现(第二十二步:二叉搜索树实现)

39 篇文章 4 订阅
28 篇文章 36 订阅

经过长时间的学习终于可以开始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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值