Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.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++;_C++_C++11 - Fatal编程技术网

C++ 在c++;

C++ 在c++;,c++,c++11,C++,C++11,有人能提出一种快速的方法来获得向量中每个元素的秩吗。 我不需要对向量进行排序,只要对向量进行排序,就可以得到每个元素的索引 例如:{40,20,10,30} 应该给出{3,1,0,2} 我是否能够获得加速,因为我实际上不必对数据进行适当排序?同样的排序下限证明也适用于这里。如果没有其他信息(密钥分发等),则下限为n log(n),您也可以进行排序。从形式上讲,任何更低的值都允许您将排列压缩到下面 话虽如此,问题在于如何对指数进行排序。看。我可以想出两种方法:(但我不认为它们会更快) 将对放入地

有人能提出一种快速的方法来获得向量中每个元素的秩吗。 我不需要对向量进行排序,只要对向量进行排序,就可以得到每个元素的索引

例如:{40,20,10,30} 应该给出{3,1,0,2}


我是否能够获得加速,因为我实际上不必对数据进行适当排序?

同样的排序下限证明也适用于这里。如果没有其他信息(密钥分发等),则下限为n log(n),您也可以进行排序。从形式上讲,任何更低的值都允许您将排列压缩到下面


话虽如此,问题在于如何对指数进行排序。看。

我可以想出两种方法:(但我不认为它们会更快)

  • 对放入地图中
  • 将索引放入另一个向量中,使用适当的比较函数对该向量进行排序

  • 对于数字而言,对数组本身进行排序并不比对索引进行排序困难——您将构建一个索引集,并按照原始值对其进行排序。

    第一种方法是复制数组并对其进行排序。然后遍历原始数组,对每个项执行二进制搜索以确定秩。在此遍历过程中,生成所需的序列。在这个方法中,你取O(n)作为副本,加上O(n lgn)作为排序,最后O(n lgn)作为产生列组序列

    另一种方法是将所有项目插入二叉搜索树(一种平衡的搜索树,如avl或红黑)。这需要O(n lgn)。二叉树必须支持“秩扩展”;也就是说,每个子树的大小必须存储在节点中。这些树可以导出操作
    position(key)
    ,该操作返回
    key
    的等级

    然后,遍历数组,并为每个条目调用
    位置(array[i])
    。在此过程中,您将生成与数组平行的秩序列。这需要O(n lgn)

    我认为这种方法的优点是,复制到成对数组中,然后对其进行排序,或者简单地对数组的副本进行排序,然后通过在复制的数组中进行二进制搜索来确定秩,这样可以避免从已排序的成对数组到秩序列的额外副本

    增加和更正:

    根据@xiaotian peiI的回答,我认为在按键排序的确定平衡二叉搜索树(avl或红黑)中插入对(键、索引)会更好;这需要O(n lgn)。然后遍历二叉树以提取索引,这需要O(n)。最后你释放了这棵树,什么需要O(n)。所以总数是O(n lgn)+O(n)+O(n)

    根据规模和复杂性的不同,可能更有效:使用一堆对(键、索引)并从中连续提取以构建列组序列


    而且速度可能更快,占用的空间肯定更少:Jarod42发布的算法,我认为也是O(n)+O(n lg n)+O(n),但这将使缓存获益更多

    template <typename T>
    std::vector<std::size_t> compute_order(const std::vector<T>& v)
    {
        std::vector<std::size_t> indices(v.size());
        std::iota(indices.begin(), indices.end(), 0u);
        std::sort(indices.begin(), indices.end(), [&](int lhs, int rhs) {
            return v[lhs] < v[rhs];
        });
        std::vector<std::size_t> res(v.size());
        for (std::size_t i = 0; i != indices.size(); ++i) {
            res[indices[i]] = i;
        }
        return res;
    }
    
    模板
    标准::向量计算顺序(常数标准::向量&v)
    {
    向量指数(v.size());
    std::iota(index.begin()、index.end()、0u);
    排序(index.begin(),index.end(),[&](int-lhs,int-rhs){
    返回v[lhs]

    [我认为]排序向量是最快的方法,这个例子不应该给出{2,1,3,0}?不,很明显,最低的值(10)有最低的索引(0)A[]={40,20,10,30},I[]={2,1,3,0},A[I[]={A[2],A[1],A[3],A[0]={10,20,30,40}。Puppy是write@rcgldr你误解了我不想要原始索引,我想要他们的新指数,假设他们被分类了这是一个很好的答案,但我知道你不能超过nlog(n)下限,我所说的加速是在这一范围内,但在复杂的细节中。。像常数因子或something@VikashB请参阅更新。我不得不说,在这方面,你的问题是一个重复的问题,不是吗?不是真的,因为常数的因素将是非常不同的,你不能完全在C++中使用NoPy。为什么你不能使用NUMPY?code>numpy.argsort(foo)
    应该适用于您的示例。我的钱是,这也给出了最好的常数。@ AmiTavory:因为NUMPY不是C++。是Python
    g++
    将不会接受
    numpy.argsort(foo)
    。不,它不会打败仅仅对向量进行排序。完美,正是我想要的,第二种方法很棒,我以前没有听说过秩扩展。下面由Jarod42提供的答案更有效。您可以根据数组对索引进行排序,然后使用排序后的索引进行单次传递(O(n)),以创建原始帖子中所需索引的数组(Jarod42答案中的vector res)。@rcgldr:是!这是一个非常漂亮的解决方案。我编辑了答案,并解释了第三种方法,我认为这种方法更有效。据我所知,Jarod42方案需要O(n)来初始化索引(iota调用),然后O(n lg n)来排序,最后O(n)来提取列组;这将需要O(n)+O(nlgn)+O(n)与O(nlgn)+O(n)@Irleon-我不明白什么方法需要O(nlgn)+O(n)。对于二叉树方法,必须在树中插入元素(如果使用对,则创建对),然后遍历树。树操作要比排序所使用的索引和“源”索引转换为“目的地”索引花费更多的时间。我错了,因为我忘记考虑树的释放。因此,在二叉搜索树中有n对插入;什么需要O(n lg n)。然后按顺序遍历二叉树,在遍历过程中,将索引复制到se