QT快速排序法

在对大量数据进行排序时耗时比较大,采用快速排序法相对较快。下面代码是对ROW*COL个数据进行排序,fDtaBuffer是存储数据的buffer,排序后的数据也放入该buffer。该代码是在网上找来的,下面会把参考代码贴上,谢谢这位高手分享代码。

 

void MainWindow::goQuick()
{
quickSort(0,COL*ROW-1); //进行快排
}

void MainWindow::quickSort(int l, int r)
{
if(l < r){
        int mid = quickQartition(l,r);  //得到分割数
        quickSort(l,mid);       //再次进行快排
        quickSort(mid+1,r);
}
}
//将数组的最左边的数据为分割数,将比分割数大的数放在分割数的右边,小的放在左边
//返回分割数最后所在的位子
int MainWindow::quickQartition(int l, int r)
{
float t = fDtaBuffer[l]; //t为分割数
    while(l < r){
        while(l < r && fDtaBuffer[r] >= t)//如果最右边的数大于分割数,则寻次右边的数进行比较
            r --;
        quickSwap(l,r); //如果分割数比右边的数要大,则将俩者交换位子
        while(l < r && fDtaBuffer[l] <= t)//同上
            l ++;
        quickSwap(l,r);
   
}
    return l;
}

void MainWindow::quickSwap(int one, int two)
{
float temp = fDtaBuffer[one];
    fDtaBuffer[one] = fDtaBuffer[two];
    fDtaBuffer[two] = temp;
}

网上参考代码如下:
1、bubble.h
#ifndef BUBBLE_H
#define BUBBLE_H

#include <QObject>
#include <QThread>
#include <QTime>
#include <QVector>
#include <QtAlgorithms>
class Bubble : public QObject
{
    Q_OBJECT
public:
    //explicit Bubble(int l,int m,int mD,int *data,QObject *parent = nullptr);
    explicit Bubble(int l,int m,int mD,int *data,QObject *parent = NULL);
    void goBubble();            //处理冒泡排序算法--1
    void goInsertion();         //处理插入排序算法--2
    void goHeap();              //堆排序--3
    void heapAdjust(int i, int len);
    void goShell();             //希尔排序--4
    void goChoice();            //选择排序--5
    void goMerge();             //归并排序--6
    void mergeSort(int l,int r);
    void merge(int l,int m, int r);
    void goBucket();            //桶排序--7
    void goQuick();             //快速排序--8
    void quickSort(int l,int r);
    int quickQartition(int l,int r);
    void quickSwap(int one,int two);
    void goRadix();             //基数排序--9
    void rand();                //随机产生数据
    void run();
signals:
    void bubbleSignal(int cur); //发送当前排序的位子
private:
    int length;     //数组的长度
    int *data;      //数组
    int max;        //单个数据的最大值
    int cur;        //排序当前处理的位置
    int mDelay;     //延时时间,方便动态展示
public slots:
};

#endif // BUBBLE_H


2、bubble.cpp
#include "bubble.h"

Bubble::Bubble(int l, int m, int mD, int *data, QObject *parent) : QObject(parent)
{
    qsrand(static_cast<uint>(QTime::currentTime().msec())); //初始化随机种子
    length = l;
    max = m;
    mDelay = mD;
    this->data = data;
    rand();
}

