c - 在 C 中快速复制数组的选定元素?

标签 c

这可能是一个非常基本的问题,但它确实让我很烦恼。我想做的基本上是使用 C 将旧 vector 中的元素复制到新 vector 中。

副本基于索引 vector ,该 vector 中的每个元素代表旧 vector 中元素的索引。索引 vector 未排序。

例如, 旧 vector A = [3.4, 2.6, 1.1]。

索引 vector B = [1, 1, 3, 3, 2, 1, 2]。

复制后,我希望新 vector 为 C = [3.4, 3.4, 1.1, 1.1, 2.6, 3.4, 2.6]。

我能想到的最残忍的解决方案是在B中运行一个循环,将A中对应的元素复制到C中。但是当 vector 太大时,成本是无法承受的。

我的问题是,此时是否有更快/更智能的方式在 C 中进行复制?

最初代码是用 Julia 编写的,我对此没有意见。在 Julia 中,我只使用 C = A[B] 并且速度很快。谁知道他们是怎么做到的?

添加C伪代码:

float *A = []; # old array
int *B = []; # index array
float *C;
for(i=0;i<length(B);i++)
{
   *(C+i) = *(A+*(B+i));
}

最佳答案

假设:length(B) 实际上不是一个函数,但您没有发布它是什么。如果是函数,则捕获到for循环外的局部变量中,并读取一次;否则你有一个 Schlemiel 画家的算法。

我认为我们能做的最好的是Duff's Device又名循环展开。我还做了一些编译器通常可以进行的微不足道的优化,但我记得编译器的循环展开不如 Duff 的设备好。我的知识可能已经过时,编译器的优化器可能已经跟上了。

可能需要进行探测以确定最佳展开数。 8 是传统的,但循环体内的代码比正常情况下大。

此代码对指针AB 具有破坏性。如果您再次需要它们,请保存它们。

float *A = []; # old array
int *B = []; # index array
float *C;
int ln = length(B);
int n = (ln + 7) % 8;
switch (n % 8) {
case 0: do { *C++ = A[*B++];
case 7:      *C++ = A[*B++];
case 6:      *C++ = A[*B++];
case 5:      *C++ = A[*B++];
case 4:      *C++ = A[*B++];
case 3:      *C++ = A[*B++];
case 2:      *C++ = A[*B++];
case 1:      *C++ = A[*B++];
    } while (--n > 0);
}

对于这么多的范围,我无法做得更好,但是对于更大的范围,可能存在更好的选择,包括重新设计您的数据结构。

关于c - 在 C 中快速复制数组的选定元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58002180/

相关文章:

c - C中的非重复数字数组?

c - 如何比较从文件中读取的值并将其与队列中的所有值进行比较?

c - 在 C 中搜索字符串内的单词

c++ - 如何在 C/C++ 中减去两个 IPv6 地址(128 位数字)?

java - Printf:Java 和 C 实现的差异

c - 使用 SDL 时未定义对 WinMain@16 的引用

c - 为Windows实现C11线程

c - 在动态分配的内存上使用指针算法的未定义行为

c - C中的链表实现

c - ELF 文件生成命令和选项