tpl_sort_utils.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef TPL_SORT_UTILS_H
00045 # define TPL_SORT_UTILS_H
00046 
00047 # include <ahPair.H>
00048 # include <tpl_arrayStack.H>
00049 # include <tpl_dynArray.H>
00050 # include <tpl_dynDlist.H>
00051 
00052 namespace Aleph 
00053 {
00054 extern const int Insertion_Threshold;
00055 
00056 extern const int Not_Found;
00057 
00080     template <typename T, class Compare>
00081 void selection_sort(T a[], const size_t & n)
00082 {
00083   int i,j, min;
00084 
00085   for (i = 0; i < n - 1; ++i)
00086     {
00087       for (min = i, j = i + 1; j < n; ++j)
00088         if (Compare () (a[j], a[min]))
00089           min = j;
00090       if (Compare () (a[min], a[i]))
00091         Aleph::swap(a[min], a[i]);
00092     }
00093 }
00094 
00095     template <typename T>
00096 void selection_sort(T a[], const size_t & n)
00097 {
00098   selection_sort <T, Aleph::less<T> > (a, n);
00099 }
00100 
00118     template <class Compare>
00119 Dlink * search_min(Dlink & list)
00120 {
00121   typename Dlink::Iterator it(list);
00122 
00123   Dlink * min = it.get_current();
00124   
00125   for (it.next(); it.has_current(); it.next())
00126     {
00127       Dlink * curr = it.get_current();
00128 
00129       if (Compare () (curr, min))
00130         min = curr;
00131     } 
00132 
00133   return min;
00134 }
00150     template <class Compare>
00151 void selection_sort(Dlink & list)
00152 {
00153   Dlink aux;
00154 
00155   while (not list.is_empty())
00156     {
00157       Dlink * min = search_min<Compare>(list); // menor de list
00158 
00159       min->del(); // saque menor de list
00160       aux.append(min); // insértelo ordenado en aux;
00161     }
00162 
00163   list.swap(&aux);
00164 }
00165     template <typename T, class Compare>
00166 class Compare_Dnode
00167 {
00168 
00169 public:
00170 
00171   bool operator () (Dlink * l1, Dlink * l2) const
00172   {
00173     Dnode<T> * n1 = static_cast<Dnode<T>*>(l1);
00174     Dnode<T> * n2 = static_cast<Dnode<T>*>(l2);
00175 
00176 
00177     I(n1 == l1 and n2 == l2);
00178 
00179     return Compare () (n1->get_data(), n2->get_data());
00180   }
00181 };
00203     template <typename T, class Compare>
00204 void selection_sort(Dnode<T> & list)
00205 {
00206   selection_sort < Compare_Dnode<T, Compare> > (list);
00207 }
00208     template <typename T>
00209 void selection_sort(Dnode<T> & list)
00210 {
00211   selection_sort < T, Aleph::less<T> > (list);
00212 }
00235     template <typename T, class Equal> inline
00236 int sequential_search(T a[], const T & x, const int & l, const int & r)
00237 {
00238   for (int i = l; i <= r; i++)
00239     if (Equal () (a[i], x))
00240       return i;
00241 
00242   return Not_Found;
00243 }
00280     template <typename T, class Equal> inline
00281 int sequential_search(DynArray<T> & a, 
00282                       const T & x, const int & l, const int & r)
00283 {
00284   for (int i = l; i <= r; i++)
00285     if (a.exist(i))
00286       if (Equal () (static_cast<const T&>(a.access(i)), x))
00287         return i;
00288 
00289   return -1;
00290 }
00291     template <typename T> inline 
00292 int sequential_search(T a[], const T & x, const int & l, const int & r)
00293 {
00294   return sequential_search<T, equal_to<T> > (a, x, l, r);
00295 }
00296 
00297     template <typename T> inline
00298 int sequential_search(DynArray<T> & a, 
00299                       const T & x, const int & l, const int & r)
00300 {
00301   return sequential_search<T, equal_to<T> > (a, x, l, r);
00302 }
00325     template <typename T, class Equal> inline
00326 Dnode<T> * sequential_search(Dnode<T> & list, const T & x)
00327 {
00328   for (typename Dnode<T>::Iterator it(list); it.has_current(); it.next())
00329     {
00330       Dnode<T> * curr = it.get_current();
00331 
00332       if (Equal () (curr->get_data(), x))
00333         return curr;
00334     }
00335 
00336   return NULL;
00337 }
00338     template <typename T> inline
00339 Dnode<T> * sequential_search(Dnode<T> & list, const T & x)
00340 {
00341   return sequential_search<T, Aleph::equal_to<T> > (list, x);
00342 }
00365     template <typename T, class Equal> inline
00366 T * sequential_search(DynDlist<T> & list, const T & x)
00367 {
00368   Dnode<T> * ret = 
00369     sequential_search<T, Equal > (static_cast<Dnode<T>&>(list), x);
00370 
00371   return ret != NULL ? &ret->get_data() : NULL;
00372 }
00373     template <typename T> inline
00374 T * sequential_search(DynDlist<T> & list, const T & x)
00375 {
00376   return sequential_search<T, Aleph::equal_to<T> > (list, x);
00377 }
00393     template <typename T, class Compare> inline
00394 int search_extreme(T a[], const int & l, const int & r)
00395 {
00396   T extreme_index = l;
00397 
00398   for (int i = l + 1; i <= r; i++)
00399     if (Compare () (a[i], a[extreme_index])) // ¿se ve un nuevo menor?
00400       extreme_index = i; // sí
00401   
00402   return extreme_index;
00403 }
00404     template <typename T> inline
00405 int search_extreme(T a[], const int & l, const int & r)
00406 {
00407   return search_extreme<T, Aleph::less<T> > (a, l, r);
00408 }
00413     template <typename T> inline
00414 int search_min(T a[], const int & l, const int & r)
00415 {
00416   return search_extreme<T, Aleph::less<T> > (a, l, r);
00417 }
00418 
00423     template <typename T> inline
00424 int search_max(T a[], const int & l, const int & r)
00425 {
00426   return search_extreme<T, Aleph::greater<T> > (a, l, r);
00427 }
00442     template <class Compare> inline
00443 Dlink * search_extreme(Dlink * list)
00444 {
00445   typename Dlink::Iterator it(*list);
00446 
00447   Dlink * curr_min  = it.get_current();
00448 
00449   for (it.next(); it.has_current(); it.next())
00450     {
00451       Dlink curr = it.get_current();
00452 
00453       if (Compare () (curr, curr_min))
00454         curr_min = curr;
00455     }
00456   return curr_min;
00457 }
00458     template <typename T, class Compare> inline 
00459 Dnode<T> * search_extreme(Dnode<T> & list)
00460 {
00461   Dlink * ret= search_extreme<Compare_Dnode<T, Compare> > (list);
00462 
00463   return static_cast<Dnode<T>*>(ret);
00464 }
00465 
00466 
00467     template <typename T> inline 
00468 Dnode<T> * search_extreme(Dnode<T> & list)
00469 {
00470   return search_extreme<T, Aleph::less<T> > (list);
00471 }
00472 
00487     template <typename T, class Compare> inline
00488 T * search_extreme(DynDlist<T> & list)
00489 {
00490   Dnode<T> * ret = 
00491     search_extreme <T, Compare> (static_cast<Dnode<T>&>(list)); 
00492 
00493   return ret != NULL ? &(ret->get_data()) : NULL;
00494 }
00495 
00496     template <typename T> inline
00497 T * search_extreme(DynDlist<T> & list)
00498 {
00499   return search_extreme<T, Aleph::less<T> > (list);
00500 }
00501 
00506     template <typename T> inline
00507 T * search_min(DynDlist<T> & list)
00508 {
00509   return search_extreme<T, Aleph::less<T> > (list);
00510 }
00511 
00516     template <typename T> inline
00517 T * search_max(DynDlist<T> & list)
00518 {
00519   return search_extreme<T, Aleph::greater<T> > (list);
00520 }
00547     template <typename T, class Compare>
00548 void insertion_sort(T a[], const size_t & l, const size_t & r)
00549 {
00550   int i,j;
00551   T tmp;
00552 
00553   for (i = l; i <= r; ++i)
00554     {
00555       tmp = a[i]; // memorice a[i], pues será sobre escrito
00556       for (j = i; j > l and Compare() (tmp, a[j - 1]); --j)
00557         a[j] = a[j - 1]; // desplazar hacia la derecha
00558       a[j] = tmp; // inserte tmp en la brecha
00559     }
00560 }
00561     template <typename T>
00562 void insertion_sort(T a[], const size_t & l, const size_t & r)
00563 {
00564   insertion_sort <T, Aleph::less<T> > (a, l, r);
00565 }
00578     template <class Compare>
00579 void insert_sorted(Dlink & list, Dlink * p)
00580 {
00581   typename Dlink::Iterator it(list); 
00582 
00583   while (it.has_current() and Compare () (it.get_current(), p)) 
00584     it.next();
00585 
00586   if (it.has_current())
00587     it.get_current()->append(p); // insertar a la derecha de current
00588   else
00589     list.append(p); 
00590 }
00602     template <class Compare>
00603 void insertion_sort(Dlink & list)
00604 {
00605   Dlink aux;
00606 
00607   while (not list.is_empty())
00608     {
00609       Dlink * p = list.remove_next();
00610 
00611       insert_sorted<Compare>(aux, p);
00612     }
00613 
00614   list.swap(&aux);
00615 }
00628     template <typename T, class Compare>
00629 void insertion_sort(Dnode<T> & list)
00630 {
00631   insertion_sort < Compare_Dnode<T, Compare> > (list);
00632 }
00633     template <typename T>
00634 void insertion_sort(Dnode<T> & list)
00635 {
00636   insertion_sort < T, Aleph::less<T> > (list);
00637 }
00638     template <typename T>
00639 int binary_search_rec(T a[], const T & x, const int & l, const int & r)
00640 {
00641   return binary_search_rec <T, Aleph::less<T> > (a, x, l, r);
00642 }
00643     template <typename T, class Compare>
00644 void merge(T a[], const int & l, const int & m, const int & r)
00645 {
00646   int i, j, k;
00647   T b[r - l + 1];
00648 
00649   for (i = l; i <= m; i++)
00650     b[i] = a[i];
00651   for (j = r, i = m + 1; i <= r; i++, j--)
00652     b[i] = a[j];
00653   for (k = l, i = l, j = r; k <= r; k++)
00654     if (Compare() (b[i] < b[j]))
00655       a[k] = b[i++];
00656     else
00657       a[k] = b[j--]; 
00658 }
00659 
00684     template <typename T, class Compare>
00685 void mergesort(T a[], const int & l, const int & r)
00686 {
00687   if (l >= r) return;
00688 
00689   const int m = (l + r)/2;
00690 
00691   mergesort<T, Compare>(a, l, m);
00692   mergesort<T, Compare>(a, m + 1, r);
00693 
00694   merge<T, Compare>(a, l, m, r);
00695 }
00696     template <typename T>
00697 void mergesort(T a[], const int & l, const int & r)
00698 {
00699   mergesort <T, Aleph::less<T> > (a, l, r);
00700 }
00716     template <class Compare>
00717 void merge_lists(Dlink & l1, Dlink & l2, Dlink & result)
00718 {
00719 
00720   I(result.is_empty());
00721 
00722   while (not l1.is_empty() and not l2.is_empty())
00723     if (Compare () (l1.get_next(), l2.get_next()))
00724       result.append(l1.remove_next());
00725     else
00726       result.append(l2.remove_next());
00727 
00728   if (l1.is_empty())
00729     result.concat_list(&l2);
00730   else
00731     result.concat_list(&l1);
00732 
00733   I(l1.is_empty() and l2.is_empty());
00734 
00735 }
00751     template <class T, class Compare>
00752 void merge_lists(Dnode<T> & l1, Dnode<T> & l2, Dnode<T> & result)
00753 {
00754   merge_lists<Compare_Dnode<T, Compare> >(l1, l2, result);
00755 }
00771     template <class Compare>
00772 void mergesort(Dlink & list)
00773 {
00774   if (list.is_unitarian_or_empty())
00775     return;
00776 
00777   Dlink l, r;
00778 
00779   list.split_list(l, r); // dividir en dos listas
00780   
00781   mergesort <Compare> (l); // ordenar la primera
00782   mergesort <Compare> (r);  // ordenar la segunda
00783   
00784   merge_lists <Compare> (l, r, list); // mezclarlas 
00785 }
00809     template <typename T, class Compare>
00810 void mergesort(Dnode<T> & list)
00811 {
00812   mergesort < Compare_Dnode<T, Compare> > (list);
00813 }
00814 
00815     template <typename T>
00816 void mergesort(Dnode<T> & list)
00817 {
00818   mergesort < T, Aleph::less<T> > (list);
00819 }
00820 
00844     template <typename T, class Compare>
00845 void mergesort(DynDlist<T> & list)
00846 {
00847   mergesort < Compare_Dnode<T, Compare> > (list);
00848 }
00849 
00850 
00851    template <typename T, class Compare>
00852 int select_pivot(T a[], const int & l, const int & r); 
00853 
00854     template <typename T, class Compare>
00855 int partition(T a[], const int & l, const int & r)
00856 {
00857   const int p = select_pivot <T, Compare> (a, l, r);
00858   Aleph::swap(a[p], a[r]);
00859   T pivot = a[r]; // elemento pivot
00860   int i = l - 1,  // índice del primer elemento a la izquierda mayor que pivot
00861       j = r;      // índice del primer elemento a la derecha mayor que pivot
00862 
00863   while (true)
00864     {
00865           // avance mientras a[i] < a[pivot]
00866       while (Compare() (a[++i], pivot)) { /* no hay cuerpo */ }
00867       while (Compare() (pivot, a[--j])) // avance mientras a[pivot]< a[j] 
00868         if (j == l) // ¿se alcanzó el borde izquierdo?
00869           break; // sí ==> hay que terminar la iteración
00870 
00871       if (i >= j) 
00872         break;
00873 
00874           // En este punto hay una inversión a[i] > a[pivot] > a[j] 
00875       Aleph::swap(a[i], a[j]); // Eliminar la inversión
00876     }
00877   Aleph::swap(a[i], a[r]);
00878 
00879   return i;
00880 }
00881 
00918     template <typename T, class Compare>
00919 void quicksort_rec(T a[], const int & l, const int & r)
00920 {
00921   if (l >= r) return;
00922 
00923   const int pivot = partition <T, Compare> (a, l, r);
00924 
00925   quicksort_rec <T, Compare> (a, l, pivot - 1);
00926   quicksort_rec <T, Compare> (a, pivot + 1, r);
00927 }
00928     template <typename T>
00929 void quicksort_rec(T a[], const int & l, const int & r)
00930 {
00931   quicksort_rec<T, Aleph::less<T> > (a, l, r);
00932 }
00948     template <typename T, class Compare>
00949 void quicksort_rec_min(T a[], const int & l, const int & r)
00950 {
00951   if (r <= l) 
00952     return;
00953   
00954   const int pivot = partition<T, Compare>(a, l, r);
00955 
00956   if (pivot - l < r - pivot) // ¿cual es la partición más pequeña?
00957     {     // partición izquierda más pequeña
00958       quicksort_rec_min<T, Compare>(a, l, pivot - 1);
00959       quicksort_rec_min<T, Compare>(a, pivot + 1, r);
00960     }
00961   else
00962     {     // partición derecha más pequeña
00963       quicksort_rec_min<T, Compare>(a, pivot + 1, r);
00964       quicksort_rec_min<T, Compare>(a, l, pivot - 1);
00965     }
00966 }
00967     template <typename T>
00968 void quicksort_rec_min(T a[], const int & l, const int & r)
00969 {
00970   quicksort_rec_min <T, Aleph::less<T> > (a, l, r);
00971 }
00972     template <typename T, class Compare>
00973 int select_pivot(T a[], const int & l, const int & r)
00974 {
00975 
00976   I(l <= r);
00977 
00978   if (l - r <= 2)
00979     return r;
00980 
00981   const int m = (r + l) / 2; // índice del centro
00982 
00983   int p = Compare () (a[l], a[m]) ? m : l; // p = max(a[l], a[m])
00984 
00985   return Compare () (a[r], a[m]) ? r : p;  // retornar min(a[r], a[m])
00986 }
01023     template <typename T, class Compare>
01024 void quicksort(T a[], const int & l, const int & r)
01025 {
01026 
01027   if (r <= l) 
01028     return;
01029 
01030   typedef typename Aleph::pair<int, int> Partition;
01031 
01032   FixedStack<Partition, 32> stack;
01033 
01034   stack.push(Partition(l, r));
01035 
01036   while (stack.size() > 0)
01037     {
01038       const Partition p = stack.pop();
01039 
01040       const int pivot = partition<T, Compare>(a, p.first, p.second);
01041 
01042       if (pivot - p.first < p.second - pivot) // ¿cuál partición más pequeña?
01043         {     // partición izquierda más pequeña
01044           stack.push(Partition(pivot + 1, p.second));
01045           stack.push(Partition(p.first, pivot - 1));
01046         }
01047       else
01048         {     // partición derecha más pequeña
01049           stack.push(Partition(p.first, pivot - 1));
01050           stack.push(Partition(pivot + 1, p.second));
01051         }
01052     }
01053 }
01054     template <typename T>
01055 void quicksort(T a[], const int & l, const int & r)
01056 {
01057   quicksort<T, Aleph::less<T> > (a, l, r);
01058 }
01071     template <class Compare>
01072 void quicksort(Dlink & list) 
01073 {
01074   if (list.is_unitarian_or_empty()) 
01075     return;
01076 
01077   Dlink * pivot = list.remove_next();
01078 
01079   Dlink smaller; // lista de los menores que pivot
01080   Dlink bigger;  // lista de los mayores que pivot
01081 
01082   while (not list.is_empty()) 
01083   {
01084     Dlink * p = list.remove_next();
01085 
01086     if (Compare () (p, pivot))
01087       smaller.append(p);
01088     else
01089       bigger.append(p);
01090   }
01091  
01092   quicksort <Compare> (bigger);  
01093   quicksort <Compare> (smaller);
01094 
01095   list.concat_list(&smaller);
01096   list.append(pivot);
01097   list.concat_list(&bigger);
01098 } 
01122     template <typename T, class Compare>
01123 void quicksort(Dnode<T> & list)
01124 {
01125   quicksort < Compare_Dnode<T, Compare> > (list);
01126 }
01127 
01128     template <typename T>
01129 void quicksort(Dnode<T> & list)
01130 {
01131   quicksort < T, Aleph::less<T> > (list);
01132 }
01173     template <typename T, class Compare>
01174 void quicksort_insertion(T a[], const int & l, const int & r)
01175 {
01176   if (r <= l) return;
01177 
01178   const int pivot = partition<T, Compare>(a, l, r);
01179 
01180   const int l_size = pivot - l; // tamaño partición izquierda
01181   const int r_size = r - pivot; // tamaño partición derecha
01182 
01183   bool left_done  = false; // true si partición izquierda está ordenada
01184   bool right_done = false; // true si partición derecha está ordenada
01185 
01186   if (l_size <= Aleph::Insertion_Threshold) // ¿partición izquierda pequeña?
01187     {     // sí ==> ordénela por inserción
01188       insertion_sort<T, Compare>(a, l, pivot - 1);  
01189       left_done = true;
01190     }
01191 
01192   if (r_size <= Aleph::Insertion_Threshold) // ¿partición derecha pequeña?
01193     {     // sí ==> ordénela por inserción
01194       insertion_sort<T, Compare>(a, pivot + 1, r);
01195       right_done = true;
01196     }
01197 
01198   if (left_done and right_done) 
01199     return; // ambas particiones ya están ordenadas por inserción
01200 
01201   if (left_done) // ¿partición izquierda ordenada por inserción?
01202     {     // sí; sólo resta ordenar recursivamente la partición derecha
01203       quicksort_insertion<T, Compare>(a, pivot + 1, r);
01204 
01205       return;
01206     }
01207 
01208   if (right_done) // ¿partición derecha ordenada por inserción?
01209     {     // sí; sólo resta ordenar recursivamente la partición izquierda
01210       quicksort_insertion<T, Compare>(a, l, pivot - 1);
01211 
01212       return;
01213     }
01214 
01215       // En este punto, ambas particiones no fueron ordenadas por inserción
01216 
01217       // Ordenar recursivamente de primero partición más pequeña 
01218   if (l_size < r_size)
01219     {     // partición izquierda más pequeña
01220       quicksort_insertion <T, Compare> (a, l, pivot - 1);
01221       quicksort_insertion <T, Compare> (a, pivot + 1, r);
01222     }
01223   else
01224     {     // partición derecha más pequeña
01225       quicksort_insertion <T, Compare> (a, pivot + 1, r);
01226       quicksort_insertion <T, Compare> (a, l, pivot - 1);
01227     }
01228 }    
01229     template <typename T>
01230 void quicksort_insertion(T a[], const int & l, const int & r)
01231 {
01232   quicksort_insertion <T, Aleph::less<T> > (a, l, r);
01233 }
01264     template <typename T, class Compare>
01265 int random_search(T a[], const T & x, const int & l, const int & r)
01266 {
01267   if (l > r)
01268     return Not_Found;
01269 
01270   const int pivot = partition<T, Compare>(a, l, r);
01271 
01272   if (Compare() (x, a[pivot]))
01273     return random_search(a, l, pivot - 1);
01274   else if (Compare() (a[pivot], x))
01275     return random_search(a, pivot + 1, r);
01276 
01277   return pivot; // elemento encontrado en el índice x
01278 }
01279     template <typename T>
01280 int random_search(T a[], const T & x, const int & l, const int & r)
01281 {
01282   return random_search <T, Aleph::less<T> > (a, x, l, r);
01283 }
01309     template <typename T, class Compare>
01310 Dnode<T> * dlink_random_search(Dlink & list, const T & x)
01311 {
01312   if (list.is_empty()) 
01313     return NULL;
01314 
01315   Dnode<T> * pivot = static_cast<Dnode<T>*>(list.remove_next());
01316   Dnode<T> item(x);
01317   Dnode<T> * item_ptr = &item; // puntero a una celda que contiene a x
01318 
01319   Dlink smaller; // lista de los menores que pivot
01320   Dlink bigger;  // lista de los mayores que pivot
01321 
01322   while (not list.is_empty()) 
01323   {
01324     Dlink * p = list.remove_next();
01325 
01326     if (Compare () (p, pivot))
01327       smaller.append(p);
01328     else
01329       bigger.append(p);
01330   }
01331 
01332   Dnode<T> * ret_val = NULL;
01333 
01334   if (Compare () (item_ptr, pivot))
01335     ret_val = dlink_random_search <T, Compare> (smaller, x);
01336   else if (Compare () (pivot, item_ptr))
01337     ret_val = dlink_random_search <T, Compare> (bigger, x);
01338   else
01339     ret_val = pivot;
01340 
01341 
01342   I(list.is_empty());
01343 
01344   list.swap(&smaller); 
01345   list.append(pivot);  
01346   list.concat_list(&bigger);
01347 
01348   return ret_val;
01349 }
01378     template <typename T, class Compare_T>
01379 Dnode<T> * random_search(Dlink & list, const T & x)
01380 {
01381   return dlink_random_search <T, Compare_Dnode<T, Compare_T> > (list, x);
01382 }
01383 
01384     template <typename T>
01385 Dnode<T> * random_search(Dlink & list, const T & x)
01386 {
01387   return random_search <T, Aleph::less<T> > (list, x);
01388 }
01389 
01418     template <typename T, class Compare>
01419 T * random_search(DynDlist<T> & list, const T & x)
01420 {
01421   Dnode<T> * p = dlink_random_search <T, Compare_Dnode<T, Compare> > (list, x);
01422 
01423   return p == NULL ? NULL : &(p->get_data());
01424 }
01425 
01426     template <typename T>
01427 T * random_search(DynDlist<T> & list, const T & x)
01428 {
01429   return random_search <T, Aleph::less<T> > (list, x);
01430 }
01431     template <typename T, class Compare> static inline
01432 const T & __random_select(T a[], const int & i, const int & l, const int & r)
01433 {
01434   const int pivot = partition<T, Compare>(a, l, r);
01435 
01436   if (i == pivot)
01437     return a[i];
01438   
01439   if (i < pivot)
01440     return __random_select<T, Compare>(a, i, l, pivot - 1);
01441   else
01442     return __random_select<T, Compare>(a, i, pivot + 1, r);
01443 }
01470     template <typename T, class Compare> 
01471 const T & random_select(T a[], const int & i, const int & n)
01472 {
01473   if (i >= n)
01474     throw std::out_of_range("index out of range");
01475 
01476   return __random_select(a, i, 0, n - 1);
01477 }
01478     template <typename T> 
01479 const T & random_select(T a[], const int & i, const int & n)
01480 {
01481   return random_select <T, Aleph::less<T> > (a, i, 0, n - 1);
01482 }
01504     template <class Compare>
01505 Dlink * dlink_random_select(Dlink & list, const size_t & i)
01506 {
01507   if (list.is_empty()) 
01508     return NULL;
01509 
01510   Dlink * pivot = list.remove_next();
01511 
01512   Dlink smaller; // lista de los menores que pivot
01513   Dlink bigger;  // lista de los mayores que pivot
01514 
01515   size_t smaller_count = 0, // cantidad de elementos de smaller
01516          bigger_count  = 0; // cantidad de elementos de bigger
01517 
01518   while (not list.is_empty()) 
01519   {
01520     Dlink * p = list.remove_next();
01521 
01522     if (Compare () (p, pivot))
01523       {
01524         smaller.append(p); ++smaller_count;
01525       }
01526     else
01527       {
01528         bigger.append(p); ++bigger_count;
01529       }
01530   }
01531 
01532   if (i >= bigger_count)
01533     throw std::out_of_range("index of selection greater than list's size");
01534 
01535 
01536   Dlink * ret_val = NULL;
01537 
01538   if (i == smaller_count)
01539     ret_val = pivot;
01540   else if (i < smaller_count)
01541     ret_val = dlink_random_select <Compare> (smaller, i);
01542   else
01543     ret_val = dlink_random_select <Compare> (bigger, i - (smaller_count + 1));
01544 
01545   list.concat_list(&smaller);
01546   list.append(pivot);
01547   list.concat_list(&bigger);
01548 
01549   return ret_val;
01550 }
01577     template <typename T, class Compare>
01578 Dnode<T> * random_select(Dlink & list, const size_t & i)
01579 {
01580   return static_cast <Dnode<T>*> 
01581     (dlink_random_select < Compare_Dnode<T, Compare> > (list, i));
01582 }
01583     template <typename T>
01584 Dnode<T> * random_select(Dlink & list, const size_t & i)
01585 {
01586   return random_select < T, Aleph::less<T> > (list, i);
01587 }
01588 
01615     template <typename T, class Compare>
01616 T * random_select(DynDlist<T> list, const size_t & i)
01617 {
01618   Dlink * link = dlink_random_select <Compare_Dnode<T, Compare> > (list, i);
01619 
01620   Dnode<T> * p = static_cast<Dnode<T>*>(link);
01621 
01622   return p != NULL ? &(p->get_data()) : NULL;
01623 }
01624 
01625     template <typename T>
01626 T * random_select(DynDlist<T> list, const size_t & i)
01627 {
01628   return random_select <T, Aleph::less<T> > (list, i);
01629 }
01662     template <typename T, class Compare>
01663 int binary_search_rec(T a[], const T & x, const int & l, const int & r)
01664 {
01665   const int m = (l + r) / 2;
01666 
01667   if (l > r)
01668     return m;
01669 
01670   if (Compare() (x, a[m]))
01671     return binary_search_rec<T, Compare>(a, l, m - 1);
01672   else if (Compare() (a[m], x))
01673     return binary_search_rec<T, Compare>(a, m + 1, r);
01674 
01675   return m; // encontrado
01676 }
01677 
01678 }
01679 
01680 # endif // TPL_SORT_UTILS_H
01681 

Leandro R. León