qalgorithms.h
上传用户:detong
上传日期:2022-06-22
资源大小:20675k
文件大小:17k
源码类别:

系统编程

开发平台:

Unix_Linux

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
  4. ** Contact: Qt Software Information (qt-info@nokia.com)
  5. **
  6. ** This file is part of the QtCore module of the Qt Toolkit.
  7. **
  8. ** Commercial Usage
  9. ** Licensees holding valid Qt Commercial licenses may use this file in
  10. ** accordance with the Qt Commercial License Agreement provided with the
  11. ** Software or, alternatively, in accordance with the terms contained in
  12. ** a written agreement between you and Nokia.
  13. **
  14. **
  15. ** GNU General Public License Usage
  16. ** Alternatively, this file may be used under the terms of the GNU
  17. ** General Public License versions 2.0 or 3.0 as published by the Free
  18. ** Software Foundation and appearing in the file LICENSE.GPL included in
  19. ** the packaging of this file.  Please review the following information
  20. ** to ensure GNU General Public Licensing requirements will be met:
  21. ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
  22. ** http://www.gnu.org/copyleft/gpl.html.  In addition, as a special
  23. ** exception, Nokia gives you certain additional rights. These rights
  24. ** are described in the Nokia Qt GPL Exception version 1.3, included in
  25. ** the file GPL_EXCEPTION.txt in this package.
  26. **
  27. ** Qt for Windows(R) Licensees
  28. ** As a special exception, Nokia, as the sole copyright holder for Qt
  29. ** Designer, grants users of the Qt/Eclipse Integration plug-in the
  30. ** right for the Qt/Eclipse Integration to link to functionality
  31. ** provided by Qt Designer and its related libraries.
  32. **
  33. ** If you are unsure which license is appropriate for your use, please
  34. ** contact the sales department at qt-sales@nokia.com.
  35. **
  36. ****************************************************************************/
  37. #ifndef QALGORITHMS_H
  38. #define QALGORITHMS_H
  39. #include <QtCore/qglobal.h>
  40. QT_BEGIN_HEADER
  41. QT_BEGIN_NAMESPACE
  42. QT_MODULE(Core)
  43. /*
  44.     Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API
  45.     and may be changed from version to version or even be completely removed.
  46. */
  47. namespace QAlgorithmsPrivate {
  48. template <typename RandomAccessIterator, typename T, typename LessThan>
  49. Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
  50. template <typename RandomAccessIterator, typename T>
  51. inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy);
  52. template <typename RandomAccessIterator, typename T, typename LessThan>
  53. Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan);
  54. template <typename RandomAccessIterator, typename T>
  55. inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &);
  56. template <typename RandomAccessIterator, typename T, typename LessThan>
  57. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
  58. template <typename RandomAccessIterator, typename T, typename LessThan>
  59. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
  60. template <typename RandomAccessIterator, typename T, typename LessThan>
  61. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan);
  62. }
  63. template <typename InputIterator, typename OutputIterator>
  64. inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest)
  65. {
  66.     while (begin != end)
  67.         *dest++ = *begin++;
  68.     return dest;
  69. }
  70. template <typename BiIterator1, typename BiIterator2>
  71. inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest)
  72. {
  73.     while (begin != end)
  74.         *--dest = *--end;
  75.     return dest;
  76. }
  77. template <typename InputIterator1, typename InputIterator2>
  78. inline bool qEqual(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
  79. {
  80.     for (; first1 != last1; ++first1, ++first2)
  81.         if (!(*first1 == *first2))
  82.             return false;
  83.     return true;
  84. }
  85. template <typename ForwardIterator, typename T>
  86. inline void qFill(ForwardIterator first, ForwardIterator last, const T &val)
  87. {
  88.     for (; first != last; ++first)
  89.         *first = val;
  90. }
  91. template <typename Container, typename T>
  92. inline void qFill(Container &container, const T &val)
  93. {
  94.     qFill(container.begin(), container.end(), val);
  95. }
  96. template <typename InputIterator, typename T>
  97. inline InputIterator qFind(InputIterator first, InputIterator last, const T &val)
  98. {
  99.     while (first != last && !(*first == val))
  100.         ++first;
  101.     return first;
  102. }
  103. template <typename Container, typename T>
  104. inline typename Container::const_iterator qFind(const Container &container, const T &val)
  105. {
  106.     return qFind(container.constBegin(), container.constEnd(), val);
  107. }
  108. template <typename InputIterator, typename T, typename Size>
  109. inline void qCount(InputIterator first, InputIterator last, const T &value, Size &n)
  110. {
  111.     for (; first != last; ++first)
  112.         if (*first == value)
  113.             ++n;
  114. }
  115. template <typename Container, typename T, typename Size>
  116. inline void qCount(const Container &container, const T &value, Size &n)
  117. {
  118.     qCount(container.constBegin(), container.constEnd(), value, n);
  119. }
  120. #if defined Q_CC_MSVC && _MSC_VER < 1300
  121. template <typename T>
  122. inline void qSwap(T &value1, T &value2)
  123. {
  124.     qSwap_helper<T>(value1, value2, (T *)0);
  125. }
  126. #else
  127. template <typename T>
  128. inline void qSwap(T &value1, T &value2)
  129. {
  130.     T t = value1;
  131.     value1 = value2;
  132.     value2 = t;
  133. }
  134. #endif
  135. #ifdef qdoc
  136. template <typename T>
  137. LessThan qLess()
  138. {
  139. }
  140. template <typename T>
  141. LessThan qGreater()
  142. {
  143. }
  144. #else
  145. template <typename T>
  146. class qLess
  147. {
  148. public:
  149.     inline bool operator()(const T &t1, const T &t2) const
  150.     {
  151.         return (t1 < t2);
  152.     }
  153. };
  154. template <typename T>
  155. class qGreater
  156. {
  157. public:
  158.     inline bool operator()(const T &t1, const T &t2) const
  159.     {
  160.         return (t2 < t1);
  161.     }
  162. };
  163. #endif
  164. template <typename RandomAccessIterator>
  165. inline void qSort(RandomAccessIterator start, RandomAccessIterator end)
  166. {
  167.     if (start != end)
  168.         QAlgorithmsPrivate::qSortHelper(start, end, *start);
  169. }
  170. template <typename RandomAccessIterator, typename LessThan>
  171. inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
  172. {
  173.     if (start != end)
  174.         QAlgorithmsPrivate::qSortHelper(start, end, *start, lessThan);
  175. }
  176. template<typename Container>
  177. inline void qSort(Container &c)
  178. {
  179. #ifdef Q_CC_BOR
  180.     // Work around Borland 5.5 optimizer bug
  181.     c.detach();
  182. #endif
  183.     if (!c.empty())
  184.         QAlgorithmsPrivate::qSortHelper(c.begin(), c.end(), *c.begin());
  185. }
  186. template <typename RandomAccessIterator>
  187. inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end)
  188. {
  189.     if (start != end)
  190.         QAlgorithmsPrivate::qStableSortHelper(start, end, *start);
  191. }
  192. template <typename RandomAccessIterator, typename LessThan>
  193. inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
  194. {
  195.     if (start != end)
  196.         QAlgorithmsPrivate::qStableSortHelper(start, end, *start, lessThan);
  197. }
  198. template<typename Container>
  199. inline void qStableSort(Container &c)
  200. {
  201. #ifdef Q_CC_BOR
  202.     // Work around Borland 5.5 optimizer bug
  203.     c.detach();
  204. #endif
  205.     if (!c.empty())
  206.         QAlgorithmsPrivate::qStableSortHelper(c.begin(), c.end(), *c.begin());
  207. }
  208. template <typename RandomAccessIterator, typename T>
  209. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
  210. {
  211.     // Implementation is duplicated from QAlgorithmsPrivate to keep existing code
  212.     // compiling. We have to allow using *begin and value with different types, 
  213.     // and then implementing operator< for those types.
  214.     RandomAccessIterator middle;
  215.     int n = end - begin;
  216.     int half;
  217.     while (n > 0) {
  218.         half = n >> 1;
  219.         middle = begin + half;
  220.         if (*middle < value) {
  221.             begin = middle + 1;
  222.             n -= half + 1;
  223.         } else {
  224.             n = half;
  225.         }
  226.     }
  227.     return begin;
  228. }
  229. template <typename RandomAccessIterator, typename T, typename LessThan>
  230. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
  231. {
  232.     return QAlgorithmsPrivate::qLowerBoundHelper(begin, end, value, lessThan);
  233. }
  234. template <typename Container, typename T>
  235. Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qLowerBound(const Container &container, const T &value)
  236. {
  237.     return QAlgorithmsPrivate::qLowerBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
  238. }
  239. template <typename RandomAccessIterator, typename T>
  240. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
  241. {
  242.     // Implementation is duplicated from QAlgorithmsPrivate.
  243.     RandomAccessIterator middle;
  244.     int n = end - begin;
  245.     int half;
  246.     while (n > 0) {
  247.         half = n >> 1;
  248.         middle = begin + half;
  249.         if (value < *middle) {
  250.             n = half;
  251.         } else {
  252.             begin = middle + 1;
  253.             n -= half + 1;
  254.         }
  255.     }
  256.     return begin;
  257. }
  258. template <typename RandomAccessIterator, typename T, typename LessThan>
  259. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
  260. {
  261.     return QAlgorithmsPrivate::qUpperBoundHelper(begin, end, value, lessThan);
  262. }
  263. template <typename Container, typename T>
  264. Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qUpperBound(const Container &container, const T &value)
  265. {
  266.     return QAlgorithmsPrivate::qUpperBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
  267. }
  268. template <typename RandomAccessIterator, typename T>
  269. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
  270. {
  271.     // Implementation is duplicated from QAlgorithmsPrivate.
  272.     qint64 l = 0;
  273.     qint64 r = end - begin - 1;
  274.     if (r < 0)
  275.         return end;
  276.     qint64 i = (l + r + 1) / 2;
  277.     while (r != l) {
  278.         if (value < begin[i])
  279.             r = i - 1;
  280.         else
  281.             l = i;
  282.         i = (l + r + 1) / 2;
  283.     }
  284.     if (begin[i] < value || value < begin[i])
  285.         return end;
  286.     else
  287.         return begin + i;
  288. }
  289. template <typename RandomAccessIterator, typename T, typename LessThan>
  290. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
  291. {
  292.     return QAlgorithmsPrivate::qBinaryFindHelper(begin, end, value, lessThan);
  293. }
  294. template <typename Container, typename T>
  295. Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value)
  296. {
  297.     return QAlgorithmsPrivate::qBinaryFindHelper(container.constBegin(), container.constEnd(), value, qLess<T>());
  298. }
  299. template <typename ForwardIterator>
  300. Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
  301. {
  302.     while (begin != end) {
  303.         delete *begin;
  304.         ++begin;
  305.     }
  306. }
  307. template <typename Container>
  308. inline void qDeleteAll(const Container &c)
  309. {
  310.     qDeleteAll(c.begin(), c.end());
  311. }
  312. /*
  313.     Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API
  314.     and may be changed from version to version or even be completely removed.
  315. */
  316. namespace QAlgorithmsPrivate {
  317. template <typename RandomAccessIterator, typename T, typename LessThan>
  318. Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan)
  319. {
  320. top:
  321.     int span = end - start;
  322.     if (span < 2)
  323.         return;
  324.     --end;
  325.     RandomAccessIterator low = start, high = end - 1;
  326.     RandomAccessIterator pivot = start + span / 2;
  327.     if (lessThan(*end, *start))
  328.         qSwap(*end, *start);
  329.     if (span == 2)
  330.         return;
  331.     if (lessThan(*pivot, *start))
  332.         qSwap(*pivot, *start);
  333.     if (lessThan(*end, *pivot))
  334.         qSwap(*end, *pivot);
  335.     if (span == 3)
  336.         return;
  337.     qSwap(*pivot, *end);
  338.     while (low < high) {
  339.         while (low < high && lessThan(*low, *end))
  340.             ++low;
  341.         while (high > low && lessThan(*end, *high))
  342.             --high;
  343.         if (low < high) {
  344.             qSwap(*low, *high);
  345.             ++low;
  346.             --high;
  347.         } else {
  348.             break;
  349.         }
  350.     }
  351.     if (lessThan(*low, *end))
  352.         ++low;
  353.     qSwap(*end, *low);
  354.     qSortHelper(start, low, t, lessThan);
  355.     start = low + 1;
  356.     ++end;
  357.     goto top;
  358. }
  359. template <typename RandomAccessIterator, typename T>
  360. inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy)
  361. {
  362.     qSortHelper(begin, end, dummy, qLess<T>());
  363. }
  364. template <typename RandomAccessIterator>
  365. Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end)
  366. {
  367.     --end;
  368.     while (begin < end)
  369.         qSwap(*begin++, *end--);
  370. }
  371. template <typename RandomAccessIterator>
  372. Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end)
  373. {
  374.     qReverse(begin, middle); 
  375.     qReverse(middle, end); 
  376.     qReverse(begin, end); 
  377. }
  378. template <typename RandomAccessIterator, typename T, typename LessThan>
  379. Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, T &t, LessThan lessThan)
  380. {
  381.     const int len1 = pivot - begin;
  382.     const int len2 = end - pivot;
  383.     if (len1 == 0 || len2 == 0)
  384.         return;
  385.     if (len1 + len2 == 2) {
  386.         if (lessThan(*(begin + 1), *(begin)))
  387.             qSwap(*begin, *(begin + 1));
  388.         return;
  389.     }
  390.     RandomAccessIterator firstCut;
  391.     RandomAccessIterator secondCut;
  392.     int len2Half;
  393.     if (len1 > len2) {
  394.         const int len1Half = len1 / 2;
  395.         firstCut = begin + len1Half;
  396.         secondCut = qLowerBound(pivot, end, *firstCut, lessThan);
  397.         len2Half = secondCut - pivot;
  398.     } else {
  399.         len2Half = len2 / 2;
  400.         secondCut = pivot + len2Half;
  401.         firstCut = qUpperBound(begin, pivot, *secondCut, lessThan);
  402.     }
  403.     qRotate(firstCut, pivot, secondCut);
  404.     const RandomAccessIterator newPivot = firstCut + len2Half;
  405.     qMerge(begin, firstCut, newPivot, t, lessThan);
  406.     qMerge(newPivot, secondCut, end, t, lessThan);
  407. }
  408. template <typename RandomAccessIterator, typename T, typename LessThan>
  409. Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &t, LessThan lessThan)
  410. {
  411.     const int span = end - begin;
  412.     if (span < 2)
  413.        return;
  414.        
  415.     const RandomAccessIterator middle = begin + span / 2;
  416.     qStableSortHelper(begin, middle, t, lessThan);
  417.     qStableSortHelper(middle, end, t, lessThan);
  418.     qMerge(begin, middle, end, t, lessThan);
  419. }
  420. template <typename RandomAccessIterator, typename T>
  421. inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy)
  422. {
  423.     qStableSortHelper(begin, end, dummy, qLess<T>());
  424. }
  425. template <typename RandomAccessIterator, typename T, typename LessThan>
  426. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
  427. {
  428.     RandomAccessIterator middle;
  429.     int n = end - begin;
  430.     int half;
  431.     while (n > 0) {
  432.         half = n >> 1;
  433.         middle = begin + half;
  434.         if (lessThan(*middle, value)) {
  435.             begin = middle + 1;
  436.             n -= half + 1;
  437.         } else {
  438.             n = half;
  439.         }
  440.     }
  441.     return begin;
  442. }
  443. template <typename RandomAccessIterator, typename T, typename LessThan>
  444. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
  445. {
  446.     RandomAccessIterator middle;
  447.     int n = end - begin;
  448.     int half;
  449.     while (n > 0) {
  450.         half = n >> 1;
  451.         middle = begin + half;
  452.         if (lessThan(value, *middle)) {
  453.             n = half;
  454.         } else {
  455.             begin = middle + 1;
  456.             n -= half + 1;
  457.         }
  458.     }
  459.     return begin;
  460. }
  461. template <typename RandomAccessIterator, typename T, typename LessThan>
  462. Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
  463. {
  464.     qint64 l = 0;
  465.     qint64 r = end - begin - 1;
  466.     if (r < 0)
  467.         return end;
  468.     qint64 i = (l + r + 1) / 2;
  469.     while (r != l) {
  470.         if (lessThan(value, begin[i]))
  471.             r = i - 1;
  472.         else
  473.             l = i;
  474.         i = (l + r + 1) / 2;
  475.     }
  476.     if (lessThan(begin[i], value) || lessThan(value, begin[i]))
  477.         return end;
  478.     else
  479.         return begin + i;
  480. }
  481. } //namespace QAlgorithmsPrivate
  482. QT_END_NAMESPACE
  483. QT_END_HEADER
  484. #endif // QALGORITHMS_H