$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
soft_heap.hh
1 // Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_UTIL_SOFT_HEAP_HH
27 # define MLN_UTIL_SOFT_HEAP_HH
28 
32 
59 # include <mln/core/concept/object.hh>
60 # include <mln/trait/value_.hh>
61 # include <mln/util/tracked_ptr.hh>
62 # include <climits>
63 # include <stack>
64 
65 
66 
67 namespace mln
68 {
69 
70  namespace util
71  {
72 
73 
75  template <typename T>
76  struct ilcell
77  {
79 
80  ilcell();
81  ilcell(const T& key, ilcell_t next = 0);
82 
83  ilcell_t next() const;
84  const T& key() const;
85 
86  void set_next(ilcell_t next);
87  void set_key(const T& key);
88 
89  private:
90  T key_;
91  ilcell_t next_;
92  };
93 
94 
96  template <typename T, typename R>
97  class node
98  {
99 
101 
102  public:
103  node();
104  node(const T& ckey, const R& rank,
105  node<T,R> *next = 0, node<T,R> *child = 0,
106  ilcell_t il = 0, ilcell_t il_tail = 0);
107  ~node();
108 
109  const T& ckey() const;
110  const R& rank() const;
111  node<T,R> * next() const;
112  node<T,R> * child() const;
113  ilcell_t il() const;
114  ilcell_t il_tail() const;
115 
116  void set_il(ilcell_t il);
117  void set_il_tail(ilcell_t il_tail);
118  void set_ckey(const T& ckey);
119  void set_rank(const R& rank);
120  void set_next(node<T,R> * next);
121  void set_child(node<T,R> *child);
122 
123  private:
124  T ckey_;
125  R rank_;
126  node<T,R> *next_;
127  node<T,R> *child_;
128  ilcell_t il_;
129  ilcell_t il_tail_;
130 
131  };
132 
133 
134 
135 
137  template <typename T, typename R>
138  class head
139  {
140  public:
141 
142  head();
143  head(const R& rank, node<T,R> *queue = 0, head<T,R> *next = 0,
144  head<T,R> *prev = 0, head<T,R> *suffix_min = 0);
145  ~head();
146 
147  node<T,R> *queue() const;
148  head<T,R> *next() const;
149  head<T,R> *prev() const;
150  head<T,R> *suffix_min() const;
151  const R& rank() const;
152 
153  void set_queue(node<T,R> *queue);
154  void set_next(head<T,R> *next);
155  void set_prev(head<T,R> *prev);
156  void set_suffix_min(head<T,R> *suffix_min);
157  void set_rank(const R& rank);
158 
159  private:
160  node<T,R> *queue_;
161  head<T,R> *next_;
162  head<T,R> *prev_;
163  head<T,R> *suffix_min_;
164  R rank_;
165 
166  };
167 
168 
169 
170 
176  //
177  template <typename T, typename R>
178  class soft_heap : public Object< soft_heap<T,R> >
179  {
181 
182  public:
183 
185  typedef T element;
186 
187 
194  // FIXME: is it a correct value for r?
195  soft_heap(unsigned r = 20);
197  ~soft_heap();
198 
199 
201  void push(const T& element);
202 
206  void push(soft_heap<T,R>& sh);
207 
210  T pop_front();
211 
213  bool is_valid() const;
214 
216  bool is_empty() const;
217 
219  int nelements() const;
220 
222  void clear();
223 
226  head<T,R> *head_hook_() const;
227 
231  void soft_clear_();
232 
233 
234 
235  private:
238  void meld(node<T,R> *q);
239 
242  void fix_minlist(head<T,R> *h);
243 
246  node<T,R> * sift(node<T,R> *v);
247 
256  template <typename L>
257  void clear_list(L *begin, L *end = 0);
258 
269  template <typename L>
270  void deep_clear_list(L *n);
271 
273  void debug_head_list() const;
274 
276  void println_() const;
277 
278  head<T,R> *header_;
279  head<T,R> *tail_;
280 
282  unsigned r_;
283 
284  int nelements_;
285  };
286 
287 
288 
289 # ifndef MLN_INCLUDE_ONLY
290 
291 
292  /*-------`
293  | ilcell |
294  \-------*/
295 
296 
297  template <typename T>
298  inline
300  {
301  }
302 
303 
304  template <typename T>
305  inline
306  ilcell<T>::ilcell(const T& key, ilcell_t next)
307  : key_(key), next_(next)
308  {
309  }
310 
311 
312  template <typename T>
313  inline
314  typename ilcell<T>::ilcell_t
315  ilcell<T>::next() const
316  {
317  return next_;
318  }
319 
320 
321  template <typename T>
322  inline
323  const T&
324  ilcell<T>::key() const
325  {
326  return key_;
327  }
328 
329 
330  template <typename T>
331  inline
332  void
333  ilcell<T>::set_next(ilcell_t next)
334  {
335  next_ = next;
336  }
337 
338 
339  template <typename T>
340  inline
341  void
342  ilcell<T>::set_key(const T& key)
343  {
344  key_ = key;
345  }
346 
347 
348 
349 
350  /*-----`
351  | node |
352  \-----*/
353 
354 
355  template <typename T, typename R>
356  inline
358  : il_(0), il_tail_(0)
359  {
360  }
361 
362 
363  template <typename T, typename R>
364  inline
365  node<T,R>::node(const T& ckey, const R& rank,
366  node<T,R> *next, node<T,R> *child,
367  ilcell_t il, ilcell_t il_tail)
368  : ckey_(ckey), rank_(rank), next_(next), child_(child),
369  il_(il), il_tail_(il_tail)
370  {
371  }
372 
373 
374  template <typename T, typename R>
375  inline
377  {
378  }
379 
380 
381  template <typename T, typename R>
382  inline
383  const T&
384  node<T,R>::ckey() const
385  {
386  return ckey_;
387  }
388 
389 
390  template <typename T, typename R>
391  inline
392  const R&
393  node<T,R>::rank() const
394  {
395  return rank_;
396  }
397 
398 
399  template <typename T, typename R>
400  inline
401  node<T,R> *
402  node<T,R>::next() const
403  {
404  return next_;
405  }
406 
407 
408  template <typename T, typename R>
409  inline
410  node<T,R> *
411  node<T,R>::child() const
412  {
413  return child_;
414  }
415 
416 
417  template <typename T, typename R>
418  inline
419  typename node<T,R>::ilcell_t
420  node<T,R>::il() const
421  {
422  return il_;
423  }
424 
425 
426  template <typename T, typename R>
427  inline
428  typename node<T,R>::ilcell_t
429  node<T,R>::il_tail() const
430  {
431  return il_tail_;
432  }
433 
434 
435  template <typename T, typename R>
436  inline
437  void
438  node<T,R>::set_il(ilcell_t il)
439  {
440  il_ = il;
441  }
442 
443 
444  template <typename T, typename R>
445  inline
446  void
447  node<T,R>::set_il_tail(ilcell_t il_tail)
448  {
449  il_tail_ = il_tail;
450  }
451 
452 
453  template <typename T, typename R>
454  inline
455  void
456  node<T,R>::set_ckey(const T& ckey)
457  {
458  ckey_ = ckey;
459  }
460 
461 
462  template <typename T, typename R>
463  inline
464  void
465  node<T,R>::set_rank(const R& rank)
466  {
467  rank_ = rank;
468  }
469 
470 
471  template <typename T, typename R>
472  inline
473  void
474  node<T,R>::set_next(node<T,R> * next)
475  {
476  next_ = next;
477  }
478 
479 
480  template <typename T, typename R>
481  inline
482  void
483  node<T,R>::set_child(node<T,R> *child)
484  {
485  child_ = child;
486  }
487 
488 
489 
490 
491  /*-----`
492  | head |
493  \-----*/
494 
495 
496  template <typename T, typename R>
497  inline
499  {
500  }
501 
502 
503  template <typename T, typename R>
504  inline
505  head<T,R>::head(const R& rank, node<T,R> *queue, head<T,R> *next,
506  head<T,R> *prev, head<T,R> *suffix_min)
507  : queue_(queue), next_(next), prev_(prev),
508  suffix_min_(suffix_min), rank_(rank)
509  {
510  }
511 
512 
513  template <typename T, typename R>
514  inline
516  {
517  }
518 
519 
520  template <typename T, typename R>
521  inline
522  node<T,R> *
523  head<T,R>::queue() const
524  {
525  return queue_;
526  }
527 
528 
529  template <typename T, typename R>
530  inline
531  head<T,R> *
532  head<T,R>::next() const
533  {
534  return next_;
535  }
536 
537 
538  template <typename T, typename R>
539  inline
540  head<T,R> *
541  head<T,R>::prev() const
542  {
543  return prev_;
544  }
545 
546 
547  template <typename T, typename R>
548  inline
549  head<T,R> *
550  head<T,R>::suffix_min() const
551  {
552  return suffix_min_;
553  }
554 
555 
556  template <typename T, typename R>
557  inline
558  const R&
559  head<T,R>::rank() const
560  {
561  return rank_;
562  }
563 
564 
565  template <typename T, typename R>
566  inline
567  void
568  head<T,R>::set_queue(node<T,R> *queue)
569  {
570  queue_ = queue;
571  }
572 
573 
574  template <typename T, typename R>
575  inline
576  void
577  head<T,R>::set_next(head<T,R> *next)
578  {
579  next_ = next;
580  }
581 
582 
583  template <typename T, typename R>
584  inline
585  void
586  head<T,R>::set_prev(head<T,R> *prev)
587  {
588  prev_ = prev;
589  }
590 
591 
592  template <typename T, typename R>
593  inline
594  void
595  head<T,R>::set_suffix_min(head<T,R> *suffix_min)
596  {
597  suffix_min_ = suffix_min;
598  }
599 
600 
601  template <typename T, typename R>
602  inline
603  void
604  head<T,R>::set_rank(const R& rank)
605  {
606  rank_ = rank;
607  }
608 
609 
610 
611 
612  /*------------`
613  | soft_heap |
614  \------------*/
615 
616 
617  template <typename T, typename R>
618  inline
619  soft_heap<T,R>::soft_heap(unsigned r)
620  {
621  nelements_ = 0;
622  r_ = r;
623  header_ = new head<T,R>(mln_max(R));
624  tail_ = new head<T,R>(mln_max(R), 0, 0, header_);
625  header_->set_next(tail_);
626  }
627 
628 
629  template <typename T, typename R>
630  inline
632  {
633  head<T,R> *tmp = header_;
634  while (tmp != 0)
635  {
636  deep_clear_list(tmp->queue());
637  tmp = tmp->next();
638  }
639  clear_list(header_, tail_->next());
640  }
641 
642 
643  template <typename T, typename R>
644  inline
645  void
646  soft_heap<T,R>::push(const T& element)
647  {
648  ilcell_t l(new ilcell<T>(element));
649  node<T,R> *q = new node<T,R>(element, 0, 0, 0, l, l);
650  meld(q);
651  ++nelements_;
652  }
653 
654 
655  template <typename T, typename R>
656  inline
657  void
658  soft_heap<T,R>::push(soft_heap<T,R>& psh)
659  {
660  head<T,R> *head = psh.head_hook_();
661  while (head != 0)
662  {
663  if (head->queue() != 0)
664  meld(head->queue());
665  head = head->next();
666  }
667  nelements_ += psh.nelements();
668  psh.soft_clear_();
669  }
670 
671 
672  template <typename T, typename R>
673  inline
674  T
676  {
677  mln_precondition(is_valid());
678 
679  node<T,R> *tmp;
680 
681  T min;
682  int childcount;
683  head<T,R> *h = header_->next()->suffix_min();
684  while (h->queue()->il() == 0)
685  {
686  tmp = h->queue();
687  childcount = 0;
688  while (tmp->next() != 0)
689  {
690  tmp = tmp->next();
691  ++childcount;
692  }
693 
694  if (childcount < h->rank() / 2)
695  {
696  h->prev()->set_next(h->next());
697  h->next()->set_prev(h->prev());
698  fix_minlist(h->prev());
699  tmp = h->queue();
700  while (tmp->next() != 0)
701  {
702  meld(tmp->child());
703  tmp = tmp->next();
704  }
705  //FIXME: is it right?
706  deep_clear_list(h->queue());
707  delete h;
708  }
709  else
710  {
711  h->set_queue(sift(h->queue()));
712  // FIXME: not generic enough.
713  if (h->queue()->ckey() == T::plus_infty())
714  {
715  h->prev()->set_next(h->next());
716  h->next()->set_prev(h->prev());
717 
718  // Remove h and switch to h->prev.
719  head<T,R> *h_bak = h;
720  h = h->prev();
721  deep_clear_list(h_bak->queue());
722  delete h_bak;
723  }
724  fix_minlist(h);
725  }
726  h = header_->next()->suffix_min();
727  }
728 
729  min = h->queue()->il()->key();
730 
731  //Don't need to delete h->queue()->il(). May be used in another node.
732  h->queue()->set_il(h->queue()->il()->next());
733  if (h->queue()->il() == 0)
734  h->queue()->set_il_tail(0);
735 
736  --nelements_;
737  return min;
738  }
739 
740 
741  template <typename T, typename R>
742  inline
743  bool
745  {
746  return header_ != 0 && tail_ != 0;
747  }
748 
749 
750  template <typename T, typename R>
751  inline
752  bool
754  {
755  return nelements_ == 0 ;
756  }
757 
758 
759  template <typename T, typename R>
760  inline
761  int
763  {
764  return nelements_;
765  }
766 
767 
768  template <typename T, typename R>
769  inline
770  void
772  {
773  if (header_->next() == tail_)
774  return;
775 
776  head<T,R> *tohead = header_->next();
777  head<T,R> *prevtail = tail_->prev();
778  prevtail->set_next(0);
779  tohead->set_prev(0);
780  header_->set_next(tail_);
781  tail_->set_prev(header_);
782 
783  head<T,R> *tmp = tohead;
784  while (tmp != 0)
785  {
786  deep_clear_list(tmp->queue());
787  tmp = tmp->next();
788  }
789  clear_list(tohead);
790 
791  nelements_ = 0;
792  }
793 
794 
795  template <typename T, typename R>
796  inline
797  void
799  {
800  clear_list(header_->next(), tail_);
801  header_->set_next(tail_);
802  header_->set_prev(0);
803  tail_->set_next(0);
804  tail_->set_prev(header_);
805  nelements_ = 0;
806  }
807 
808 
809  template <typename T, typename R>
810  inline
811  head<T,R> *
813  {
814  return header_;
815  }
816 
817 
818  template <typename T, typename R>
819  inline
820  void
821  soft_heap<T,R>::meld(node<T,R>* q)
822  {
823  head<T,R> *tohead = header_->next();
824  while (q->rank() > tohead->rank())
825  tohead = tohead->next();
826  head<T,R> *prevhead = tohead->prev();
827 
828  node<T,R> *top, *bottom;
829 
830  while (q->rank() == tohead->rank())
831  {
832  if (util::ord_strict(q->ckey(), tohead->queue()->ckey()))
833  {
834  top = q;
835  bottom = tohead->queue();
836  }
837  else
838  {
839  top = tohead->queue();
840  bottom = q;
841  }
842 
843  q = new node<T,R>(top->ckey(), top->rank() + 1, top, bottom,
844  top->il(), top->il_tail());
845 
846  tohead = tohead->next();
847  }
848 
849  head<T,R> *h;
850  if (prevhead == tohead->prev())
851  {
852  h = new head<T,R>(q->rank(), q, tohead, prevhead);
853  }
854  else
855  {
856  // Do not create a new head.
857  h = prevhead->next();
858 
859  //Discard/delete everything between h and tohead.
860  head<T,R> *head_del = h->next(), *tmp_del;
861  while (head_del != tohead)
862  {
863  tmp_del = head_del->next();
864  delete head_del;
865  head_del = tmp_del;
866  }
867 
868  }
869  h->set_queue(q);
870  h->set_rank(q->rank());
871  h->set_prev(prevhead);
872  h->set_next(tohead);
873 
874  prevhead->set_next(h);
875  tohead->set_prev(h);
876 
877  fix_minlist(h);
878  }
879 
880 
881  template <typename T, typename R>
882  inline
883  void
884  soft_heap<T,R>::fix_minlist(head<T,R> *h)
885  {
886  head<T,R> *tmpmin;
887  if (h->next() == tail_)
888  tmpmin = h;
889  else
890  tmpmin = h->next()->suffix_min();
891 
892  while (h != header_)
893  {
894  if (util::ord_strict(h->queue()->ckey(), tmpmin->queue()->ckey()))
895  tmpmin = h;
896  h->set_suffix_min(tmpmin);
897  h = h->prev();
898  }
899  }
900 
901 
902  template <typename T, typename R>
903  inline
904  node<T,R> *
905  soft_heap<T,R>::sift(node<T,R> *v)
906  {
907  node<T,R> *tmp;
908  // We do not need to free the list since these object are also pointed by
909  // other structs.
910  v->set_il(0);
911  v->set_il_tail(0);
912 
913  if (v->next() == 0 && v->child() == 0)
914  {
915  //FIXME: not generic enough...
916  v->set_ckey(T::plus_infty());
917  return v;
918  }
919  node<T,R> *v_next_bak = v->next();
920  v->set_next(sift(v->next()));
921 
922  // Cleanup possibly removed nodes.
923  while (v_next_bak != v->next())
924  {
925  deep_clear_list(v_next_bak->next());
926  deep_clear_list(v_next_bak->child());
927  tmp = v_next_bak->next();
928  delete v_next_bak;
929  v_next_bak = tmp;
930  }
931 
932  if (util::ord_strict(v->child()->ckey(), v->next()->ckey()))
933  {
934  // Swap child and next.
935  tmp = v->child();
936  v->set_child(v->next());
937  v->set_next(tmp);
938  }
939 
940  v->set_il(v->next()->il());
941  v->set_il_tail(v->next()->il_tail());
942  v->set_ckey(v->next()->ckey());
943 
944  if (v->rank() > r_ && (v->rank() % 2 == 1
945  || v->child()->rank() < static_cast<unsigned>((v->rank() - 1))))
946  {
947  node<T,R> *v_next_bak = v->next();
948  v->set_next(sift(v->next()));
949 
950  // Cleanup possibly removed nodes.
951  while (v_next_bak != v->next())
952  {
953  deep_clear_list(v_next_bak->next());
954  deep_clear_list(v_next_bak->child());
955  tmp = v_next_bak->next();
956  delete v_next_bak;
957  v_next_bak = tmp;
958  }
959 
960  if (util::ord_strict(v->child()->ckey(), v->next()->ckey()))
961  {
962  tmp = v->child();
963  v->set_child(v->next());
964  v->set_next(tmp);
965  }
966 
967  if (v->next()->ckey() != T::plus_infty() && v->next()->il() != 0)
968  {
969  v->next()->il_tail()->set_next(v->il());
970  v->set_il(v->next()->il());
971  if (v->il_tail() == 0)
972  v->set_il_tail(v->next()->il_tail());
973  v->set_ckey(v->next()->ckey());
974  }
975  }
976 
977  if (v->child()->ckey() == T::plus_infty())
978  {
979  if (v->next()->ckey() == T::plus_infty())
980  {
981  // Clear child and next lists.
982  deep_clear_list(v->child());
983  deep_clear_list(v->next());
984 
985  v->set_child(0);
986  v->set_next(0);
987  }
988  else
989  {
990  node<T,R> *next_bak = v->next();
991 
992  // There may be several children, we must clear all of them.
993  deep_clear_list(v->child());
994 
995  v->set_child(v->next()->child());
996  v->set_next(v->next()->next());
997  delete next_bak;
998  }
999  }
1000 
1001  return v;
1002  }
1003 
1004 
1005  template <typename T, typename R>
1006  template <typename L>
1007  inline
1008  void
1009  soft_heap<T,R>::clear_list(L *begin, L *end)
1010  {
1011  L *tmp;
1012  while (begin != end)
1013  {
1014  tmp = begin->next();
1015  delete begin;
1016  begin = tmp;
1017  }
1018  }
1019 
1020 
1021  template <typename T, typename R>
1022  template <typename L>
1023  inline
1024  void
1025  soft_heap<T,R>::deep_clear_list(L *n)
1026  {
1027  L *current_node, *tmp;
1028  std::stack<L *> st;
1029 
1030  st.push(n);
1031  while (!st.empty())
1032  {
1033  current_node = st.top();
1034  st.pop();
1035  while (current_node != 0)
1036  {
1037  if (current_node->child() != 0)
1038  st.push(current_node->child());
1039 
1040  tmp = current_node->next();
1041  delete current_node;
1042 
1043  current_node = tmp;
1044  }
1045  }
1046  }
1047 
1048 
1049  template <typename T, typename R>
1050  inline
1051  void
1052  soft_heap<T,R>::debug_head_list() const
1053  {
1054  head<T,R> *n = header_;
1055  std::cout << "Head list = " << std::endl;
1056  while (n != 0)
1057  {
1058  std::cout << n->id << "(";
1059 
1060  node<T,R> *current_node;
1061  std::stack< node<T,R> *> st;
1062  st.push(n->queue());
1063  while (!st.empty())
1064  {
1065  current_node = st.top();
1066  st.pop();
1067  while (current_node != 0)
1068  {
1069  if (current_node->child() != 0)
1070  st.push(current_node->child());
1071  std::cout << current_node->id << ",";
1072  current_node = current_node->next();
1073  }
1074  }
1075 
1076  std::cout << ") - ";
1077  n = n->next();
1078  }
1079  std::cout << std::endl;
1080  }
1081 
1082 
1083  template <typename T, typename R>
1084  inline
1085  void
1086  soft_heap<T,R>::println_() const
1087  {
1088 
1089  std::cout << "===============" << std::endl;
1090  head<T,R> *head = header_;
1091  while (head != 0)
1092  {
1093  std::cout << "<Head>" << std::endl;
1094  node<T,R> *node = head->queue(), *child;
1095  while (node != 0)
1096  {
1097  std::cout << " <node>" << std::endl;
1098 
1099  ilcell_t il(node->il());
1100  while (il != 0)
1101  {
1102  std::cout << il->item() << std::endl;
1103  il = il->next();
1104  }
1105 
1106  child = node->child();
1107  while (child != 0)
1108  {
1109  std::cout << " <child>" << std::endl;
1110  ilcell_t il(child->il());
1111  while (il != 0)
1112  {
1113  std::cout << il->item() << std::endl;
1114  il = il->next();
1115  }
1116  child = child->child();
1117  std::cout << " </child>" << std::endl;
1118  }
1119  node = node->next();
1120 
1121  std::cout << " </node>" << std::endl;
1122  }
1123  std::cout << "</Head>" << std::endl;
1124  head = head->next();
1125  }
1126  }
1127 
1128 
1129 # endif // ! MLN_INCLUDE_ONLY
1130 
1131 
1132  } // end of namespace mln::util
1133 
1134 } // end of namespace mln
1135 
1136 
1137 #endif // ! MLN_UTIL_SOFT_HEAP_HH