Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何快速从排序向量中获得排序子向量_C++_Sorting_Vector_Large Data - Fatal编程技术网

C++ 如何快速从排序向量中获得排序子向量

C++ 如何快速从排序向量中获得排序子向量,c++,sorting,vector,large-data,C++,Sorting,Vector,Large Data,我的数据结构如下: struct X { float value; int id; }; 按值排序的向量(大小N(想想100000)(在程序执行期间保持不变): std::向量值; 现在,我想写一个函数 void subvector(std::vector<X> const& values, std::vector<int> const& ids, std::vector<X

我的数据结构如下:

struct X {
  float value;
  int id;
};
按值排序的向量(大小N(想想100000)(在程序执行期间保持不变):

std::向量值;
现在,我想写一个函数

void subvector(std::vector<X> const& values, 
               std::vector<int> const& ids, 
               std::vector<X>& out /*, 
               helper data here */);
void子向量(标准::向量常量和值,
标准::向量常量和ID,
标准::向量和输出/*,
助手数据在此*/);
它用传递的ID(大小MN(大约是N的0.8倍)给出的值的排序子集填充参数,fast(内存不是问题,这将重复进行,因此构建lookuptables(来自函数参数的助手数据)或者只做一次的其他事情是完全可以的)

我目前的解决方案:
生成可查找的lut,其中包含值中的id->偏移量(准备,所以为常量运行时)
创建
std::vector tmp
,大小为N,填充无效ID(线性输入N
对于每个id,将
值[lut[id]]
复制到
tmp[lut[id]]
(线性输入M
在tmp上循环,将项目复制到输出(线性输入N

这在N中是线性的(因为它比M大),但是临时变量和重复的复制让我很烦。有没有比这更快的方法呢?注意M将接近N,所以O(MlogN)是不利的


编辑:是上述算法的一个示例实现,用于明确所需的输出并证明它在线性时间内是可行的-问题是关于避免临时变量或以其他方式加速它的可能性,非线性的东西不会更快:)。

由于向量已排序,如果你想让它的一个子集按同样的方式排序,我想我们可以直接把你想要的块切掉,而不需要重新排列

为什么不使用find_if()两次呢。一次查找所需范围的起点,一次查找范围的终点。这将为您提供子向量的开始和结束迭代器。使用这些迭代器构造一个新的向量。其中一个向量重载使用两个迭代器


如果我正确理解了你的问题,你实际上是在尝试创建一个线性时间排序算法(取决于数字M的输入大小)。 这是不可能的

您当前的方法是对可能的值进行排序。 这需要线性时间到可能值N的数量(理论上,假设地图搜索需要O(1)时间)

您所能做的最好的事情是,使用快速排序方法(O(MlogM)f.e.quicksort、mergesort等)对M的小值进行排序(您从地图上找到的),并可能对M的大值进行线性搜索。 例如,如果N为100000,M为100,则仅使用排序算法要快得多

我希望你能理解我说的话。如果你还有问题,我会尽力回答:)

编辑:(评论) 我会进一步解释我的意思。 假设你知道你的数字在1到100之间。 您将它们排序到某个位置(实际上它们是“自然”排序的),并且您希望以排序形式获得它们的子集。 如果可以比O(N)或O(MlogM)更快地进行排序,那么排序算法将只使用此方法进行排序


F.e.通过拥有数字集{5,10,3,8,9,1,7},知道它们是已排序数字集{1,2,3,4,5,6,7,8,9,10}的子集,你仍然无法比O(N)(N=10)或O(MlogM)(M=7)更快地对它们进行排序。

你可以尝试的另一种方法是使用哈希表而不是向量来查找ID:

void subvector(std::vector<X> const& values, 
               std::unordered_set<int> const& ids, 
               std::vector<X>& out) {

    out.clear();
    out.reserve(ids.size());
    for(std::vector<X>::const_iterator i = values.begin(); i != values.end(); ++i) {
        if(ids.find(i->id) != ids.end()) {
            out.push_back(*i);
        }
    }
}
void子向量(标准::向量常量和值,
标准::无序集合常量和ID,
标准::向量和输出){
out.clear();
out.reserve(id.size());
对于(std::vector::const_迭代器i=values.begin();i!=values.end();++i){
如果(ids.find(i->id)!=ids.end()){
向外推。向后推(*i);
}
}
}

这是在线性时间内运行的,因为
unordered_set::find
是恒定的预期时间(假设对int进行散列没有问题)。然而,我怀疑它在实践中可能不如您最初使用向量描述的方法快。

那么,这
tmp
的目的是什么?它最初是从哪里来的?为什么不直接在
out
中构建输出,而不使用任何中间临时变量?此外,您试图构建的内容在您的问题中没有得到很好的描述。最初,您似乎说需要大小为
M
的输出。然而,您的算法在所有情况下都试图构建大小为
N
的输出。那么,在所有这些都完成之后,您想在
数组中得到什么呢?关于“tmp从何而来”,我创建了它。关于“为什么我不直接在
out
中构建它”-我不知道预先将元素放置在何处,我不知道子向量中的位置。不,我的输出是size
M
,它在N中是线性的,因为我在tmp中测试每个元素。是的,
id
值是唯一的。第二个向量按
id
排序,使用
equal_range
copy
和最后的
sort
按值排序应该会给你
M log N
复杂度。这是我没有提到的一点-M将非常接近N,因此这将是不利的(对于非常稀疏的id,这将是有利的)不确定这是否会起作用。如果我正确阅读问题,OP将数组按
值排序
,并希望按
id
进行选择。是的,id不是连续的(不必排序)不,我不想创建线性排序时间算法-我想从已经排序的向量中获取值,所以不需要s
void subvector(std::vector<X> const& values, 
               std::unordered_set<int> const& ids, 
               std::vector<X>& out) {

    out.clear();
    out.reserve(ids.size());
    for(std::vector<X>::const_iterator i = values.begin(); i != values.end(); ++i) {
        if(ids.find(i->id) != ids.end()) {
            out.push_back(*i);
        }
    }
}