更快地从struct数组中交换元素

时间:2017-01-29 01:32:52

标签: c arrays struct swap

我有这个结构:

import numpy as np
from scipy.stats import beta
from matplotlib import pyplot as plt

figure = plt.figure("Figure")
subplot1 = figure.add_subplot(2,2,1)
x = np.linspace (0, 1.0, 200) 
y1 = beta.pdf(x, 10, 7)
subplot1.plot(x, y1, "-", label="r'$\alpha=10, \beta=7$'")
subplot1.legend() #throws an error when I include this statement
plt.show()

我创建了一个这个结构的数组,并使用快速排序算法对它们进行排序。 为此,我必须使用此函数交换元素:

typedef struct data{
    char name[100], pseudo[100];
    int num0, num1, num2, num3, num4;
    long int lnum0, lnum1, lnum2, lnum3, lnum4;
    double dnum0, dnum1;
}data;
data list[50]

我的结构中有16个元素,我必须重复16次这个函数来交换它们。 我的问题是:是否还有其他更简单,更快捷或更好的方法,或者我们可以优化此功能吗?

3 个答案:

答案 0 :(得分:2)

这是使用N类型为T的元素对数组进行排序的典型解决方法,其中假设Nsizeof(T)都很大。

  1. 创建N 指针的临时数组T
  2. 使用指向实际数组中元素的指针填充临时数组。
  3. 对临时数组进行排序。 (比较元素时,你必须取消引用指针。交换元素时,你只需要交换单个指针。)
  4. 重新排列原始数组中的元素,使它们的顺序与临时数组中指针的顺序相同。
  5. 再次释放临时阵列。
  6. 此技术的优势在于,您只需执行O(N) T次互换,而O(N log(N))可以进行T*次互换。缺点是你必须分配临时缓冲区并在比较元素时通过额外的指针间接。你必须进行基准测试才能看出这是否能为你的类型带来回报。

    可能的优化是在堆栈上分配临时数组,因为它永远不会超过排序例程。但是,在堆栈上放置大型数组可能会导致堆栈溢出,因此请注意大小。

答案 1 :(得分:1)

我不确定这是你在寻找什么,但加速这些交换的一种简单方法是在“list”中存储指向“struct data”的指针,而不是存储整个结构本身。这样,当你交换时,你一次只交换4或8个字节(分别为32位和64位),而不是高达256个字节。

如果你打算连续存储和交换这些结构的所有内存,最好的办法是使用矢量内在函数(SIMD)。这是一个guide for gcc。这是one for msvc

答案 2 :(得分:1)

如果不是因为你问的是优化,我认为这是一项功课。但是,分类品种的家庭作业通常不涉及优化。尽管如此,你的机构会教会你在现实世界中永远不要重新发明轮子,除非好处超过成本。在这种情况下,他们没有。

  • 想象一下,如果你的最快的x86 代码也是最慢的ARM 。这是一种常见的情况,标准库包含<stdlib.h>中的两个函数:qsortbsearch。可能性是,标准库的作者更好地了解如何为每个平台编写,测试和调整排序算法。
  • 想象一下,如果每个进程在每个给定时间重新运行轮子,导致大量重复排序功能被保留并在内存中交换...使用标准库代码的一个主要好处是它可以在许多进程之间共享,从而减少重复的资源消耗。减少资源消耗也很可能导致更快的代码,在这种情况下,在多个进程之间共享此资源也可能减少缓存抖动。

要使用qsortbsearch,首先需要定义比较函数。这可以像包装strcmp一样简单,如果你可以保证基于的排序字段实际上是一个字符串(即字符序列以'\0'结尾)。比较函数需要使用签名int compare(void const *x, void const *y);,例如:

int compare_data_by_name(void const *x, void const *y) {
    data const *foo = x, *bar = y;
    return strcmp(foo->name, bar->name);
}

致电qsort(list, sizeof list / sizeof *list, sizeof *list, compare_data_by_name);将对list进行排序。

致电bsearch(&(data){ .name = "fred" }, list, sizeof list / sizeof *list, sizeof *list, compare_data_by_name);将检索名称为"fred"的项目。