改进这个算法

时间:2013-03-24 05:50:35

标签: c arrays algorithm sorting

我正在寻找如何改进这个算法的建议。这是一个非常简单的算法,可以在数组中插入一个数字,并在inserction之后保持它的排序。这是一个很好用的函数,因此我需要快速运行它可能的。

static inline void sort_insert(int *arr,int target,int size)
{
  int i, at; 

  for(i = 0; i < size && arr[i] != 0 && arr[i] < target; i++)
    /* do nothing */;

  at = i; // insertion point

  /* if the number will be inserted into last postion,we don't need loop */
  if (at == size) {
    arr[at - 1] = target;
    return;
  }

  for(i = size - 1; i > at; i--)
    arr[i] = arr[i - 1];
  arr[at] = target;
}

注意: 请避免内置功能。稍后将在程序集中重写此算法。

3 个答案:

答案 0 :(得分:2)

有人已经提到为什么不对Binary Search进行修改。它是这样的 -

  1. 首先搜索您在数组A中插入的元素X。
  2. 在搜索结束时(无论是找到还是找不到)都插入新元素。
  3. 如果要处理类似元素的插入顺序(例如,要插入X = 3但A中已有3个,那么也可以在O(1)时间内完成。在Bin-Search之后根据您想要放置新元素的位置向左或向右移动。
  4. 所有这一切都将在O(log n)时间内完成,这是一个血腥的快速,这是最快的。

答案 1 :(得分:2)

通常的方法(例如,在插入排序中)是从阵列移位元件的顶部向上开始并同时寻找插入点。以这种方式,您只触摸上面的元素插入。在伪C:

// a[0] t0 a[n_elements - 1] contain sorted data
// Insert val_to_insert in sorted order by shifting up until we find the right place
for (i = n_elements; i > 0 && a[i - 1] > val_to_insert; i--)
  a[i] = a[i - 1];
// i is now the insertion point
a[i] = val_to_insert;

您的算法必须触及所有元素。平均而言,插入排序方法将快1/2。

另一个技巧是在位置0保持“虚拟” - 无效值,以便可以消除i > 0比较。当它达到此值时,其他条件将始终为false,因此循环将在运行数组底部之前停止。这称为 sentinel

看起来你从头开始搜索的原因是0终止了数组。如果你真的在速度之后,那么你应该改变数据结构并将数组的结尾记录为整数。这将使上述插入算法更快(平均1/2)插入算法。

添加最后要注意的是,编译器特别擅长优化这种插入的简单循环结构。如果使用-O4或等效编译包含此代码的模块,则不可能通过在汇编中重新编码来使代码更快。

答案 2 :(得分:0)

这段代码太可怕了;我甚至都不读它。通过修复缩进来改进它,然后我(像其他人一样)可以阅读它。

在C算法上导出汇编算法有两个原因,我可以提出。他们都疯了:

  1. 你认为C和汇编有什么共同之处吗?除了编程语言之外,它们几乎没有任何共同之处。别忘了这个;学习汇编就好像它具有与C“共同”的特征,或者学习C就像它具有与汇编“共同”的特征一样,因为C不受某个特定架构的约束。你可能会认为“这在C中起作用,因为它适用于我的建筑”,但是一只鸡可能会或者可能不会在没有它的情况下四处跳跃。 C有未定义的行为。未定义的行为可能会在您的鞋子中产生预期的结果,但C不是专为您的鞋设计的。
  2. 您认为您可以手动优化您的计划吗?您的编译器可能会产生比您更好的装配。毕竟,编译器是由编写年的程序集的专家编写的。同样,C标准库由专家编写。或许,您可以使用编译器内联标准库qsort / bsearch并转换为汇编。不要忘记分析编译器生成的“-O3”版本,并将其与您对汇编输出的每个“优化”进行比较;通过为您的比较提供标准的标准,我认为您会发现浪费数天,数周,数月或数年的时间来减少性能。