更好(更快)算法来比较整数向量的2向量?

时间:2018-05-03 15:31:21

标签: c++ arrays vector intersection

我有一组原始数据文件,每个文件有800万~9百万行(是的, 8,000,000~9,000,000)采用以下格式,

1,2,3,4,5,16,23,35
1,2,3,4,6,17,23,36
1,2,3,4,7,18,23,37
1,2,3,4,8,19,23,38
1,2,3,4,9,20,23,39
1,2,3,4,10,21,23,40
1,2,3,4,11,22,23,41
1,2,3,4,12,23,24,42
1,2,3,4,13,24,25,43
1,2,3,4,14,25,26,44

每行有8个排序数字,范围从1到49。 另一组"过滤器"文件中每个都有6百万~7百万行 以下格式,

13,4,7,8,18,20
9,10,11,12,5,6,7,8,1,2,3,4,21,22,23,24,13,14,15,16,29,30,31,32,45,46,47,48
29,49,36,37,34,17,15,9,16,30,28,47,46,27,20,32,14,26,1,4,3,6,10,2,7,48,44,41

每行有4~28个非排序数,范围1~49 我需要比较"原始数据和#34;中的每一行。文件中包含"过滤器"中的每一行文件 并获得交叉点值,例如原始的第1行,过滤器中的第1~3行

1  // since only 4 is in common with filter line 1
7  // since only 35 not found in filter line 2
6  // since 5 23 35 not found in filter line 3    

比较后,将根据阈值输出结果。 e.g。

output raw data line with intersection value >= 2,
output raw data line with intersection value == 4

我知道(最多)有900万到800万行比较。 首先,我尝试使用set_intersection来完成这项工作,但是完成任务需要花费很长时间(在传递给set_intersection之前对过滤行进行排序)。

int res[8];
int *it = set_intersection(Raw.Data, Raw.Data+8, FilterVal.begin(), FilterVal.end(), res);
ds = GetIntersect(GDE.DrawRes, LotArr) * 2;
int IntersectCnt=it-res;

接下来,我尝试构建一个整数为零的数组:

int ResArr[49] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

并使用3个辅助函数:

void InitResArr(int * inResArr, vector<int> & FilterVal) {
    for (int i = 0; i < FilterVal.size(); i++) {
        inResArr[FilterVal[i] - 1] = 1;
    }
}
void ResetResArr(int * inResArr, vector<int> & FilterVal) {
    for (int i = 0; i < FilterVal.size(); i++) {
        inResArr[FilterVal[i] - 1] = 0;
    }
}

int GetIntersect(int * inResArr, int * inRawData) {
    int RtnVal = 0;
    for (int i = 0; i < 8; i++) {
        RtnVal+=inResArr[inRawData[i] - 1];
    }

但是这种方法仍然需要3个小时来完成1次比较(1个原始数据文件和1个过滤器)。 我有5000个原始数据文件和40,000个过滤器! 还有其他更好的方法来处理这项任务吗?感谢。

Regds

林志峰

1 个答案:

答案 0 :(得分:-1)

不确定它对您的案例的效果如何(很难理解您的描述中的内容)但我已经考虑过以下算法:

对长行进行排序。它可以在O(n)中完成,其中n是单个数据行的长度,只需简单计数即可。

之后,仅针对过滤行中的每个数字,对已排序的行执行二进制搜索。这将是O(m * log(n)),其中m是过滤器行的数量。应该是对O(m*n)的重大改进(您还需要将所有这些复杂性乘以数据行的数量,确切地说)。

此外,请注意您的I / O,在算法更新后,它可能会成为下一个瓶颈(如果您使用的是iostream,请不要忘记std::ios::sync_with_stdio(false)