The feature of set is that all elements are automatically sorted according to the key value, the set element does not have the real value (value) and the key value (key) as well as the map, the key value of the set is the real value, and the real value is the key value. Set does not allow two elements to have the same key value. The value of a set element cannot be modified by an iterator.
The only difference between multiset and set is that Multiset allows key values to be duplicated.
We use the red-black tree as the underlying data structure of set and multiset, and the implementation of set and Multiset is completely a layer of interface encapsulated on the basis of the red-black tree, and all set and multiset operations call the red-black-tree API instead. For STL red-black Tree implementation, please visit: STL simple red-black tree implementation
The program I wrote with VS2013 (GitHub), the set and multiset versions of the code is located in cghstL/ version / Cghstl-0.4.2.rar
In STL, the following files are required for both the set and the bottom of the multiset:
1. GlobalConstruct.h, construction and destructor files, located in cghstl/allocator/cghallocator /
2. CghAlloc.h, Space configurator file, located in cghstl/allocator/cghallocator/
3. Rb_tree.h, implementation of the red and black tree, located in cghstL/associative containers/ Rb-tree/
Set implementation file CghSet.h, located at cghstL/associative containers/ cghset/
Set test file Test_cghset.cpp, located at cghstL/test/
Multiset implementation file CghMultiset.h, located cghstL/associative containers / Cghmultiset /
Multiset test File Test_cghmultiset.cpp, located in cghstL/Test/
1. Construction and destruction
Look first, globalConstruct.h. constructor file
/******************************************************************** Copyright (c) Chen gonghao* all Rights reserved.** [email protected]** function: Implementation code for global construction and destruction ************************************************** /#include "stdafx.h" #include <new.h> #include <type_traits> #ifndef _cgh_global_ Construct_#define _cgh_global_construct_namespace cgh{#pragma region Unified tectonic destructor Template<class T1, class t2> inline void construct (t1* p, const t2& value) {new (P) T1 (value);} Template<class t>inline void Destroy (t* pointer) {pointer->~t ();} Template<class forwarditerator>inline void Destroy (ForwardIterator first, ForwardIterator last) {// It was supposed to be here. Using the feature extractor (traits programming technique) to determine whether an element is non-trivial//non-trivial element can directly free memory//trivial element to do call destructor and then free memory for (; first < Last ++first) Destroy (&*first);} #pragma endregion} #endif
In accordance with the STL interface specification, the correct order is to allocate memory first and then construct the element. The implementation of the constructor takes the form of placement new, and for the sake of simplification, I call the destructor directly to destroy the element, and in the case of efficiency, it is generally judged whether the element is a non-trivial type, and the elements of non-trivial can directly free memory. It can be understood that non-trivial are all allocated on the stack, without our concern, the program is automatically recycled, trivial elements to be allocated on the heap, need to manually call the destructor to destroy, and then free memory.
2. Space Configurator
CghAlloc.h is a space configurator file, and the Space Configurator is responsible for memory application and recycling.
/******************************************************************** Copyright (c) Chen gonghao* All rights reserved.** [email protected]** function: implementation code for Cghallocator Space Configurator ************************************************** /#ifndef _cgh_alloc_#define _cgh_alloc_#include <new> #include <cstddef> #include < cstdlib> #include <climits> #include <iostream>namespace cgh{#pragma region memory allocation and deallocation functions, element Construction and destructors// Memory allocation Template<class t>inline t* _allocate (ptrdiff_t size, t*) {set_new_handler (0); t* tmp = (t*) (:: Operator new ((size_t) (Size * sizeof (T))), if (TMP = = 0) {Std::cerr << "out of Memory" << std::e Ndl;exit (1);} return TMP;} Memory free template<class t>inline void _deallocate (t* buffer) {:: operator delete (buffer);} Element constructs Template<class T1, class t2>inline void _construct (t1* p, const t2& value) {new (P) T1 (value);} Element destructor Template<class t>inline void _destroy (t* ptr) {ptr->~t ();} #pragma endregion#pragma Region CghalloImplementation of the Cator Space Configurator template<class t>class cghallocator{public:typedef tvalue_type;typedef T*pointer;typedef const T* Const_pointer;typedef t&reference;typedef Const T&CONST_REFERENCE;TYPEDEF size_tsize_type;typedef ptrdiff_ Tdifference_type;template<class u>struct rebind{typedef cghallocator<u> Other;}; Static pointer allocate (size_type N, const void* hint = 0) {return _allocate ((Difference_type) n, (pointer) 0);} static void Deallocate (pointer p, Size_type N) {_deallocate (P);} static void Deallocate (void* p) {_deallocate (P);} void construct (pointer p, const t& value) {_construct (P, value);} void Destroy (pointer p) {_destroy (P);} Pointer address (reference x) {return (pointer) &x;} Const_pointer const_address (Const_reference x) {return (Const_pointer) &x;} Size_type max_size () Const{return size_type (uint_max/sizeof (T));}}; #pragma endregion#pragma region encapsulates the STL standard Space Configurator Interface Template<class T, class Alloc = Cghallocator<t>>class simple _alloc{public:static t* Allocate (SIze_t N) {return 0 = = n? 0: (t*) Alloc::allocate (n*sizeof (t));} Static t* Allocate (void) {return (t*) alloc::allocate (sizeof (T)); static void Deallocate (t* p, size_t N) {if (0! = N) Alloc::d eallocate (P, n*sizeof (T));} static void Deallocate (void* p) {Alloc::d eallocate (P);}}; #pragma endregion} #endif
Classcghallocator is the definition of the Space Configurator class, the main four functions are as follows: Allocate function allocates memory, deallocate function frees memory, construct constructs elements, destroy destructors. These four functions are eventually implemented by invoking the four inline functions of _allocate, _deallocate, _construct, _destroy.
We write our own space Configurator must encapsulate a layer of STL standard interface,
TEMPLATE<CLASST, class Alloc = Cghallocator<t>>classsimple_alloc
3. Implementation of red and black trees
Red black tree as a set of the underlying data structure, its implementation is more complex, here does not unfold, interested children shoes please step another blog: stl Simple Red-black tree implementation
Implementation of the 4.cghSet
The internal structure of the Cghset can be divided into the following sections:
1. A bunch of TypeDef, note that set of the underlying data structure is red black tree, Cghset own no member variables, all operations are to call the red and black tree API, the implementation of the STL red and Black tree, please move: STL Simple red black tree implementation;
2. Structure and destructor of Cghset;
3. APIs provided to the user
Cghset code comments have been written in detail, children's shoes can refer to the internal structure of Cghset to master the framework of the iterator, with comments to understand how Cghset works.
CghSet.h
/******************************************************************** Copyright (c) Chen gonghao* All rights reserved.** [email protected]** File contents: Cghset implementation ************************************************************* /#ifndef _cgh_set_#define _cgh_set_#include "globalConstruct.h" #include "cghAlloc.h" #include "rb_tree.h" Namespace cgh{/* By default in ascending order */template<class key, class compare = Std::less<key>, class Alloc = cghallocator< Key>>class cghset{#pragma region typedefprivate:typedef keykey_type;typedef keyvalue_type;typedef Compare Key_ Compare;typedef Compare Value_compare;typedefcgh_rb_tree<key_type, Value_type, Std::identity<value_type> Key_compare, Alloc>rep_type;rep_type T;public:typedef TypeName Rep_type::const_pointerpointer;typedef TypeName Rep_type::const_pointerconst_pointer;typedef TypeName Rep_type::const_referencereference;typedef TypeName Rep_type :: Const_referenceconst_ference;typedef TypeName Rep_type::iteratoriterator;typedeF TypeName Rep_type::size_typesize_type;typedef TypeName Rep_type::d ifference_typedifference_type; #pragma endregion #pragma region constructor Public:cghset (): t (compare ()) {}cghset (const Cghset<key, compare, alloc>&x): t (x.t) {} Cghset<key, Compare, alloc>& operator= (const Cghset<key, compare, alloc>&x) {t = X.t;return *this;} #pragma endregion#pragma region is provided to the user api/* return key comparison function */key_compare Key_comp () const{return T.key_comp ();} /* return value comparison function */value_compare Value_comp () const{return T.key_comp ();} /* Returns an iterator that specifies the first element of set */iterator begin () {return t.begin ();} /* Returns an iterator that specifies the last element of the set */iterator end () {return t.end ();} /* Whether the set is empty */bool empty () const{return T.empty ();} /* Set size */size_type size () const{return t.size ();} /* Set Maximum capacity */size_type max_size () const{return t.max_size ();} /* insert element into set */STD::p air<iterator, bool> Insert (const value_type&x) {std::p air<typename rep_type:: Iterator, bool> p = t.insert_unique (x); return std::p air<iterator, bool> (P.first, P.second);} /* Returns an iterator that points to the element to find if not found, returns End*/iterator find (const key_type&x) {return t.find (x);} #pragma endregion};} #endif
Implementation of the 5.multiset
The internal structure of the Cghmultiset can be divided into the following sections:
1. A bunch of TypeDef, note that Multiset's underlying data structure is red black tree, multiset own no member variables, all operations are to call the red and black tree API, the implementation of the STL red and Black tree, please move: STL Simple red black tree implementation;
2. Structure and destructor of Cghmultiset;
3. APIs provided to the user
CghMultiset.h
/******************************************************************** Copyright (c) Chen gonghao* All rights reserved.** [email protected]** File contents: Cghmultiset implementation ******************************************************** /#ifndef _cgh_multi_set_#define _cgh_multi_set_#include "globalConstruct.h" #include "cghAlloc.h" #include "Rb_tree.h" namespace Cgh{template<class key, class compare = Std::less<key>, class Alloc = cghallocator<key& gt;>/* by default in ascending order */class cghmultiset{#pragma region typedefprivate:typedef Keykey_type;typedef keyvalue_type; typedef compare KEY_COMPARE;TYPEDEF Compare Value_compare;typedefcgh_rb_tree<key_type, Value_type, std::identity <value_type>, Key_compare, Alloc>rep_type;rep_type T;public:typedef TypeName Rep_type::const_ Pointerpointer;typedef TypeName Rep_type::const_pointerconst_pointer;typedef TypeName Rep_type::const_ Referencereference;typedef TypeName Rep_type::const_referenceconst_ference;typedef TypeName Rep_type::iTeratoriterator;typedef TypeName Rep_type::size_typesize_type;typedef TypeName Rep_type::d ifference_typedifference _type; #pragma endregion#pragma region constructor Public:cghmultiset (): t (compare ()) {}cghmultiset (const Cghmultiset<key, Compare, Alloc>&x): t (x.t) {}cghmultiset<key, compare, alloc>& operator= (const Cghmultiset<key, Compare, alloc>&x) {t = X.t;return *this;} The api/* return key comparison function that is provided to the user by the #pragma endregion#pragma region */key_compare Key_comp () const{return T.key_comp ();} /* return value comparison function */value_compare Value_comp () const{return T.key_comp ();} /* Returns an iterator specifying the first element of Cghmultiset */iterator begin () {return t.begin ();} /* Returns an iterator specifying the last element of Cghmultiset */iterator end () {return t.end ();} /* Cghmultiset is null */bool empty () const{return T.empty ();} /* Cghmultiset sizes */size_type size () const{return t.size ();} /* Cghmultiset Maximum capacity */size_type max_size () const{return t.max_size ();} /* Insert element into Cghmultiset */iterator Insert (const value_type&x) {//std::p air<typename rep_type::iterator, BOOL> P = t.insert_equal (x); return t.insert_equal (x);} /* Returns an iterator that points to the element to find if not found, returns End*/iterator find (const key_type&x) {return t.find (x);} #pragma endregion};} #endif
6. Test 6.1 Test Cghset
The main contents of the test link are explained in the comments
Test_cghset.cpp
/******************************************************************** Copyright (c) Chen gonghao* All rights reserved.** [email protected]** file contents: Cghset Test ************************************************************* /#include "stdafx.h" #include "cghSet.h" using Namespace::std;int _tmain (int argc, _tchar* argv[]) {using namespace: :cgh;cghset<int> Test;test.insert (3); Test.insert (2); Test.insert (5); Test.insert (4); Test.insert (1); Test.insert (5); Std::cout << Endl << "disorderly insert: 3,2,5,4,1,5" << endl << endl;std::cout << " Results sorted by Set container: "<< endl << endl;for (cghset<int>::iterator iter = Test.begin (); ITER! = Test.end (); ++ite R) {std::cout << *iter << ",";} Std::cout << Endl << endl << "Set does not allow the insertion of duplicate key values, we insert 5 two times, but in the output, 5 appear once"; Std::cout << Endl << Endl << "----------------------"; std::cout << Endl << endl << "Use the Find function to find elements with a value of 3 in Set" << Endl << Endl;cghset<int>::iterator iter = Test.find (3); if (iter! = Test.end ()) {std::cout << "iter! = Test.end (), found, *iter =" << * ITER;} Std::cout << Endl << endl << "----------------------"; std::cout << Endl << endl << "use The Find function is looking for elements with a value of 6 in Set "<< Endl << endl;cghset<int>::iterator iter2 = test.find (6); if (iter2 = = Test.end () {std::cout << "iter2 = = Test.end (), not found";} Std::cout << Endl << endl << "----------------------"; std::cout << Endl << endl << "se Size of T: "<< test.size () << Endl << endl;system (" pause "); return 0;}
The test results are as shown
6.2 Test Cghmultiset
The main contents of the test link are explained in the comments
Test_cghmultiset.cpp
/******************************************************************** Copyright (c) Chen gonghao* All rights reserved.** [email protected]** file contents: Cghmultiset Test ******************************************************** /#include "stdafx.h" #include "cghMultiset.h" using Namespace::std;int _tmain (int argc, _tchar* argv[]) {using Namespace::cgh;cghmultiset<int> Test;test.insert (3); Test.insert (2); Test.insert (5); Test.insert (4); Test.insert (1); Test.insert (5), std::cout << Endl << "disorderly insert: 3,2,5,4,1,5" << Endl << endl;std:: cout << "sorted by Set Container:" << endl << endl;for (cghmultiset<int>::iterator iter = Test.begin (); ITER ! = Test.end (); ++iter) {std::cout << *iter << ",";} Std::cout << Endl << endl << multiset allow insertion of duplicate key values, we insert 5 two times, and 5 appear two times in the output; Std::cout << Endl <& Lt Endl << "----------------------"; std::cout << Endl << endl << "Use the Find function to find elements with a value of 3 in Set" << Endl << Endl;cghmultiset<int>::iterator iter = Test.find (3); if (iter! = Test.end ()) {std::cout << "iter! = TEST.E nd (), found, *iter = "<< *iter;} Std::cout << Endl << endl << "----------------------"; std::cout << Endl << endl << "use The Find function is looking for elements with a value of 6 in Set "<< Endl << endl;cghmultiset<int>::iterator iter2 = test.find (6); if (iter2 = = Test.end ()) {std::cout << "iter2 = = Test.end (), not found";} Std::cout << Endl << endl << "----------------------"; std::cout << Endl << endl << "se Size of T: "<< test.size () << Endl << endl;system (" pause "); return 0;}
The test results are as shown
Implementation of 11.STL simple set and Multiset