diff --git a/Source/Makefile b/Source/Makefile index 0f0ee63..54543db 100644 --- a/Source/Makefile +++ b/Source/Makefile @@ -21,6 +21,7 @@ check: @bin/deque_demo @bin/list_demo @bin/Rb_tree_test + @bin/set_test clean: @rm -r bin distclean: clean diff --git a/Source/header/set.h b/Source/header/set.h new file mode 100644 index 0000000..4c986ce --- /dev/null +++ b/Source/header/set.h @@ -0,0 +1,162 @@ +/** + * file: set.h + * date: 2018/05/16 + * author: F_TD5X(jhx) + **/ + +#ifndef _CUSTL_SET_H +#define _CUSTL_SET_H + +#include "tree.h" + +namespace custl { + +template , + typename _Alloc = _Key> +class set; + +template +class set { + public: + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; + + private: + typedef _Rb_tree, key_compare, + _Alloc> + _Rep_type; + _Rep_type _M_t; + + public: + typedef typename _Rep_type::const_pointer pointer; + typedef typename _Rep_type::const_pointer const_pointer; + typedef typename _Rep_type::const_reference reference; + typedef typename _Rep_type::const_reference const_reference; + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::allocator_type allocator_type; + set() : _M_t(_Compare(), allocator_type()) {} + explicit set(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) {} + + set(const set<_Key, _Compare, _Alloc>& __x) : _M_t(__x._M_t) {} + set<_Key, _Compare, _Alloc>& operator=( + const set<_Key, _Compare, _Alloc>& __x) { + _M_t = __x._M_t; + return *this; + } + template + set(_InputIterator __first, _InputIterator __last) + : _M_t(_Compare(), allocator_type()) { + _M_t.insert_unique(__first, __last); + } + + template + set(_InputIterator __first, _InputIterator __last, const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) { + _M_t.insert_unique(__first, __last); + } + + key_compare key_comp() const { return _M_t.key_comp(); } + value_compare value_comp() const { return _M_t.key_comp(); } + allocator_type get_allocator() const { return _M_t.get_allocator(); } + + iterator begin() const { return _M_t.begin(); } + iterator end() const { return _M_t.end(); } + //reverse_iterator rbegin() const { return _M_t.rbegin(); } + //reverse_iterator rend() const { return _M_t.rend(); } + bool empty() const { return _M_t.empty(); } + size_type size() const { return _M_t.size(); } + size_type max_size() const { return _M_t.max_size(); } + void swap(set<_Key, _Compare, _Alloc>& __x) { _M_t.swap(__x._M_t); } + + std::pair insert(const value_type& __x) { + std::pair __p = + _M_t.insert_unique(__x); + return std::pair(__p.first, __p.second); + } + iterator insert(iterator __position, const value_type& __x) { + typedef typename _Rep_type::iterator _Rep_iterator; + return _M_t.insert_unique((_Rep_iterator&)__position, __x); + } + template + void insert(_InputIterator __first, _InputIterator __last) { + _M_t.insert_unique(__first, __last); + } + void erase(iterator __position) { + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__position); + } + size_type erase(const key_type& __x) { return _M_t.erase(__x); } + void erase(iterator __first, iterator __last) { + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__first, (_Rep_iterator&)__last); + } + void clear() { _M_t.clear(); } + + iterator find(const key_type& __x) const { return _M_t.find(__x); } + size_type count(const key_type& __x) const { + return _M_t.find(__x) == _M_t.end() ? 0 : 1; + } + iterator lower_bound(const key_type& __x) const { + return _M_t.lower_bound(__x); + } + iterator upper_bound(const key_type& __x) const { + return _M_t.upper_bound(__x); + } + std::pair equal_range(const key_type& __x) const { + return _M_t.equal_range(__x); + } +}; + +template +inline bool operator==(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) { + return __x._M_t == __y._M_t; +} + +template +inline bool operator<(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) { + return __x._M_t < __y._M_t; +} + +template +inline bool operator!=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) { + return !(__x == __y); +} + +template +inline bool operator>(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) { + return __y < __x; +} + +template +inline bool operator<=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) { + return !(__y < __x); +} + +template +inline bool operator>=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) { + return !(__x < __y); +} + +template +inline void swap(set<_Key, _Compare, _Alloc>& __x, + set<_Key, _Compare, _Alloc>& __y) { + __x.swap(__y); +} + +} // namespace custl + +#endif \ No newline at end of file diff --git a/Source/header/tree.h b/Source/header/tree.h index 83f6ded..b2ae0b6 100644 --- a/Source/header/tree.h +++ b/Source/header/tree.h @@ -427,26 +427,26 @@ inline _Rb_tree_node_base* _Rb_tree_rebalance_for_erase( template > class _Rb_tree { - protected: - typedef _Rb_tree_node_base* _Base_ptr; - typedef _Rb_tree_color _Color_type; +protected: + typedef _Rb_tree_node_base* _Base_ptr; + typedef _Rb_tree_color _Color_type; typedef _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc> _Self; - public: - typedef _Key key_type; - typedef _Val value_type; - typedef value_type* pointer; - typedef value_type& reference; - typedef const value_type* const_pointer; - typedef const value_type& const_reference; - typedef _Rb_tree_node<_Val>* _Link_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; +public: + typedef _Key key_type; + typedef _Val value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type* const_pointer; + typedef const value_type& const_reference; + typedef _Rb_tree_node<_Val>* _Link_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; allocator_type get_allocator() const { return allocator_type(); } - protected: +protected: _Link_type _M_header; _Link_type _M_get_node() { return allocator<_Rb_tree_node<_Val>>::allocate(1); @@ -475,7 +475,7 @@ class _Rb_tree { _M_put_node(__p); } - protected: +protected: size_type _M_node_count; _Compare _M_key_compare; @@ -529,16 +529,16 @@ class _Rb_tree { return (_Link_type)_Rb_tree_node_base::_S_maximum(__x); } - public: +public: typedef _Rb_tree_iterator<_Val> iterator; typedef _Rb_tree_const_iterator<_Val> const_iterator; - private: +private: iterator _M_insert(_Base_ptr __x, _Base_ptr __y, const value_type& __v); _Link_type _M_copy(_Link_type __x, _Link_type __p); void _M_erase(_Link_type __x); - public: +public: _Rb_tree() : _M_node_count(0), _M_key_compare() { _M_header = _M_get_node(); _M_empty_initialize(); @@ -570,31 +570,31 @@ class _Rb_tree { _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& operator=( const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x); - private: +private: void _M_empty_initialize() { _S_color(_M_header) = red; _M_root() = nullptr; _M_rightmost() = _M_leftmost() = _M_header; } - public: +public: _Compare key_comp() const { return _M_key_compare; } iterator begin() { return _M_leftmost(); } iterator end() { return _M_header; } const_iterator begin() const { return _M_leftmost(); } const_iterator end() const { return _M_header; } - bool empty() { return _M_node_count == 0; } + bool empty() const { return _M_node_count == 0; } size_type size() const { return _M_node_count; } size_type max_size() const { return size_type(-1); } void swap(_Self& __t) { - swap(_M_header, __t._M_header); - swap(_M_node_count, __t._M_node_count); - swap(_M_key_compare, __t._M_key_compare); + std::swap(_M_header, __t._M_header); + std::swap(_M_node_count, __t._M_node_count); + std::swap(_M_key_compare, __t._M_key_compare); } - public: +public: std::pair insert_unique(const value_type& __x); iterator insert_equal(const value_type& __x); iterator insert_unique(iterator __pos, const value_type& __x); @@ -603,6 +603,10 @@ class _Rb_tree { void insert_unique(const value_type* __first, const value_type* __last); void insert_equal(const_iterator __first, const_iterator __last); void insert_equal(const value_type* __first, const value_type* __last); + template + void insert_unique(_InsertIterator __first, _InsertIterator __last); + template + void insert_equal(_InsertIterator __first, _InsertIterator __last); void erase(iterator __pos); size_type erase(const key_type& __x); @@ -845,25 +849,29 @@ _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_equal( } } -template +template void _Rb_tree<_Key, _Val, _KoV, _Cmp, _Alloc>::insert_equal( const _Val* __first, const _Val* __last) { for (; __first != __last; ++__first) insert_equal(*__first); } -template +template void _Rb_tree<_Key, _Val, _KoV, _Cmp, _Alloc>::insert_equal( const_iterator __first, const_iterator __last) { for (; __first != __last; ++__first) insert_equal(*__first); } -template +template void _Rb_tree<_Key, _Val, _KoV, _Cmp, _Alloc>::insert_unique( const _Val* __first, const _Val* __last) { for (; __first != __last; ++__first) insert_unique(*__first); } -template +template void _Rb_tree<_Key, _Val, _KoV, _Cmp, _Alloc>::insert_unique( const_iterator __first, const_iterator __last) { for (; __first != __last; ++__first) insert_unique(*__first); @@ -891,7 +899,8 @@ _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::erase(const _Key& __x) { return __n; } -template +template typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Link_type _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_M_copy(_Link_type __x, _Link_type __p) { @@ -1073,7 +1082,8 @@ _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::equal_range( return std::pair(lower_bound(__k), upper_bound(__k)); } -template +template inline std::pair< typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::const_iterator, typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::const_iterator> @@ -1129,6 +1139,22 @@ bool _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::__verify() const { return true; } +template +template +void _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique( + _II __first, _II __last) { + for (; __first != __last; ++__first) insert_unique(*__first); +} + +template +template +void _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_equal( + _II __first, _II __last) { + for (; __first != __last; ++__first) insert_equal(*__first); +} + template > struct rb_tree : public _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc> { diff --git a/Source/test/Rb_tree_test.cpp b/Source/test/Rb_tree_test.cpp index 290be0e..5dff939 100644 --- a/Source/test/Rb_tree_test.cpp +++ b/Source/test/Rb_tree_test.cpp @@ -37,6 +37,8 @@ int main() { custl::_Rb_tree, std::less>::iterator it = tree.begin(); for (int i = 1; it != tree.end(); ++it, ++i) assert(*it == i); + assert(*(++tree.lower_bound(2)) == 3); + assert(*tree.upper_bound(2) == 3); // Cleaer test tree.clear(); @@ -74,6 +76,7 @@ int main() { // Structure verify assert(tree.__verify()); + tree.clear(); // copy test custl::_Rb_tree, std::less> t1; @@ -96,5 +99,8 @@ int main() { t4.insert_unique(Node(i)); assert((*(++t4.begin())).a == 2); + //swap test + t1.swap(tree); + std::cout << "Rb tree Unit test passed" << std::endl; } diff --git a/Source/test/set_test.cpp b/Source/test/set_test.cpp new file mode 100644 index 0000000..417bb21 --- /dev/null +++ b/Source/test/set_test.cpp @@ -0,0 +1,40 @@ +/** + * file: set_test.cpp + * date: 2018-05-16 + * author: F_TD5X(jhx) + **/ + +#include +#include +#include + +#include "set.h" + +int main() { + // test 1 default construct, insert and find + custl::set s1; + assert(s1.empty()); + std::cout << s1.max_size() << std::endl; + for (int i = 0; i < 10; i++) s1.insert(i); + assert(*s1.begin() == 0); + assert(s1.size() == 10); + assert(s1.lower_bound(0) == s1.begin()); + assert(s1.lower_bound(10) == s1.end()); + assert(*s1.upper_bound(8) == 9); + s1.insert(1); + assert(s1.size() == 10); + s1.clear(); + assert(s1.empty()); + + // test 2 copy construct + for (int i = 0; i < 10; i++) s1.insert(i); + custl::set s2(s1.begin(), s1.end()); + assert(s2.size() == 10); + custl::set> s3(s1.begin(), s1.end(), + std::greater()); + assert(*s3.begin() == 9); + // test swap + swap(s1,s2); + + std::cout << "Set test passed" << std::endl; +}