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) 编辑 收藏 举报