C++11多线程希尔排序

2380阅读 0评论2014-11-01 AoyamaRyo
分类:C/C++

        用惯了Qt的QThread,爱之恨之。Qt的“信号与槽“模型,当然比纯C++用起来更顺手,对象的跨线程通信也很自然。另一面,用QThread创建 一个线程却不如C便捷。要么需要继承QThread,而后重载run函数,在其中实现逻辑功能。要么需要继承QObject类,在该类中实现逻辑功能,而 后该类的对象调用moveToThread(QThread &thrd),把该对象移动到新线程空间。C++11的thread却很方便。
        突然发现我大概要从Qt回归C++了。对C++的孤陋寡闻,大概是拜Qt所赐吧。它太强大了,以至于无需去了解其他东西。

        复习数据结构,发现希尔排序、快速排序先天为多线程而生。希尔排序很直观,每趟排序中各个子列放在各自的线程里执行,下一趟依赖上一趟的结果,随趟数增多 并发度减小。快排要灵活一些,数据集被不断的二分,可以使越来越多的线程参与排序。所以,希尔排序从N个线程递减至1个线程,快排从1个线程递增至N个线 程,N为处理器core总数。
        粗略用C++11的Thread类实现了一下希尔排序。快排,大概需要先实现个线程池,方便分发任务。

        Thread支持lambda函数,这可真是方便到家了。

1、简陋地做一个类把数组按线性映射成N个子列,书写上方便一些:

点击(此处)折叠或打开

  1. #ifndef SHELLARRAY_H
  2. #define SHELLARRAY_H

  3. #include <exception>
  4. #include <string>
  5. #include <sstream>
  6. typedef std::string string;
  7. #include <QDebug>

  8. class ShellSortException:public std::exception{
  9.     public :
  10.         ShellSortException(string msg){m_sMsg = msg;}
  11.         const char* what(){return m_sMsg.data();}
  12.         ~ShellSortException(){}
  13.     private:
  14.         string m_sMsg;
  15. };

  16. void inline throwException(const string &errMsg){
  17.     std::stringstream errstm;
  18.     errstm << "err:" << errMsg << " @" << __FILE__ << ":"
  19.            <<__LINE__;
  20.     throw ShellSortException(errstm.str());
  21. }

  22. /*
     * ShellArray  ----  A rough but convenient  array class which is able to
     *                          reflect a numerical array to several subset.
     * Note: this is an incomplete class which cann't be used in program,
     * & maybe it will be consummated with thread-safe, copy, shadow copy ,etc later.
    */


  1. template<class Type>
  2. class ShellArray
  3. {
  4. public:
  5.     explicit ShellArray():m_nUpIdx(0){
  6.     }
  7.     bool initialize(Type *data,int size,int idx=0,int period=1){
  8.         if(nullptr == data || size < 0 || period < 0 || idx < 0){
  9.             throwException("Invalid source data information!");
  10.         }
  11.         m_ptData = data;
  12.         m_nOffset = idx;
  13.         m_nPeriod = period;

  14.         m_nUpIdx = size / period - 1;
  15.         if(idx < size % period)
  16.             m_nUpIdx += 1;
  17.         m_nSize = m_nUpIdx + 1;
  18.         return true;
  19.     }
  20.    Type &operator [](int n){
  21.         if(n > m_nUpIdx)
  22.             throw ShellSortException("err: index over upper limit!");
  23.         return m_ptData[n * m_nPeriod + m_nOffset];
  24.     }
  25.    int size(){
  26.        return (m_nUpIdx + 1);
  27.    }
  28. private:
  29.     int m_nOffset;
  30.     int m_nUpIdx;
  31.     int m_nPeriod;
  32.     int m_nSize;
  33.     Type *m_ptData;
  34. };
  35. #endif // SHELLARRAY_H
2、希尔排序的多线程实现:

