latest version v1.9 - last update 10 Apr 2010 |
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