微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++多级排序比较器应用

一、介绍

C++的比较器与java类似。首先自己定义比较逻辑(一个函数),然后将比较逻辑传入c++提供的排序方法中,按照比较逻辑进行排序。

二、 一个例子

#include <string>
#include <vector>
#include <iostream>
#include<iomanip>
#include <algorithm>
#include <set>
#include <chrono>
#include <random>

using namespace std;

//排序规则
typedef struct _sortRule {
    int col;      //字段号
    int sortType; //排序方式:0,按字符串排;1,按数字排
    int iSAEs;    //0,升序;非0,降序
} TSortRule;

//待排序的数据集
typedef struct sortData {
    int index;      //数据所在的列号
    vector<string> data; //数据
    vector<TSortRule> sortRules;    //排序规则
} SortData;


/*
 * 比较器逻辑
 * 如果想要升序排序,那么(1<2<3)左边的数据小于右边的。也就是l<r为:true
 * 如果想要降序排序,那么(3<2<1)左边的数据大于右边的。也就是l>r为:true
 */
bool cmpLogic(const SortData &l, const SortData &r, int index, int size) {
    if (index == size) {
        return true;
    }
    //升序
    if (l.sortRules[index].iSAEs == 0) {
        //按数字排序
        if (l.sortRules[index].sortType == 1) {
        // 如果想要升序排序,那么(1<2<3)左边的数据小于右边的。也就是l<r为:true
        // 如果想要降序排序,那么(3<2<1)左边的数据大于右边的。也就是l>r为:true
            if (strtol(l.data[index].c_str(), nullptr, 10) < strtol(r.data[index].c_str(), nullptr, 10)) {
                return true;
            }
            if (strtol(l.data[index].c_str(), nullptr, 10) > strtol(r.data[index].c_str(), nullptr, 10)) {
                return false;
            }
            if (strtol(l.data[index].c_str(), nullptr, 10) == strtol(r.data[index].c_str(), nullptr, 10)) {
                cmpLogic(l, r, index + 1, size);
            }
        } else { //按字符串排序
            if (l.data[index].compare(r.data[index])<0) {
                return true;
            }
            if (l.data[index].compare(r.data[index])>0) {
                return false;
            }
            if (strcmp(l.data[index].data(),r.data[index].data())==0) {
                cmpLogic(l, r, index + 1, size);
            }
        }
    } else { //降序
        if (l.sortRules[index].sortType == 1) {
            if (strtol(l.data[index].c_str(), nullptr, 10) > strtol(r.data[index].c_str(), nullptr, 10)) {
                return true;
            }
            if (strtol(l.data[index].c_str(), nullptr, 10) < strtol(r.data[index].c_str(), nullptr, 10)) {
                return false;
            }
            if (strtol(l.data[index].c_str(), nullptr, 10) == strtol(r.data[index].c_str(), nullptr, 10)) {
                cmpLogic(l, r, index + 1, size);
            }
        } else {
            if (l.data[index].compare(r.data[index])>0) {
                return true;
            }
            if (l.data[index].compare(r.data[index])<0) {
                return false;
            }
            if (strcmp(l.data[index].data(),r.data[index].data())==0) {
                cmpLogic(l, r, index + 1, size);
            }
        }
    }
}

/*
 * 自定义比较器,这个函数就是排序的依据。
 * 如果想要升序排序,那么(1<2<3)左边的数据小于右边的。也就是l<r为:true
 * 如果想要降序排序,那么(3<2<1)左边的数据大于右边的。也就是l>r为:true
 */
bool cmp(const SortData &l, const SortData &r) {
    int minNum = min(l.data.size(), l.sortRules.size());
    return cmpLogic(l, r, 0, minNum);
}

/**
 * @brief 对二维表进行排序
 * @param list,二维vector定义的二维表;
 * @param sortRules,排序规则
 * @param inrows,参加排序的记录列表
 * @param outrows,顺序索引列表(二维表本身并不排序,排序结果由本索引表承担)
 * @return 0,成功;恒为0
 * @note  本算法要求性能足够高,可支持百万级记录数
 */
