如何使用R和Rcpp在递归中删除NumericVector中的元素

5
我正在尝试学习如何使用Rcpp包来进行R编程。因此,我开始使用Rcpp测试基本的排序算法。我是从Hadley Wickham的教程这里开始的。
我成功地递归实现了插入排序算法,具体代码如下:
library(Rcpp)

vetor<-sample(100)
vetor
cppFunction("
    NumericVector insertionsortRC(NumericVector vetor, int n) {
        double aux;
        int i;

        if(n>1) {
            insertionsortRC(vetor,n-1);
            aux=vetor[n-1];
            i=n-1;
            while(vetor[i-1]>aux && i>=0 ) {
                vetor[i]=vetor[i-1];
                i--;
                }
            vetor[i]=aux;
            }

        return vetor;
        }
    ")

但是这个函数需要2个参数,然后我尝试了这种方式:
cppFunction("
    NumericVector insertionsortRC(NumericVector vetor) {
        int n = vetor.size();

        double aux;
        int i;

        if(n>1) {
            vetor.erase(n-1);
            insertionsortRC(vetor);
            aux=vetor[n-1];
            i=n-1;
            while(vetor[i-1]>aux && i>=0 ) {
                vetor[i]=vetor[i-1];
                i--;
                }
            vetor[i]=aux;
            }

        return vetor;
        }
    ")

我认为在这里使用erase不是一个好主意,因为它似乎从内存中删除了元素,无法在递归调用后恢复它。我还以为问题可能出在vetor.erase(n-1);这一行上,尝试了vetor.erase(n);并编译通过,但根本没有起作用。

使用vetor.erase(n);时,在R中出现以下错误:

insertionsortRC(vetor) * Error in `/usr/lib/R/bin/exec/R': malloc(): memory corruption: 0x098db548 *

而使用vetor.erase(n-1);则得到了奇怪的输出:

插入排序RC(vetor)        [1] 3.607393e-313 3.300000e+01 3.100000e+01 8.600000e+01 2.500000e+01 7.000000e+01        [7] 4.000000e+01 8.800000e+01 8.100000e+01 1.300000e+01 8.500000e+01 8.700000e+01       [13] 3.900000e+01 6.000000e+01 6.400000e+01 1.000000e+01 8.200000e+01 8.900000e+01       [19] 1.400000e+01 6.600000e+01 3.600000e+01 1.500000e+01 9.600000e+01 2.600000e+01       [25] 4.000000e+00 5.400000e+01 2.900000e+01 8.300000e+01 5.500000e+01 6.800000e+01       [31] 9.100000e+01 6.000000e+00 1.000000e+02 5.100000e+01 7.000000e+00 5.300000e+01       [37] 9.900000e+01 6.500000e+01 2.300000e+01 9.400000e+01 5.700000e+01 9.000000e+01       [43] 3.200000e+01 4.700000e+01 1.600000e+01 5.000000e+01 2.800000e+01 3.000000e+00       [49] 9.800000e+01 1.100000e+01 1.800000e+01 7.600000e+01 6.300000e+01 7.700000e+01       [55] 7.400000e+01 4.900000e+01 8.000000e+00 9.700000e+01 1.200000e+01 2.700000e+01       [61] 3.500000e+01 7.900000e+01 8.000000e+01 2.000000e+01 6.700000e+01 9.300000e+01       [67] 5.000000e+00 5.600000e+01 9.000000e+00 3.700000e+01 2.400000e+01 9.200000e+01       [73] 6.900000e+01 3.800000e+01 4.400000e+01 1.700000e+01 4.600000e+01 4.300000e+01       [79] 3.400000e+01 1.900000e+01 2.000000e+00 9.500000e+01 7.200000e+01 1.000000e+00       [85] 6.100000e+01 4.100000e+01 6.200000e+01 2.200000e+01 4.200000e+01 2.100000e+01       [91] 8.400000e+01 4.800000e+01 7.800000e+01 7.300000e+01 3.000000e+01 5.900000e+01       [97] 5.800000e+01
有人能告诉我: 01. 是否可以使用Rcpp和R来实现这段代码,只用一个参数——数据向量来调用函数? 02. 如何正确地实现?
3个回答

6
简而言之:
  1. 好消息是你的编译工作正常。

  2. 不太好的消息是出现了段错误。很可能是代码中的逻辑错误。

  3. 一般来说,添加或删除 NumericVector(等等)是一个不好的想法。这些是浅层类型,直接连接到同一对象的 R 内存 ("无副本")。这意味着扩展或删除是昂贵的。考虑使用 STL 的 std::vector。所有这些都有记录。


4

几点提醒:

vector.erase(n)是未定义的行为。第一个索引是0,最后一个索引是n-1erase不进行边界检查,因为这会让所有人都付出代价。相反,它假设在C++世界中普遍适用的函数被正确使用。

了解std::sort,它比自己实现的排序方法更加高效,尤其是插入排序。

Rcpp向量有一个sort方法。所以一个NumericVector可以对自己进行排序。

学习属性,例如使用Rcpp-attributes的指南,这样更简单,并且这将为您处理默认参数提供一种方法。


1
尝试一下:vector.erase(vector.begin()+desiredElement) 这应该可以解决你的问题。
NumericVector 类型似乎与 std::vector 有关,至少在处理数据插入和删除方面是如此,这意味着你必须使用迭代器(但我不是 Rcpp 大师)。
Brian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接