SHOGUN  v2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Set.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 2012 Evgeniy Andreev (gsomix)
8  *
9  * Copyright (C) 2012 Evgeniy Andreev (gsomix)
10  */
11 
12 #ifndef _SET_H_
13 #define _SET_H_
14 
15 #include <shogun/base/SGObject.h>
16 #include <shogun/lib/common.h>
17 #include <shogun/lib/Hash.h>
18 #include <shogun/base/DynArray.h>
19 
20 #include <cstdio>
21 
22 namespace shogun
23 {
24 
25 #ifndef DOXYGEN_SHOULD_SKIP_THIS
26 
27 template<class T> struct CSetNode
28 {
30  int32_t index;
31 
33  bool free;
34 
36  T element;
37 
39  CSetNode<T> *left;
40 
42  CSetNode<T> *right;
43 };
44 #endif
45 
49 template<class T> class CSet: public CSGObject
50 {
51 public:
53  CSet(int32_t size=41, int32_t reserved=128, bool tracable=true)
54  {
55  hash_size=size;
56  free_index=0;
57  num_elements=0;
58  use_sg_mallocs=tracable;
59 
60  if (use_sg_mallocs)
61  hash_array=SG_CALLOC(CSetNode<T>*, size);
62  else
63  hash_array=(CSetNode<T>**) calloc(size, sizeof(CSetNode<T>*));
64 
65  for (int32_t i=0; i<size; i++)
66  {
67  hash_array[i]=NULL;
68  }
69 
70  array=new DynArray<CSetNode<T>* >(reserved, tracable);
71  }
72 
74  virtual ~CSet()
75  {
76  if (array!=NULL)
77  {
78  for(int32_t i=0; i<array->get_num_elements(); i++)
79  {
80  if (array->get_element(i)!=NULL)
81  {
82  if (use_sg_mallocs)
84  else
85  free(array->get_element(i));
86  }
87  }
88  delete array;
89  }
90 
91  if (hash_array!=NULL)
92  {
93  if (use_sg_mallocs)
95  else
96  free(hash_array);
97  }
98  }
99 
101  virtual const char* get_name() const { return "Set"; }
102 
107  void add(const T& element)
108  {
109  int32_t index=hash(element);
110  if (chain_search(index, element)==NULL)
111  {
112  insert_key(index, element);
113  num_elements++;
114  }
115  }
116 
121  bool contains(const T& element)
122  {
123  int32_t index=hash(element);
124  if (chain_search(index, element)!=NULL)
125  return true;
126 
127  return false;
128  }
129 
134  void remove(const T& element)
135  {
136  int32_t index=hash(element);
137  CSetNode<T>* result=chain_search(index, element);
138 
139  if (result!=NULL)
140  {
141  delete_key(index, result);
142  num_elements--;
143  }
144  }
145 
151  int32_t index_of(const T& element)
152  {
153  int32_t index=hash(element);
154  CSetNode<T>* result=chain_search(index, element);
155 
156  if (result!=NULL)
157  return result->index;
158 
159  return -1;
160  }
161 
166  int32_t get_num_elements() const
167  {
168  return num_elements;
169  }
170 
175  int32_t get_array_size() const
176  {
177  return array->get_num_elements();
178  }
179 
187  T* get_element_ptr(int32_t index)
188  {
189  if (array->get_element(index)!=NULL)
190  return &(array->get_element(index)->element);
191  return NULL;
192  }
193 
201  CSetNode<T>* get_node_ptr(int32_t index)
202  {
203  return array->get_element(index);
204  }
205 
207  CSetNode<T>** get_array()
208  {
209  return array->get_array();
210  }
211 
212 private:
216  int32_t hash(const T& element)
217  {
218  return CHash::MurmurHash3((uint8_t*)(&element), sizeof(element), 0xDEADBEEF) % hash_size;
219  }
220 
222  bool is_free(CSetNode<T>* node)
223  {
224  if (node->free==true)
225  return true;
226 
227  return false;
228  }
229 
231  CSetNode<T>* chain_search(int32_t index, const T& element)
232  {
233  if (hash_array[index]==NULL)
234  {
235  return NULL;
236  }
237  else
238  {
239  CSetNode<T>* current=hash_array[index];
240 
241  do // iterating all items in the list
242  {
243  if (current->element==element)
244  return current; // it's a search key
245 
246  current=current->right;
247 
248  } while (current!=NULL);
249 
250  return NULL;
251  }
252  }
253 
255  void insert_key(int32_t index, const T& element)
256  {
257  int32_t new_index;
258  CSetNode<T>* new_node;
259 
261  {
262  // init new node
263  if (use_sg_mallocs)
264  new_node=SG_CALLOC(CSetNode<T>, 1);
265  else
266  new_node=(CSetNode<T>*) calloc(1, sizeof(CSetNode<T>));
267 
268  array->append_element(new_node);
269 
270  new_index=free_index;
271  free_index++;
272  }
273  else
274  {
275  new_node=array->get_element(free_index);
276  ASSERT(is_free(new_node));
277 
278  new_index=free_index;
279  free_index=new_node->index;
280  }
281 
282  new_node->index=new_index;
283  new_node->free=false;
284  new_node->element=element;
285  new_node->left=NULL;
286  new_node->right=NULL;
287 
288  // add new node in start of list
289  if (hash_array[index]==NULL)
290  {
291  hash_array[index]=new_node;
292  }
293  else
294  {
295  hash_array[index]->left=new_node;
296  new_node->right=hash_array[index];
297 
298  hash_array[index]=new_node;
299  }
300  }
301 
303  void delete_key(int32_t index, CSetNode<T>* node)
304  {
305  int32_t temp=0;
306 
307  if (node==NULL)
308  return;
309 
310  if (node->right!=NULL)
311  node->right->left = node->left;
312 
313  if (node->left!=NULL)
314  node->left->right = node->right;
315  else
316  hash_array[index] = node->right;
317 
318  temp=node->index;
319 
320  node->index=free_index;
321  node->free=true;
322  node->left=NULL;
323  node->right=NULL;
324 
325  free_index=temp;
326  }
327 
328 
329 protected:
332 
334  int32_t hash_size;
335 
337  int32_t free_index;
338 
340  int32_t num_elements;
341 
343  CSetNode<T>** hash_array;
344 
347 };
348 
349 }
350 
351 #endif /* _MAP_H_ */

SHOGUN Machine Learning Toolbox - Documentation