1. 程式人生 > 其它 >Qt 多執行緒程式設計、自動排序

Qt 多執行緒程式設計、自動排序

需求: QT產生隨機數10000個 通過多執行緒(為了是主頁面不卡頓) 一個執行緒氣泡排序、一個執行緒快速排序,看看哪個演算法更快。

程式執行結果是這樣的

mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QVector>
//生成隨機數
class Generate : public QThread
{
    Q_OBJECT
public:
    explicit Generate(QObject *parent = nullptr);

    //槽函式用來接收主執行緒給的num值
    void recvNum(int num);

//受保護的
protected:
    void run() override;

    //訊號
signals:
    void sendArray(QVector<int>);

private:
    int m_num;

};

//氣泡排序
class BubbleSort : public QThread
{
    Q_OBJECT
public:
    explicit BubbleSort(QObject *parent = nullptr);

    void recvArray(QVector<int> list);

protected:
    void run() override;

signals:
    void finish(QVector<int> num);

private:
    QVector<int> m_list;

};

//快速排序
class QuickSort : public QThread
{
    Q_OBJECT
public:
    explicit QuickSort(QObject *parent = nullptr);

    void recvArray(QVector<int> list);

protected:
    void run() override;

private:
    void quickSort(QVector<int> &list, int l, int r);

signals:
    void finish(QVector<int> num);

private:
    QVector<int> m_list;

};

#endif // MYTHREAD_H

  mythread.cpp

#include "mythread.h"
#include <QElapsedTimer>
#include <QDebug>

Generate::Generate(QObject *parent) : QThread(parent)
{

}

void Generate::recvNum(int num){
    m_num = num;
}

void Generate::run()
{
    qDebug()<<"生成隨機數的執行緒地址:"<<QThread::currentThread();
    QElapsedTimer time;
    QVector<int> list;
    //開始時間
    time.start();
    for(int i=0; i < m_num; i++){
        //qrand()%100000  對10萬取餘、生成10萬以內的隨機數
        list.push_back(qrand()%100000);
    }
    //總用時
    int milsec = time.elapsed();
    qDebug()<<"生成"<<m_num<<"個隨機數總用時間:"<<milsec<<"毫秒";

    //傳送資料List通過sendArray這個方法
    emit sendArray(list);
}



BubbleSort::BubbleSort(QObject *parent) : QThread(parent)
{

}

//接受執行緒傳送來的 STL容器vector
void BubbleSort::recvArray(QVector<int> list)
{
    m_list = list;
}

void BubbleSort::run()
{
    qDebug() << "氣泡排序的執行緒的執行緒地址: " << QThread::currentThread();
    QElapsedTimer time;
    time.start();
    int temp;
    for(int i=0; i<m_list.size(); ++i)
    {
        for(int j=0; j<m_list.size()-i-1; ++j)
        {
            if(m_list[j] > m_list[j+1])
            {
                temp = m_list[j];
                m_list[j] = m_list[j+1];
                m_list[j+1] = temp;
            }
        }
    }
    int milsec = time.elapsed();
    qDebug() << "氣泡排序用時" << milsec << "毫秒";
    emit finish(m_list);
}


QuickSort::QuickSort(QObject *parent) : QThread(parent)
{

}

void QuickSort::recvArray(QVector<int> list)
{
    m_list = list;
}

void QuickSort::run()
{
    qDebug() << "快速排序的執行緒的執行緒地址: " << QThread::currentThread();
    QElapsedTimer time;
    time.start();
    quickSort(m_list, 0, m_list.size()-1);
    int milsec = time.elapsed();
    qDebug() << "快速排序用時" << milsec << "毫秒";
    emit finish(m_list);
}

void QuickSort::quickSort(QVector<int> &s, int l, int r)
{
    if (l < r)
    {
        int i = l, j = r;
        // 拿出第一個元素, 儲存到x中,第一個位置成為一個坑
        int x = s[l];
        while (i < j)
        {
            // 從右向左找小於x的數
            while (i < j && s[j] >= x)
            {
                //左移, 直到遇到小於等於x的數
                j--;
            }
            if (i < j)
            {
                //將右側找到的小於x的元素放入左側坑中, 右側出現一個坑
                //左側元素索引後移
                s[i++] = s[j];
            }

            // 從左向右找大於等於x的數
            while (i < j && s[i] < x)
            {
                //右移, 直到遇到大於x的數
                i++;
            }
            if (i < j)
            {
                //將左側找到的元素放入右側坑中, 左側出現一個坑
                //右側元素索引向前移動
                s[j--] = s[i];
            }
        }
        //此時 i=j,將儲存在x中的數填入坑中
        s[i] = x;
        quickSort(s, l, i - 1); // 遞迴呼叫
        quickSort(s, i + 1, r);
    }
}

  

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "mythread.h"


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

signals:
    //主執行緒傳送給子執行緒的訊號、產生多少個隨機數
    void starting(int num);

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;


};
#endif // WIDGET_H

  widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);



    //建立子執行緒物件
    Generate* gen = new Generate(this);
    BubbleSort* bubble = new BubbleSort(this);
    QuickSort* quick = new QuickSort(this);

    /*
    訊號槽、當程式執行開始、
    this當前程式
    &Widget當前的視窗類,
    gen 生成隨機數的子程序物件、
    需要呼叫recvNum槽函式接受主視窗發來的生成多少隨機數
    */
    connect(this,&Widget::starting,gen,&Generate::recvNum);


//    connect(this,SIGNAL(starting(int)),gen,SLOT(recvNum(int)));


    //啟動子執行緒
    connect(ui->start,&QPushButton::clicked,this,[=](){


        //子執行緒需要產生多少個隨機數
        emit starting(10000);
        gen->start();
    });

    //傳送QVector容器 給冒泡和快拍兩個
    connect(gen, &Generate::sendArray, bubble, &BubbleSort::recvArray);
    connect(gen, &Generate::sendArray, quick, &QuickSort::recvArray);

    //拿到主執行緒發過來的隨機數、通過sendArray發過來
    connect(gen,&Generate::sendArray,this,[=](QVector<int> list){
        bubble->start();
        quick->start();


        for(int i=0; i<list.size();++i)
        {
            ui->randomList->addItem(QString::number(list.at(i)));
        }

    });


    connect(bubble, &BubbleSort::finish, this, [=](QVector<int> list){
        for(int i=0; i<list.size(); ++i)
        {
            ui->bubbleList->addItem(QString::number(list.at(i)));
        }
    });
    connect(quick, &QuickSort::finish, this, [=](QVector<int> list){
        for(int i=0; i<list.size(); ++i)
        {
            ui->quickList->addItem(QString::number(list.at(i)));
        }
    });
}

Widget::~Widget()
{
    delete ui;
}