目录
思路
沿着前面博客的思路,现在用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 排序