void Bubble::goBubble()
{
    bool flag = false;  //供判断是否已经完成
    for(int i = 1; i < length && !flag; i ++){
        flag = true;
        for(int j = 0; j < length-i; j++){
            if(data[j] > data[j+1]){
                int t = data[j];
                data[j] = data[j+1];
                data[j+1] = t;
                flag = false;
            }
            bubbleSignal(j);
            QThread::msleep(static_cast<unsigned int>(mDelay));
        }
    }
    for(int i = 0; i < length; i++){
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}

void Bubble::goInsertion()
{
    //直接插入排序
    for (int i = 1; i < length;i++) {
        int j ;
        if(data[i] < data[i - 1]){
            int temp = data[i];
            for (j = i - 1;j>= 0&&temp < data[j];j--) {
                data[j+1] = data[j];
                bubbleSignal(j);
                QThread::msleep(static_cast<unsigned int>(mDelay));
            }
            data[j + 1] = temp;
            bubbleSignal(j);
            QThread::msleep(static_cast<unsigned int>(mDelay));
        }
    }
    for(int i = 0; i < length; i++){
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}

void Bubble::goHeap()
{
    // 初始化堆
    // length / 2 - 1是二叉树中最后一个非叶子结点的序号
    for (int i = length / 2 -1; i >= 0; i--)
    {
        heapAdjust(i,length);
        cur = i;
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
    // 交换堆顶元素和最后一个元素
    for (int i = length-1; i >= 0; i--)
    {
        int temp;
        temp = data[i];
        data[i] = data[0];
        data[0] = temp;
        heapAdjust(0,i);
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
    for(int i = 0; i < length;i++){
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}
//重新构建大顶堆
void Bubble::heapAdjust(int i, int len)
{
    int temp = data[i];
    for(int j = 2*i+1;j <len; j=j*2+1){
        if(j < len-1 && data[j] < data[j + 1]){
            ++j;
        }
        if(temp >= data[j])
            break;
        data[i] = data[j];
        i = j;
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
    data[i] = temp;
}

void Bubble::goShell()
{
    int increasement = length;
    int i, j, k;
    do
    {
        // 确定分组的增量
        increasement = increasement / 3 + 1;
        for (i = 0; i < increasement; i++)
        {
            for (j = i + increasement; j < length; j += increasement)
            {//这里跟插入排序的思想很像,通过挪位来插入值
                if (data[j] < data[j - increasement])
                {
                    int temp = data[j];
                    for (k = j - increasement; k >= 0 && temp < data[k]; k -= increasement)
                    {
                        data[k + increasement] = data[k];
                        bubbleSignal(k);
                        QThread::msleep(static_cast<unsigned int>(mDelay));
                    }
                    data[k + increasement] = temp;

                }
            }
        }
    } while (increasement > 1);
    for(int i = 0; i < length;i++){
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}

void Bubble::goChoice()
{
    for (int i = 0;i < length; i++) {   //先进行整体循环遍历
        int index = i;                  //当前比较的位子
        for (int j = i+1;j < length; j++) {
            if(data[index] > data[j]){  //在余下的数找到其最小的数
                index = j;
                bubbleSignal(j);
                QThread::msleep(static_cast<unsigned int>(mDelay));
            }
        }
        if(index == i)  //没有找到,即表示当前数是余下数的最小数
            continue;
        else {          //找到,即将当前位子的数与找到的数进行交换
            int temp = data[index];
            data[index] = data[i];
            data[i] = temp;
        }
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
    for(int i = 0; i < length;i++){
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}
/*举个栗子 有数据 12,9,11,13,5,7
 * 先进行递归将数组分为长度尽可能相等的两部分
 *      第一次递归    第二次递归  第三次递归
 *      12,9,11 -->  12,9           经过mergeSort递归到底
 *                          --> 9,12  在merge中进行排序
 *                     11            返回上一层递归中,向右递归到底
 *                          --> 9,11,12     在merge中进行排序
 *      13,5,7 --->  13,5 --> 5,13 --> 5,7,13   同理上
 *      -->5,7,9,11,12,13           得到最终排序
 *  最终会在动画看到先是排好一个小山峰(9,11,12)然后紧接着又排好一个小山峰(5,7,13)
 *  然后俩个小山峰进行在merge中进行归并就得出了大山峰(5,7,9,11,12,13)
 */
void Bubble::goMerge()
{
    mergeSort(0,length-1);
    for(int i = 0; i < length;i++){
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}
//将数组分为尽可能相等的俩个部分
void Bubble::mergeSort(int l, int r)
{
    if(l < r){
        int m = l + (r-l)/2;
        mergeSort(l,m);
        mergeSort(m+1,r);
        merge(l,m,r);
    }
}
//对于俩个被分开的两个部分进行整个归并排序
void Bubble::merge(int l, int m, int r)
{
    int n1 = m-l+1;
    int n2 = r - m;
    int L[n1],R[n2];
    for(int i = 0; i < n1; i++){
        L[i] = data[l+i];       //存数组l到m之间的数据
    }
    for(int i = 0; i < n2; i++){
        R[i] = data[m + 1 + i]; //存数组m+1到r之间的数据
    }
    int k = l,i = 0, j = 0;
    while(i < n1 && j < n2){    //将两个部分进行排序
        if(L[i] <= R[j]){
            data[k] = L[i];
            i++;
        }
        else{
            data[k] = R[j];
            j++;
        }
        k++;
        bubbleSignal(k);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
    while(i < n1){              //将L中剩余的值放入data中
        data[k] = L[i];
        i ++;
        k ++;
        bubbleSignal(k);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
    while(j < n2){
        data[k] = R[j];         //将R中剩余的值放入data中
        j ++;
        k ++;
        bubbleSignal(k);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}

void Bubble::goBucket()
{
    int max = data[0];
    for(int i = 1 ;i < length; i ++){
        if(data[i] > max)
            max = data[i];
    }
    max ++;                         //加一是为了防止数组越界
    QVector<int> b[10];             //假设放十个桶,这个可以自定义
    for (int i = 0; i < length; i++) {
        int bi = 10*data[i]/max;
        b[bi].push_back(data[i]);   //然后将数据以10为间隔放置数据
    }

    int c = 0,len =0;   //c用来表示新放入数组的位子,len表示经历各个桶的累长度
    for(int i = 0; i < 10; i ++){   //将data的数据进行重新放入,方便动图观看
        for(int j = 0; j < b[i].size(); j++){
            data[c++] = b[i].at(j);
        }
    }
    c = 0;
    for(int i = 0; i < 10; i ++){
        //这里本想使用sort库来实现各个桶内的排序方便偷个懒的
        //可是那样就不好动图表现了,就用了直接插入排序来代替了,好像也不是很好看
        //std::sort(b[i].begin(),b[i].end());
        for(int j = 1+len; j < b[i].size()+len; j++){
            //直接插入排序
            int k;
            if(data[j] < data[j - 1]){
                int temp = data[j];
                for (k = j - 1;k>= len&&temp < data[k];k--) {
                    data[k+1] = data[k];
                    bubbleSignal(k);
                    QThread::msleep(static_cast<unsigned int>(mDelay));
                }
                data[k+1] = temp;
//                bubbleSignal(k + len);
//                QThread::msleep(static_cast<unsigned int>(mDelay));
            }
        }
        len += b[i].size();
    }
    for(int i = 0; i < length;i++){
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}

void Bubble::goQuick()
{
    quickSort(0,length-1);      //进行快排
    for(int i = 0; i < length;i++){
        bubbleSignal(i);
        QThread::msleep(static_cast<unsigned int>(mDelay));
    }
}

void Bubble::quickSort(int l, int r)
{
    if(l < r){
        int mid = quickQartition(l,r);  //得到分割数
        quickSort(l,mid);       //再次进行快排
        quickSort(mid+1,r);
    }
}
//将数组的最左边的数据为分割数,将比分割数大的数放在分割数的右边,小的放在左边
//返回分割数最后所在的位子
int Bubble::quickQartition(int l, int r)
{
    int t = data[l];    //t为分割数
    while(l < r){
        while(l < r && data[r] >= t)//如果最右边的数大于分割数,则寻次右边的数进行比较
            r --;
        quickSwap(l,r); //如果分割数比右边的数要大,则将俩者交换位子
        while(l < r && data[l] <= t)//同上
            l ++;
        quickSwap(l,r);
    }
    return l;
}

void Bubble::quickSwap(int one, int two)
{
    int temp = data[one];
    data[one] = data[two];
    data[two] = temp;
    bubbleSignal(one);
    QThread::msleep(static_cast<unsigned int>(mDelay));
}

void Bubble::goRadix()
{
    int max = data[0];      //寻找最大值,由此得知所需的位数
    for(int i = 1 ; i < length; i++){
        if(data[i] > max)
            max = data[i];
    }
    //以个、十、百....的位的数目来遍历
    for (int exp = 1; max/exp > 0; exp *= 10) {
        int output[length];
        int count[10] = {0};
        for(int i = 0; i < length; i++){//得到每个位数上的数字的个数
            count[(data[i]/exp)%10]++;  //例如在{1,2,11,13,4}个位为一的有2个,个位为2的有1,...
        }
        //然后将所得到的所有位数进行累加求和,方便判断是在output[]的那个位子上
        for(int i = 1; i < 10; i++){
            count[i] += count[i - 1];
        }
        for(int i = length -1; i >= 0; i--){
            output[count[(data[i]/exp)%10] - 1]= data[i];
            count[(data[i]/exp)%10] --;
            bubbleSignal(i);
            QThread::msleep(static_cast<unsigned int>(mDelay));
        }
        for(int i = 0; i < length; i++){
            data[i] = output[i];    //将此趟排序好的数据赋值回去
            bubbleSignal(i);
            QThread::msleep(static_cast<unsigned int>(mDelay));
        }
    }
}

void Bubble::rand()
{
    if(data == nullptr)
        throw "数据不合理";
    bool flag[length];
    for(int i = 0; i < length; i++)
        flag[i] = false;
    for(int i = 0; i < length ; i++){
        while(1){
            int r = qrand()%max + 1;
            if(flag[r-1] == false){
                data[i] = r;
                flag[r-1]= true;
                break;
            }
        }
    }
}

void Bubble::run()
{
    goBubble();
    QThread::sleep(1);
    rand();
    goShell();
    QThread::sleep(1);
    rand();
    goBucket();
    QThread::sleep(1);
    rand();
    goHeap();
    QThread::sleep(1);
    rand();
    goInsertion();
    QThread::sleep(1);
    rand();
    goShell();
    QThread::sleep(1);
    rand();
    goQuick();
    QThread::sleep(1);
    rand();
    goRadix();
    QThread::sleep(1);
    rand();
    goMerge();
}
3、widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "bubble.h"
#include <QPainter>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    //explicit Widget(QWidget *parent = nullptr);
    explicit Widget(QWidget *parent = NULL);
    ~Widget();
    void paintEvent(QPaintEvent *e);
signals:
    void start();       //开启子线程
public slots:
    void deal(int c);   //处理来自子线程的消息
private:
    Ui::Widget *ui;
    int blockH;     //绘图方块的高
    int blockW;     //绘图方块的宽
    int length;     //数组长度
    int *data;      //数组
    int cur;        //排序的位子
    QThread *thread;
    Bubble *bubble;
};

#endif // WIDGET_H

4、widget.cpp
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    length = 140;
    blockH = 6;
    blockW = 8;
    data = new int [length];
    cur = 0;
    bubble = new Bubble(length,length,20,data);

    setGeometry(0,0,length*blockW,length*blockH);

    thread = new QThread(this);
    bubble->moveToThread(thread);
    //进行信号与槽的绑定
    connect(bubble,&Bubble::bubbleSignal,this,&Widget::deal);
    connect(this,&Widget::start,bubble,&Bubble::run);
    thread->start();    //开启子线程
    emit start();       //运行子线程的goBubble函数
}
void Widget::paintEvent(QPaintEvent *){
    QPainter painter;
    if(data == nullptr)
        return ;
    painter.begin(this);
    for(int i = 0; i< length;i++){
        QRect rect(i*blockW,height()-data[i]*blockH,
                   blockW - 1,data[i]*blockH);
        if(i == cur){
            painter.fillRect(rect,Qt::blue);
        }else {
            painter.fillRect(rect,Qt::red);
        }
    }
    painter.end();
}

void Widget::deal(int c)
{
    cur = c;
    repaint();  //进行重绘
}
Widget::~Widget()
{
    delete [] data;
    thread->quit();     //结束子线程
    thread->wait();     //回收子线程资源
    delete ui;
}

5、main.cpp
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}






 

posted on 2019-06-04 14:42  crystal_rachel  阅读(741)  评论(0编辑  收藏  举报

导航