QGpCoreTools/SortedVector.h
Go to the documentation of this file.
00001 /***************************************************************************
00002 **
00003 **  This file is part of QGpCoreTools.
00004 **
00005 **  This library is free software; you can redistribute it and/or
00006 **  modify it under the terms of the GNU Lesser General Public
00007 **  License as published by the Free Software Foundation; either
00008 **  version 2.1 of the License, or (at your option) any later version.
00009 **
00010 **  This file is distributed in the hope that it will be useful, but WITHOUT
00011 **  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 **  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00013 **  License for more details.
00014 **
00015 **  You should have received a copy of the GNU Lesser General Public
00016 **  License along with this library; if not, write to the Free Software
00017 **  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 **
00019 **  See http://www.geopsy.org for more information.
00020 **
00021 **  Created: 2010-07-27
00022 **  Authors:
00023 **    Marc Wathelet (LGIT, Grenoble, France)
00024 **
00025 ***************************************************************************/
00026 
00027 #ifndef SORTEDVECTOR_H
00028 #define SORTEDVECTOR_H
00029 
00030 #include <QtCore>
00031 
00032 #include "QGpCoreToolsDLLExport.h"
00033 
00034 namespace QGpCoreTools {
00035 
00036 template <class Key, class T>
00037 class QGPCORETOOLS_EXPORT SortedVector : private QVector<T *>
00038 {
00039 public:
00040   SortedVector() {_n2=1;}
00041 
00042   bool isEmpty() const {return QVector<T *>::isEmpty();}
00043   int count() const {return QVector<T *>::count();}
00044   T * at(int index) const {return QVector<T *>::at(index);}
00045 
00046   void insert(T * o);
00047   void remove(int index);
00048   void clear();
00049   void reserve(int n) {QVector<T *>::reserve(n);}
00050 
00051   void append(T * o) {QVector<T *>::append(o);}
00052   void sort() {qSort(QVector<T *>::begin(), QVector<T *>::end(), lessThan);}
00053 
00054   bool contains(const Key& k) const {return indexOf(k)>-1;}
00055   int indexOf(const Key& k) const;
00056   const QVector<T *>& vector() const {return *this;}
00057 private:
00058   static bool lessThan(const T * o1, const T * o2) {return o1->key()<o2->key();}
00059   int indexAfter(const Key& k) const;
00060 
00061   int _n2;
00062 };
00063 
00064 template<class Key, class T>
00065 int SortedVector<Key, T>::indexOf(const Key& k) const
00066 {
00067   if(count()<12) { /* For few elements, faster to check systematically
00068                       n integer comparisons
00069                       n increments
00070                       n object comparisons
00071                    */
00072     for(int i=count()-1; i>=0; i--) {
00073       if(k==at(i)->key()) return i;
00074     }
00075     return -1;
00076   } else {        /*
00077                     4+2*l object comparisons
00078                     2*l   integer comparisons
00079                     3*l   increments (including bit shifts)
00080                     With l=ceil(log2(n)), e.g. n=12, l=4: 12 oc  8 ic  12 i
00081                                                   7, l=3: 10 oc  6 ic   9 i
00082                                                  20, l=5: 14 oc 10 ic  15 i
00083                                                 100, l=7: 16 oc 14 ic  21 i
00084                   */
00085     if(k<at(0)->key()) return -1;
00086     if(k==at(0)->key()) return 0;
00087     int lasti=count()-1;
00088     if(k>at(lasti)->key()) return -1;
00089     int i=_n2;
00090     int step2=_n2 >> 1;
00091     while(step2>0) {
00092       if(i>lasti) {
00093         i-=step2;
00094       } else {
00095         const Key& ki=at(i)->key();
00096         if(k<ki) {
00097           i-=step2;
00098         } else if(k>ki) {
00099           i+=step2;
00100         } else {
00101           return i;
00102         }
00103       }
00104       step2=step2 >> 1;
00105     }
00106     if(k==at(i)->key()) {
00107       return i;
00108     } else {
00109       return -1;
00110     }
00111   }
00112 }
00113 
00114 template<class Key, class T>
00115 int SortedVector<Key, T>::indexAfter(const Key& k) const
00116 {
00117   if(isEmpty() || k<at(0)->key()) return 0;
00118   int lasti=count()-1;
00119   if(k>=at(lasti)->key()) return count();
00120   int i=_n2;
00121   int step2=_n2 >> 1;
00122   while(step2>0) {
00123     if(i>lasti) {
00124       i-=step2;
00125     } else if(k<=at(i)->key()) {
00126       if(k>at(i-1)->key()) break;
00127       i-=step2;
00128     } else {
00129       i+=step2;
00130     }
00131     step2=step2 >> 1;
00132   }
00133   return i;
00134 }
00135 
00136 template<class Key, class T>
00137 void SortedVector<Key, T>::insert(T * o)
00138 {
00139   int i=indexAfter(o->key());
00140   QVector<T *>::insert(i, o);
00141   while(_n2<count()) _n2=_n2 << 1;
00142 }
00143 
00144 template<class Key, class T>
00145 void SortedVector<Key, T>::remove(int index)
00146 {
00147   QVector<T *>::remove(index);
00148   int n2=_n2 >> 1;
00149   if(n2>0 && n2>=count()) {
00150     _n2=n2;
00151   }
00152 }
00153 
00154 template<class Key, class T>
00155 void SortedVector<Key, T>::clear()
00156 {
00157   QVector<T *>::clear();
00158 }
00159 
00160 } // namespace QGpCoreTools
00161 
00162 #endif // SORTEDVECTOR_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines