记一次表格数据排序优化(二)--std::sort + 运行模式光速排序

目录

思路

代码

效果


思路

沿着前面博客的思路,现在用std::sort代替自己写的冒泡算法。这样的好处有二:

1 sort函数的复杂度是O(nlog(n)),而冒泡算法的复杂度是O(n^2)

2 从上一篇的排序代码,可以看到,使用了一个while循环,内嵌一个for循环,for循环内部还有一个if判断。一般来说,循环内部有if分支将影响CPU的分支预测,使得流水线(pipeline)负荷不满,拉低运行效率。使用sort则不会有此问题。

3 抛开排序之前的预处理遍历不谈,自写的冒泡算法在cache-miss上没有做任何考虑。std::sort在这方面可能也有所优化

代码

这里只修改了类ModelFreqDetect

#ifndef MODELFREQDETECT_H
#define MODELFREQDETECT_H

#include <QAbstractTableModel>

class ModelFreqDetect : public QAbstractTableModel
{
    Q_OBJECT
public:
    ModelFreqDetect(QStringList, int, int, QObject * parent = 0);

    int iAddRows(bool bLeft, std::vector<QStringList> &);
    void                                vSortByColumn(int iCol);
protected:
    int rowCount(const QModelIndex &) const override;

    int columnCount(const QModelIndex &) const override;

    QVariant data(const QModelIndex &index, int role) const override;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
    const       int                     m_cnst_iLeftSize;
    const       int                     m_cnst_iRightSize;
    //数据保存在m_vec_qstrlst
    std::vector<QStringList>            m_vec_qstrlst;
    QStringList                         m_qstrlstHeader;
private:
    QScopedArrayPointer<int>            m_arrOrder;
    int                                 m_iMajorCol;
    const int                           m_cnst_iMaxRowCount;//表格最大行数,本示例中是30000
    //m_vecOrder的元素是m_vec_qstrlst中每个成员的序号。元素的相对次序决定了排序结果
    std::vector<int>                    m_vecOrder;
    void                                vSort(std::vector<QStringList> & vecInput,
                                              int, Qt::SortOrder);
};
#endif // MODELFREQDETECT_H
#include "ModelFreqDetect.h"


ModelFreqDetect::ModelFreqDetect(QStringList qstrlst, int iLeftSize, int iRightSize, QObject * parent): QAbstractTableModel(parent),
    m_qstrlstHeader(qstrlst), m_iMajorCol(2), m_cnst_iLeftSize(iLeftSize),
    m_cnst_iRightSize(iRightSize),
    //默认m_iMajorCol=2
    m_arrOrder(new int[m_qstrlstHeader.size()]), m_cnst_iMaxRowCount(iLeftSize + iRightSize),
    m_vec_qstrlst(iLeftSize + iRightSize)
{
    m_vecOrder.resize(0);
    for(int k = 0; k < m_qstrlstHeader.size(); k++)
    {
        m_arrOrder[k] = Qt::AscendingOrder;
    }
}

int ModelFreqDetect::iAddRows(bool bLeft, std::vector<QStringList> & vec_qstrlst)
{
    //m_vec_qstrlst并不是手工排序后的结果,而是采用默认排序
    //所谓默认排序,指的是左结果排在右前面。内部的次序按照udp发来的次序
    int iLoc = bLeft ? 0 : m_cnst_iLeftSize;
    //假如送来的vec_qstrlst代表左信息,则从m_vec_qstrlst.begin()开始覆盖;
    //否则就是代表右信息,从m_vec_qstrlst.begin()开始跳过m_cnst_iLeftSize,覆盖右
    std::copy(vec_qstrlst.begin(), vec_qstrlst.end(), m_vec_qstrlst.begin() + iLoc);


    if(m_iMajorCol > -1 && m_iMajorCol < m_qstrlstHeader.size())
    {
        //排序
        vSort(m_vec_qstrlst, m_iMajorCol, (Qt::SortOrder)(m_arrOrder[m_iMajorCol]));
    }

    emit dataChanged(createIndex(0, 0), createIndex(m_cnst_iMaxRowCount - 1, m_qstrlstHeader.size() - 1));

    return vec_qstrlst.size();
}


int ModelFreqDetect::rowCount(const QModelIndex & parent) const
{
    return m_cnst_iMaxRowCount;
}

int ModelFreqDetect::columnCount(const QModelIndex & parent) const
{
    return m_qstrlstHeader.size();
}

QVariant ModelFreqDetect::data(const QModelIndex &index, int role) const
{
    int i = index.row(), j = index.column();
    if ((i >= 0) && (i < qMin(m_cnst_iMaxRowCount, (const int)(m_vecOrder.size()))))
    {
        if(role == Qt::DisplayRole)
        {
            if (0 <= j && j < m_qstrlstHeader.size())
            {
                QStringList qstrlst = m_vec_qstrlst.at(i);
                if(qstrlst.size() > j)
                {
                    //return qstrlst.at(j);
                    return m_vec_qstrlst.at(m_vecOrder.at(i)).at(j);
                }
            }
        }
        else
        {

        }
    }
    else if(role == Qt::TextAlignmentRole)
        return Qt::AlignCenter;
    else
    {

    }

    return QVariant();
}

//ok
QVariant ModelFreqDetect::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role == Qt::DisplayRole)
    {
        if(orientation == Qt::Horizontal)
        {
            if(section < m_qstrlstHeader.size())
            {
                QString qstrOrder;
                if(section == m_iMajorCol)
                {
                    if(Qt::AscendingOrder == m_arrOrder[m_iMajorCol])
                        qstrOrder = "^";
                    else
                        qstrOrder = "v";
                }
                else
                {
                    qstrOrder = "";
                }
                return m_qstrlstHeader.at(section) + qstrOrder;
            }
        }
        else
        {
            return QString("%1").arg(section);
        }
    }
    else if(role == Qt::TextAlignmentRole)
    {
        return Qt::AlignCenter;
    }
    else
    {

    }

    return QAbstractTableModel::headerData(section, orientation, role);
}

void ModelFreqDetect::vSortByColumn(int iCol)
{
    if(Qt::AscendingOrder == m_arrOrder[iCol])
    {
        m_arrOrder[iCol] = Qt::DescendingOrder;
    }
    else if(Qt::DescendingOrder == m_arrOrder[iCol])
        m_arrOrder[iCol] = Qt::AscendingOrder;
    else
        m_arrOrder[iCol] = Qt::AscendingOrder;
    m_iMajorCol = iCol;

    //然后排序,排序结果保存在m_vecOrder
    vSort(m_vec_qstrlst, iCol, (Qt::SortOrder)(m_arrOrder[iCol]));
    //更新界面
    emit dataChanged(createIndex(0, 0), createIndex(m_cnst_iMaxRowCount - 1, m_qstrlstHeader.size() - 1));
}

void ModelFreqDetect::vSort(std::vector<QStringList> & vecInput,
           int iCol, Qt::SortOrder order)
{
    //1 先把用来排序的那一列的数据提取出来,并且无效的序号不要计入m_vecOrder
    std::vector<float> vecVal;
    std::vector<int> vecIdx;
    for(int k = 0; k < vecInput.size(); k++)
    {
        if(vecInput.at(k).isEmpty())
        {
            vecVal.push_back(0);
        }
        else
        {
            vecIdx.push_back(k);
            vecVal.push_back(vecInput.at(k).at(iCol).toFloat());
        }
    }

    //2 排序
    std::sort(vecIdx.begin(), vecIdx.end(), [&vecVal](int a, int b){
        return vecVal.at(a) < vecVal.at(b);
    });

    m_vecOrder.swap(vecIdx);

    //假如是降序(Descending order),则m_vecOrder反向
    if(Qt::DescendingOrder == order)
        std::reverse(m_vecOrder.begin(), m_vecOrder.end());
}

 完整代码见【免费】stdsort完成qt表格排序资源-CSDN文库

效果

在运行模式下测试,几乎没有任何卡顿。

测试数据见【免费】排序测试数据,分两部分,一个是属性为左,另一个属性为右两者各15000条数据资源-CSDN文库

sort 排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值