LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiQuickPartialSort.h

00001 /*
00002  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*----------------------------------------------------------------
00025  * project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiQuickPartialSort.h
00027  * authors ....: Guy Wafo
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 27.3.2001
00030  * revisions ..: $Id: ltiQuickPartialSort.h,v 1.5 2006/02/08 12:41:02 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_QUICKMEDIAN_H_
00034 #define _LTI_QUICKMEDIAN_H_
00035 
00036 #include "ltiFunctor.h"
00037 #include "ltiVector.h"
00038 #include "ltiMatrix.h"
00039 #include <algorithm>
00040 
00041 namespace lti {
00042 
00043   /**
00044    * Quick partial sort.
00045    * 
00046    * This class is used to extract the n smallest elements of a
00047    * vector, without requiring to complete the sort.  Since the
00048    * apply method expects the index of the element you want for sure at
00049    * its destination if the vector were completelly sorted, to get the
00050    * first n elements you need to give the apply method "n-1".
00051    *
00052    * It is usually employed when you just required, for example, the
00053    * three smallest elements of a vector.  In this case you would
00054    * apply(2,vct), since "2" is the index of the third element of
00055    * the vector.  
00056    *
00057    * A major difference to the STL method std::partial_sort is that this
00058    * functor don't even sorts the elements at the begining, it just ensures
00059    * that they are smaller or equal the element at the given position, and
00060    * that the elements after the final one at the pivot position are greater
00061    * or equal the pivot element.  In this sense, this corresponds to the
00062    * std::partition algorithm, but here we use the LTI-Lib functor-based
00063    * interface.
00064    *
00065    * The type of the vector elements T must accept the operator< and
00066    * operator=.
00067    *
00068    * Note that this functor always sorts in increasing order.
00069    * If you need the n greatest elements, then just give as pivot-index
00070    * vct.size()-n, and the last elements are the ones you are looking for.
00071    *
00072    * @see lti::sort,lti::quickMedian,lti::quickPartialSort2
00073    *
00074    * You may also be interested in the std::nth_element and std::partial_sort
00075    * functions of the <algorithms> file, which can be better if you are
00076    * dealing with STL structures or if you really want to sort the beginning of
00077    * your vector.  Since these standard functions are templates, you can also
00078    * use them with lti::vectors.
00079    *
00080    * @ingroup gStats
00081    */
00082   template <class T>
00083   class quickPartialSort : public functor {
00084   public:
00085 
00086     /**
00087      * The parameters for the class quickPartialSort
00088      */
00089     class parameters : public functor::parameters {
00090     public:
00091       /**
00092        * Default constructor
00093        */
00094       parameters() : functor::parameters() {
00095         pivotIndex = int(2);
00096       };
00097 
00098       /**
00099        * Copy constructor
00100        * @param other the parameters object to be copied
00101        */
00102       parameters(const parameters& other) : functor::parameters() {
00103         copy(other);
00104       }
00105       
00106       /**
00107        * Destructor
00108        */
00109       ~parameters() {
00110       };
00111 
00112       /**
00113        * Returns name of this type
00114        */
00115       const char* getTypeName() const {
00116         return "quickPartialSort::parameters";
00117       };
00118 
00119       /**
00120        * Copy the contents of a parameters object
00121        * @param other the parameters object to be copied
00122        * @return a reference to this parameters object
00123        */
00124       parameters& copy(const parameters& other) {
00125 #     ifndef _LTI_MSC_6
00126         // MS Visual C++ 6 is not able to compile this...
00127         functor::parameters::copy(other);
00128 #     else
00129         // ...so we have to use this workaround.
00130         // Conditional on that, copy may not be virtual.
00131         functor::parameters& (functor::parameters::* p_copy)
00132                             (const functor::parameters&) =
00133                             functor::parameters::copy;
00134         (this->*p_copy)(other);
00135 #     endif
00136 
00137         
00138         pivotIndex = other.pivotIndex;
00139         
00140         return *this;
00141       };
00142 
00143       /**
00144        * Copy the contents of a parameters object
00145        * @param other the parameters object to be copied
00146        * @return a reference to this parameters object
00147        */
00148       parameters& operator=(const parameters& other) {
00149         return copy(other);
00150       };
00151 
00152       /**
00153        * Returns a pointer to a clone of the parameters
00154        */
00155       virtual functor::parameters* clone() const {
00156         return new parameters(*this);
00157       };
00158 
00159 #     ifndef _LTI_MSC_6
00160       /**
00161        * Write the parameters in the given ioHandler
00162        * @param handler the ioHandler to be used
00163        * @param complete if true (the default) the enclosing begin/end will
00164        *        be also written, otherwise only the data block will be written.
00165        * @return true if write was successful
00166        */
00167       virtual bool write(ioHandler& handler,const bool complete=true) const
00168 #     else
00169       /**
00170        * This function is required by MSVC only, as a workaround for a
00171        * very awful bug, which exists since MSVC V.4.0, and still by
00172        * V.6.0 with all bugfixes (so called "service packs") remains
00173        * there...  This method is also public due to another bug, so please
00174        * NEVER EVER call this method directly: use write() instead
00175        */
00176       bool writeMS(ioHandler& handler,const bool complete=true) const
00177 #     endif
00178       {
00179         bool b = true;
00180         if (complete) {
00181           b = handler.writeBegin();
00182         }
00183         
00184         if (b) {
00185           
00186           lti::write(handler,"pivotIndex",pivotIndex);
00187         }
00188 
00189 #     ifndef _LTI_MSC_6
00190         // This is the standard C++ code, which MS Visual C++ 6 is not able to
00191         // compile...
00192         b = b && functor::parameters::write(handler,false);
00193 #     else
00194         bool (functor::parameters::* p_writeMS)(ioHandler&,
00195                                                          const bool) const =
00196           functor::parameters::writeMS;
00197         b = b && (this->*p_writeMS)(handler,false);
00198 #     endif
00199 
00200         if (complete) {
00201           b = b && handler.writeEnd();
00202         }
00203 
00204         return b;
00205       }
00206 
00207 #     ifdef _LTI_MSC_6
00208       /**
00209        * Write the parameters in the given ioHandler
00210        * @param handler the ioHandler to be used
00211        * @param complete if true (the default) the enclosing begin/end will
00212        *        be also written, otherwise only the data block will be written.
00213        * @return true if write was successful
00214        */
00215       bool write(ioHandler& handler,
00216                  const bool complete=true) const {
00217         // ...we need this workaround to cope with another really
00218         // awful MSVC bug.
00219         return writeMS(handler,complete);
00220       }
00221 #     endif
00222 
00223 
00224 #     ifndef _LTI_MSC_6
00225       /**
00226        * Read the parameters from the given ioHandler
00227        * @param handler the ioHandler to be used
00228        * @param complete if true (the default) the enclosing begin/end will
00229        *        be also written, otherwise only the data block will be written.
00230        * @return true if read was successful
00231        */
00232       virtual bool read(ioHandler& handler,const bool complete=true)
00233 #     else
00234       /**
00235        * This function is required by MSVC only, as a workaround for a
00236        * very awful bug, which exists since MSVC V.4.0, and still by
00237        * V.6.0 with all bugfixes (so called "service packs") remains
00238        * there...  This method is also public due to another bug, so please
00239        * NEVER EVER call this method directly: use read() instead
00240        */
00241       bool readMS(ioHandler& handler,const bool complete=true)
00242 #     endif
00243       {
00244         bool b = true;
00245         if (complete) {
00246           b = handler.readBegin();
00247         }
00248         
00249         if (b) {
00250           
00251           lti::read(handler,"pivotIndex",pivotIndex);
00252         }
00253 
00254 #       ifndef _LTI_MSC_6
00255         // This is the standard C++ code, which MS Visual C++ 6 is not
00256         // able to compile...
00257         b = b && functor::parameters::read(handler,false);
00258 #       else
00259         bool (functor::parameters::* p_readMS)(ioHandler&,
00260                                                         const bool) =
00261           functor::parameters::readMS;
00262         b = b && (this->*p_readMS)(handler,false);
00263 #       endif
00264 
00265         if (complete) {
00266           b = b && handler.readEnd();
00267         }
00268         
00269         return b;
00270       }
00271 
00272 #     ifdef _LTI_MSC_6
00273       /**
00274        * Read the parameters from the given ioHandler
00275        * @param handler the ioHandler to be used
00276        * @param complete if true (the default) the enclosing begin/end will
00277        *        be also written, otherwise only the data block will be written.
00278        * @return true if read was successful
00279        */
00280       bool read(ioHandler& handler,const bool complete=true) {
00281         // ...we need this workaround to cope with another really awful MSVC
00282         // bug.
00283         return readMS(handler,complete);
00284       }
00285 #     endif
00286 
00287       // ------------------------------------------------
00288       // the parameters
00289       // ------------------------------------------------
00290 
00291       /**
00292        * Specifies the position in the vectors that will have its own
00293        * place, if the whole vector where sorted.  This means,
00294        * all first "pivotIndex" elements in the output vectors will
00295        * be smaller or equal the rest of the elements.
00296        *
00297        * Default value: 2
00298        */
00299       int pivotIndex;
00300 
00301     };
00302 
00303     /**
00304      * default constructor
00305      */
00306     quickPartialSort();
00307 
00308     /**
00309      * copy constructor
00310      * @param other the object to be copied
00311      */
00312     quickPartialSort(const quickPartialSort<T>& other);
00313 
00314     /**
00315      * destructor
00316      */
00317     virtual ~quickPartialSort();
00318 
00319     /**
00320      * returns the name of this type ("quickPartialSort")
00321      */
00322     virtual const char* getTypeName() const;
00323 
00324     /**
00325      * The given matrix is used as source and destination.
00326      * 
00327      * The matrix will be considered as a vector, where the rows of the matrix
00328      * are simply concatenated.  The first parameters::pivotIndex elements of
00329      * the resulting matrix will be smaller or equall than the rest of
00330      * the elements.
00331      *
00332      * @param srcdest matrix<T> with the source data.  The result
00333      *                 will be left here too.
00334      * @return true if successful, false otherwise.
00335      */
00336     bool apply(matrix<T>& srcdest) const;
00337 
00338     /**
00339      * Partially sorts given matrix, which is NOT modified.
00340      *
00341      * The elements of the matrix will be considered as part of a vector
00342      * with "columns()" times "rows()" elements.
00343      * @param src matrix<T> with the source data.
00344      * @param dest the median value of the given matrix.
00345      *
00346      * @return true if successful, false otherwise.
00347      */
00348     bool apply(const matrix<T>& src,matrix<T>& dest) const;
00349 
00350     /**
00351      * Operates on the given parameter.
00352      *
00353      * The resulting vector has its first parameters::pivotIndex elements of
00354      * smaller or equall than the rest of the elements.
00355      *
00356      * @param srcdest vector<T> with the source data.  The result will
00357      *        be left here too.
00358      *
00359      * @return true if successful, false otherwise.
00360      */
00361     bool apply(vector<T>& srcdest) const;
00362 
00363     /**
00364      * Partially sorts the input vector and leaves the result in the
00365      * destination vector.
00366      *
00367      * @param src vector<T> with the source data.
00368      * @param dest the partially sorted vector.  The first pivotIndex elements
00369      *             are less or equal than the rest of the elements of the 
00370      *             vector.
00371      *
00372      * @return true if successful, false otherwise.
00373      */
00374     bool apply(const vector<T>& src, vector<T>& dest) const;
00375 
00376     /**
00377      * Partially sorts the vector on-place.
00378      *
00379      * @param srcdest vector<T> with the source data.  The result
00380      *                 will be left here too.
00381      *
00382      * @return true if successful, false otherwise.
00383      */
00384     bool apply(std::vector<T>& srcdest) const;
00385 
00386     /**
00387      * operates on the given parameter.
00388      * @param src vector<T> with the source data.
00389      * @param dest the partially sorted vector.
00390      *
00391      * @return true if successful, false otherwise.
00392      */
00393     bool apply(const std::vector<T>& src, std::vector<T>& dest) const;
00394 
00395     /**
00396      * The given matrix is used as source and destination.
00397      * 
00398      * The matrix will be considered as a vector, where the rows of the matrix
00399      * are simply concatenated.  The first parameters::pivotIndex elements of
00400      * the resulting matrix will be smaller or equall than the rest of
00401      * the elements.
00402      *
00403      * @param pivotIndex pivot position on the given vector.  The result
00404      *                   has the first "pivotIndex" elements smaller or
00405      *                   equal the rest of the vector elements.
00406      * @param srcdest matrix<T> with the source data.  The result
00407      *                 will be left here too.
00408      * @return true if successful, false otherwise.
00409      */
00410     bool apply(const int pivotIndex,matrix<T>& srcdest) const;
00411 
00412     /**
00413      * Partially sorts given matrix, which is NOT modified.
00414      *
00415      * The elements of the matrix will be considered as part of a vector
00416      * with "columns()" times "rows()" elements.
00417      * @param pivotIndex pivot position on the given vector.  The result
00418      *                   has the first "pivotIndex" elements smaller or
00419      *                   equal the rest of the vector elements.
00420      * @param src matrix<T> with the source data.
00421      * @param dest the median value of the given matrix.
00422      *
00423      * @return true if successful, false otherwise.
00424      */
00425     bool apply(const int pivotIndex,
00426                const matrix<T>& src,matrix<T>& dest) const;
00427 
00428     /**
00429      * Operates on the given parameter.
00430      *
00431      * The resulting vector has its first pivotIndex elements of
00432      * smaller or equall than the rest of the elements.
00433      *
00434      * @param pivotIndex pivot position on the given vector.  The result
00435      *                   has the first "pivotIndex" elements smaller or
00436      *                   equal the rest of the vector elements.
00437      * @param srcdest vector<T> with the source data.  The result will
00438      *        be left here too.
00439      *
00440      * @return true if successful, false otherwise.
00441      */
00442     bool apply(const int pivotIndex,vector<T>& srcdest) const;
00443 
00444     /**
00445      * Partially sorts the input vector and leaves the result in the
00446      * destination vector.
00447      *
00448      * @param pivotIndex pivot position on the given vector.  The result
00449      *                   has the first "pivotIndex" elements smaller or
00450      *                   equal the rest of the vector elements.
00451      * @param src vector<T> with the source data.
00452      * @param dest the partially sorted vector.  The first pivotIndex elements
00453      *             are less or equal than the rest of the elements of the 
00454      *             vector.
00455      *
00456      * @return true if successful, false otherwise.
00457      */
00458     bool apply(const int pivotIndex,
00459                const vector<T>& src, vector<T>& dest) const;
00460 
00461     /**
00462      * Partially sorts the vector on-place.
00463      *
00464      * @param pivotIndex pivot position on the given vector.  The result
00465      *                   has the first "pivotIndex" elements smaller or
00466      *                   equal the rest of the vector elements.
00467      * @param srcdest vector<T> with the source data.  The result
00468      *                 will be left here too.
00469      *
00470      * @return true if successful, false otherwise.
00471      */
00472     bool apply(const int pivotIndex,std::vector<T>& srcdest) const;
00473 
00474     /**
00475      * Partially sorts the vector on-copy.
00476      *
00477      * @param pivotIndex pivot position on the given vector.  The result
00478      *                   has the first "pivotIndex" elements smaller or
00479      *                   equal the rest of the vector elements.
00480      * @param src vector<T> with the source data.
00481      * @param dest the partially sorted vector.
00482      *
00483      * @return true if successful, false otherwise.
00484      */
00485     bool apply(const int pivotIndex,
00486                const std::vector<T>& src, std::vector<T>& dest) const;
00487 
00488     /**
00489      * copy data of "other" functor.
00490      * @param other the functor to be copied
00491      * @return a reference to this functor object
00492      */
00493     quickPartialSort& copy(const quickPartialSort& other);
00494 
00495     /**
00496      * returns a pointer to a clone of this functor.
00497      */
00498     virtual functor* clone() const;
00499 
00500     /**
00501      * returns used parameters
00502      */
00503     const parameters& getParameters() const;
00504 
00505   protected:
00506     /**
00507      * this method calculates the median in a recursively form
00508      */
00509     T  findMedian(vector<T>& vct,
00510                   const int& begin,
00511                   const int& end,
00512                   const int& medianPos) const;
00513     
00514     /**
00515      * this method chooses a pivot-value and ensures that lower values lie
00516      * at the left and higher values at the right of its final position, which
00517      * will be returned.
00518      */
00519     int partition(vector<T>& vct,
00520                   const int& begin,
00521                   const int& end) const;
00522 
00523     /**
00524      * this method calculates the median in a recursively form
00525      */
00526     T  findMedian(std::vector<T>& vct,
00527                   const int& begin,
00528                   const int& end,
00529                   const int& medianPos) const;
00530     
00531     /**
00532      * this method chooses a pivot-value and ensures that lower values lie
00533      * at the left and higher values at the right of its final position, which
00534      * will be returned.
00535      */
00536     int partition(std::vector<T>& vct,
00537                   const int& begin,
00538                   const int& end) const;
00539 
00540   };
00541 
00542   /**
00543    * Quick partial sort with colateral effects.
00544    * 
00545    * This class is used to extract the n smallest elements of a
00546    * vector, without requiring to complete the sort, while a second
00547    * vector is sorted exactly the same way.  
00548    *
00549    * It is usually employed when you just required, for example, the
00550    * three smallest elements of a vector.  
00551    *
00552    * If the so-called pivot-index is equal to vct.size()/2 (where vct is the
00553    * vector you want to partially sort), then this functor is equivalent
00554    * to the quickMedian.
00555    *
00556    * The type of the vector elements T must accept the operator< and
00557    * operator=.
00558    *
00559    * Note that this functor always sorts in increasing order.
00560    * If you need the n greatest elements, then just give as pivot-index
00561    * vct.size()-n, and the last elements are the ones you are looking for.
00562    *
00563    * @see lti::quickMedian2, lti::sort2, lti::quickPartialSort
00564    *
00565    * @ingroup gStats
00566    */
00567   template <class T,class U>
00568   class quickPartialSort2 : public quickPartialSort<T> {
00569   public:
00570     
00571     typedef typename quickPartialSort<T>::parameters parameters;
00572 
00573     /**
00574      * default constructor
00575      */
00576     quickPartialSort2();
00577 
00578     /**
00579      * copy constructor
00580      * @param other the object to be copied
00581      */
00582     quickPartialSort2(const quickPartialSort2<T,U>& other);
00583 
00584     /**
00585      * destructor
00586      */
00587     virtual ~quickPartialSort2();
00588 
00589     /**
00590      * returns the name of this type ("quickPartialSort2")
00591      */
00592     virtual const char* getTypeName() const;
00593 
00594     /**
00595      * Partially sort the vector \a keys and reorder the elements of \a data
00596      * accordingly.
00597      *
00598      * Both vectors must have the same size.
00599      *
00600      * @param keys vector<T> with the key data.  This vector will
00601      *             be partially sorted.
00602      * @param data vector<U> with data to be sorted the same way as the keys.
00603      *             You can for example use a ivector initialized with the
00604      *             index values (i.e. data(i)=i), so that after the apply
00605      *             method you can check which elements are below the median
00606      *             and which above.
00607      *             
00608      * @return true if successful, false otherwise.
00609      */
00610     bool apply(vector<T>& keys,vector<U>& data) const;
00611 
00612     /**
00613      * Partially sort the vector \a keys and reorder the elements of \a data
00614      * accordingly.
00615      *
00616      * Both vectors must have the same size.
00617      *
00618      * @param keys vector<T> with the key data.  This vector will
00619      *             be partially sorted.
00620      * @param data vector<U> with data to be sorted the same way as the keys.
00621      *             You can for example use a ivector initialized with the
00622      *             index values (i.e. data(i)=i), so that after the apply
00623      *             method you can check which elements are below the median
00624      *             and which above.
00625      *             
00626      * @return true if successful, false otherwise.
00627      */
00628     bool apply(std::vector<T>& keys,vector<U>& data) const;
00629 
00630     /**
00631      * Partially sort the vector \a keys and reorder the elements of \a data
00632      * accordingly.
00633      *
00634      * Both vectors must have the same size.
00635      *
00636      * @param pivotIndex pivot position on the given vector.  The result
00637      *                   has the first "pivotIndex" elements smaller or
00638      *                   equal the rest of the vector elements.
00639      * @param keys vector<T> with the key data.  This vector will
00640      *             be partially sorted.
00641      * @param data vector<U> with data to be sorted the same way as the keys.
00642      *             You can for example use a ivector initialized with the
00643      *             index values (i.e. data(i)=i), so that after the apply
00644      *             method you can check which elements are below the median
00645      *             and which above.
00646      *             
00647      * @return true if successful, false otherwise.
00648      */
00649     bool apply(const int pivotIndex,
00650                vector<T>& keys,vector<U>& data) const;
00651 
00652     /**
00653      * Partially sort the vector \a keys and reorder the elements of \a data
00654      * accordingly.
00655      *
00656      * Both vectors must have the same size.
00657      *
00658      * @param pivotIndex pivot position on the given vector.  The result
00659      *                   has the first "pivotIndex" elements smaller or
00660      *                   equal the rest of the vector elements.
00661      * @param keys vector<T> with the key data.  This vector will
00662      *             be partially sorted.
00663      * @param data vector<U> with data to be sorted the same way as the keys.
00664      *             You can for example use a ivector initialized with the
00665      *             index values (i.e. data(i)=i), so that after the apply
00666      *             method you can check which elements are below the median
00667      *             and which above.
00668      *             
00669      * @return true if successful, false otherwise.
00670      */
00671     bool apply(const int pivotIndex,
00672                std::vector<T>& keys,vector<U>& data) const;
00673 
00674     /**
00675      * returns a pointer to a clone of this functor.
00676      */
00677     virtual functor* clone() const;
00678 
00679   protected:
00680     /**
00681      * this method calculates the median in a recursively form
00682      */
00683     T  findMedian(vector<T>& vct,
00684                   vector<U>& data,
00685                   const int& begin,
00686                   const int& end,
00687                   const int& medianPos) const;
00688     
00689     /**
00690      * this method chooses a pivot-value and ensures that lower values lie
00691      * at the left and higher values at the right of its final position, which
00692      * will be returned.
00693      */
00694     int partition(vector<T>& vct,
00695                   vector<U>& data,
00696                   const int& begin,
00697                   const int& end) const;
00698 
00699     /**
00700      * this method calculates the median in a recursively form
00701      */
00702     T  findMedian(std::vector<T>& vct,
00703                   vector<U>& data,
00704                   const int& begin,
00705                   const int& end,
00706                   const int& medianPos) const;
00707     
00708     /**
00709      * this method chooses a pivot-value and ensures that lower values lie
00710      * at the left and higher values at the right of its final position, which
00711      * will be returned.
00712      */
00713     int partition(std::vector<T>& vct,
00714                   vector<U>& data,
00715                   const int& begin,
00716                   const int& end) const;
00717 
00718   };
00719 
00720 
00721 
00722 }
00723 
00724 #include "ltiQuickPartialSort_template.h"
00725 
00726 #endif

Generated on Sat Apr 10 15:26:02 2010 for LTI-Lib by Doxygen 1.6.1