点击(此处)折叠或打开

  1. #ifndef SHELLSORT_H
  2. #define SHELLSORT_H

  3. #include <thread>
  4. #include <vector>
  5. typedef std::thread thread;
  6. #include "shellarray.h"

  7. #define CORE_CNT 4
  8. #define MULTITHREAD_THRESHOLD 10

  9. template<class Type>
  10. class ShellSort final
  11. {
  12. public:
  13.     explicit ShellSort(Type *data ,int size);
  14.     int sort();
  15.     static int insertSort(ShellArray<Type> &dArr,int n);
  16. private:
  17.     Type *m_ptData;
  18.     int m_nSize;
  19.     int m_nThreadsCnt;
  20. };

  21. template <class Type>
  22. ShellSort<Type>::ShellSort(Type *data,int size){
  23.     if(nullptr == data || size < 0){
  24.         throw ShellSortException("err: ShellSort with a invalid data pointer or a invalid size!");
  25.     }
  26.     if(size < MULTITHREAD_THRESHOLD)
  27.         m_nThreadsCnt = 1;
  28.     else
  29.         m_nThreadsCnt = CORE_CNT;
  30.     m_nSize = size;
  31.     m_ptData = data;
  32. }

  33. template <class Type>
  34.  int ShellSort<Type>::sort(){
  35.     /* There are so many data and more than one cores that we'd
  36.      * better use multi-thread mode.
  37.      */
  38.      std::vector<std::thread*> tmpVector;
  39.      int step = 1;
  40.      while(m_nThreadsCnt > 1){
  41.         for(int i = 0; i < m_nThreadsCnt; ++i){
  42.             std::thread *tThread = new std::thread([=](){
  43.                 ShellArray<Type> tmpShArr;
  44.                 tmpShArr.initialize(this->m_ptData,
  45.                                     this->m_nSize,
  46.                                     i,
  47.                                     this->m_nThreadsCnt);
  48.                 this->insertSort(tmpShArr,tmpShArr.size());
  49.             });
  50.             tmpVector.push_back(tThread);
  51.         }
  52.         for(auto &i : tmpVector){
  53.             i->join();
  54.             delete i;
  55.         }
  56.         tmpVector.clear();
  57.         m_nThreadsCnt -= step;
  58.         ++step;
  59.     }
  60.      ShellArray<Type> tArray;
  61.      tArray.initialize(m_ptData,m_nSize);
  62.      insertSort(tArray,tArray.size());
  63.      return 0;
  64. }

  65. template<class Type>
  66. int ShellSort<Type>::insertSort(ShellArray<Type> &dArr, int n){
  67.     try{
  68.     Type tmp;
  69.     int j = 0;
  70.     for(int i = 1; i < n; ++i ){
  71.         tmp = dArr[i];
  72.         j = i - 1;
  73.         while(j >= 0 && tmp < dArr[j]){
  74.             dArr[j+1] = dArr[j];
  75.             --j;
  76.         }
  77.         dArr[j+1] = tmp;
  78.     }
  79.     }catch(std::exception &e){
  80.         string _str = e.what();
  81.         qDebug() << _str.data();
  82.     }
  83.     return 0;
  84. }

  85. #endif // SHELLSORT_H

3、测试:

点击(此处)折叠或打开

  1. #include <QDebug>
  2. #include "shellsort.h"

  3. int main(int argc, char *argv[])
  4. {
  5.     int arr[88888];
  6.     for(int i = 0; i < 88888; ++i)
  7.         arr[i] = 88888-i;
  8.     ShellArray<int> sarr;
  9.     sarr.initialize(&arr[0],88888);

  10.     try{
  11.     ShellSort<int> ss(&arr[0],88888);
  12.      ss.sort();
  13.      std::stringstream strstm;
  14.     for(int i = 0; i < 88888; ++i)
  15.         strstm << arr[i] << " ";
  16.     qDebug() << strstm.str().data();
  17.     }catch(ShellSortException &e){
  18.         qDebug() << e.what();
  19.     }

  20.     return 0;
  21. }


上一篇:Qt5.3编写Android定时器
下一篇:没有了