int Sort(const vector<vector<string>> &list, const vector<TSortRule> &sortRules, const vector<size_t> &inrows,
         vector<size_t> &outrows) {
    //初始化待排序的list
    vector<SortData> sortList;
    for (size_t i: inrows) {
        SortData sortData;
        sortData.index = i;
        sortData.data = list[i];
        cout << sortData.index << ":";
        for (const string &str: list[i]) {
            cout << str << " ";
        }
        cout << "" << endl;
        sortData.sortRules = sortRules;
        sortList.emplace_back(sortData);
    }
    /*
     * 核心,调用<algorithm>库提供的排序函数sort(const _RanIt _First(待排序的集合的开始位置), const _RanIt _Last(待排序的集合的开始位置), _Pr _Pred(传入一个函数,也就是比较器))
     */
    sort(sortList.begin(), sortList.end(), cmp);
    cout << "排序后的序列:" << endl;
    for (const SortData &sortData1:sortList) {
        outrows.emplace_back(sortData1.index);
        cout << sortData1.index << " " << endl;
    }
    return 0;
}


/**
 * 初始化list,大小为40*20,每行,前十个为:数字(随机获取),后十个为:rmb_+随机数
 * @param list
 * @param rows
 */
void initData(vector<vector<string>> &list, int rows) {
    list.resize(rows);

    std::random_device rd;     //Get a random seed from the OS entropy device, or whatever
    std::mt19937_64 eng(rd()); //Use the 64-bit Mersenne Twister 19937 generator
    int maxnum = 100;
    std::uniform_int_distribution<unsigned long long> distr(8, rows);// distribution in range [1, num]
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 10; j++) {
            list[i].emplace_back(to_string(distr(eng)));
        }
        for (int j = 0; j < 10; j++) {
            list[i].emplace_back("rmb_" + to_string(distr(eng)));
        }
    }
}


class elapsedtimer {
public:
    elapsedtimer() : m_begin(std::chrono::high_resolution_clock::Now()) {}

    void reset() { m_begin = std::chrono::high_resolution_clock::Now(); }

    //ns
    int64_t elapsed_ns() const {
        return std::chrono::duration_cast<std::chrono::nanoseconds>(
                std::chrono::high_resolution_clock::Now() - m_begin).count();
    }

    //us
    int64_t elapsed_us() const {
        return std::chrono::duration_cast<std::chrono::microseconds>(
                std::chrono::high_resolution_clock::Now() - m_begin).count();
    }

    //ms
    int64_t elapsed_ms() const {
        return std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::high_resolution_clock::Now() - m_begin).count();
    }

    //s
    int64_t elapsed_s() const {
        return std::chrono::duration_cast<std::chrono::seconds>(
                std::chrono::high_resolution_clock::Now() - m_begin).count();
    }

    //m
    int64_t elapsed_min() const {
        return std::chrono::duration_cast<std::chrono::minutes>(
                std::chrono::high_resolution_clock::Now() - m_begin).count();
    }

    //h
    int64_t elapsed_hours() const {
        return std::chrono::duration_cast<std::chrono::hours>(
                std::chrono::high_resolution_clock::Now() - m_begin).count();
    }

private:
    std::chrono::time_point<std::chrono::high_resolution_clock> m_begin;
};


void test(int datanum, int col, int sorttype) {
    vector<vector<string>> list;
    elapsedtimer et;
    initData(list, datanum);
    cout << "init  ms:" << et.elapsed_ms() << endl;

    vector<TSortRule> sortRules;

    TSortRule sortRule;
    for (int i = 0; i < col; i++) {
        sortRule.col = i;

        if (sorttype > 1) {
            sortRule.sortType = (sorttype + i) % 2;

        } else {
            sortRule.sortType = sorttype;
        }
        sortRule.iSAEs = 0;
        sortRules.emplace_back(sortRule);
    }

    vector<size_t> outrows;
    vector<size_t> inrows = {1, 2, 3, 4};

    et.reset();

    Sort(list, sortRules, inrows, outrows);


    printf("%d\t%d\t%s\tms:%lld\n", datanum, col, sorttype ? "int" : "str", et.elapsed_ms());
    // FILE *fp = fopen("./times1.txt", "a+");
    // fprintf(fp, "%d\t%d\t%s\t%s\t%lld\n", datanum, col, sorttype > 1 ? "混合" : (sorttype? "整形":"字符串"), altype? "pair" : "list", et.elapsed_ms());
    // fflush(fp);
    // fclose(fp);
}

int main() {
    test(40, 5, 0);
}

原文地址:https://www.jb51.cc/wenti/3285835.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