Algorithm 什么是适合嵌入式系统的排序算法?
我正在为一个嵌入式系统开发软件,我需要实现一个排序例程,我在选择最佳解决方案时遇到了困难。我的要求如下:Algorithm 什么是适合嵌入式系统的排序算法?,algorithm,sorting,embedded,Algorithm,Sorting,Embedded,我正在为一个嵌入式系统开发软件,我需要实现一个排序例程,我在选择最佳解决方案时遇到了困难。我的要求如下: 因为这是一个内存非常有限的系统,所以空间复杂性是一个主要因素 由于要排序的元素数量通常很小,而且排序只是偶尔发生,因此时间复杂性不一定是主要因素 我的应用程序需要一个稳定的算法 因为这是一个嵌入式系统,所以代码大小是一个因素 无法保证数据最初将以近乎排序的顺序排列 我考虑了以下算法: 气泡排序(是的,尽管我不好意思这么说) 侏儒排序 插入排序 就地合并排序(虽然在我看来,链表比数组更理想?
- 气泡排序(是的,尽管我不好意思这么说)
- 侏儒排序
- 插入排序
- 就地合并排序(虽然在我看来,链表比数组更理想?)
虽然答案(就我的具体情况而言)很可能是“嗯,嗯,没关系,我们只关心使用冒泡排序”,但这个答案不是很有用一般来说,什么样的排序算法对嵌入式系统有用?不要为冒泡排序感到羞耻,它有自己的位置。如果您的数据集很小,那么很容易编写代码,而且如果您做得正确,它是稳定的(永远不要交换相等的元素) 如果您的数据主要是通过在每次传递时交替方向进行排序,那么它也可能会非常快。我知道你说它一开始并没有被分类,我说的是,如果你分类然后坚持下去,它会变成这样的可能性。在这两种情况下,如果数据集的大小很小,那么它是否完全未排序实际上并不重要 如果您在另一个答案的评论中提到,您的数据集大小约为11,则情况尤其如此。如果没有一个明确设计为故意制造恐怖的排序算法,那么任何算法都可以很容易地以足够快的速度处理这样的大小 如果您的环境没有提供稳定的排序,那么考虑到您的约束和属性,我会选择冒泡排序
事实上,使用下面的程序和
time
实用程序,我发现qsort
和冒泡排序所用的CPU时间只有在元素计数达到10000时才会产生影响
而且,即使在那时,这种泡沫也只花了不到半秒钟的时间。除非你每秒要做很多排序,否则这是无关紧要的
#include <stdio.h>
#include <stdlib.h>
static int data[10000];
#define SZDATA (sizeof (*data))
#define NMDATA (sizeof (data) / sizeof (*data))
int compfn (const void *a, const void *b) {
if (*((int*)a) > *((int*)b))
return 1;
if (*((int*)a) < *((int*)b))
return -1;
return 0;
}
int main (void) {
int i, tmp, swapped, count;
for (i = 0; i < NMDATA; i++)
data[i] = (i * 3) % 11;
if (0) {
qsort (data, NMDATA, SZDATA, compfn);
} else {
swapped = 1;
count = NMDATA;
while (swapped) {
swapped = 0;
for (i = 1; i < count; i++) {
if (data[i] < data[i-1]) {
tmp = data[i];
data[i] = data[i-1];
data[i-1] = tmp;
swapped = 1;
}
}
count --;
}
}
//for (i = 0; i < NMDATA; i++)
//printf ("%10d\n", data[i]);
return 0;
}
我怀疑使用小数据集进行更快的冒泡排序是因为缺少函数调用
需要注意的是,对于较小的数据集,算法的效率通常不重要,因为像big-O这样的东西通常与数据集变大相关
但是,此测试是在我的环境中完成的,您的环境可能会有很大差异。我建议在您的环境中执行相同的测量——实现冒泡排序,只考虑在必要时移动到更复杂的算法。
在一位评论员的建议下,我使用
srand(42)
和rand()
重新运行测试,以填充数组元素。在这种情况下,气泡排序的结果只稍微差一点,10000个元素的结果是642毫秒对413毫秒,1000个元素的结果是82毫秒对74毫秒
考虑到问题中的约束条件(小元素计数、不频繁排序、稳定性要求、低空间复杂度),与任何更复杂的算法相比,我仍然更喜欢气泡排序的简单性
不过,请记住我之前的建议:您需要在自己的环境中计时。结果可能大不相同。您可以使用我提供的代码作为这样做的基线。说真的,无论你选择哪种方法,只要不到一秒钟,就足以满足你的需要。系统是否嵌入并不重要。重要的是您列出的因素:代码大小限制、可用ram、所需速度和元素数量 正如您所概述的,冒泡排序是一个完全可以接受的解决方案:它小、可预测、易于内存,并且非常易于实现和调试。我在20世纪80年代初看到了一个证据,得出结论:对于n,冒泡排序是时间最优的≤ 11现代快速运动可能会稍微改变这一点,但我怀疑盈亏平衡可能会减少很多
要使不稳定的排序算法稳定,请添加包含原始位置的排序键。仅当主键是平局键时才参考辅助键。插入排序也很好,它在实践中运行速度快,稳定且到位。它与gnome排序非常相关,在实践中更快,但对于gnome排序,代码更小,占用的辅助空间更少(不是大O,区别在于常量) 编辑:是的,我搞砸了一点,把它们颠倒过来了——我可能不应该在喝咖啡之前回答问题。。它以前说过,插入排序比gnome排序的代码和空间要少删除“在嵌入式系统上”并将问题改为“一般来说,什么排序算法有用”。下一步,试试看!到目前为止,您尝试了什么,内存消耗是多少,执行时间是多少,代码大小是多少 嵌入式或台式机您应该执行这些实验并提出这些问题。没有一般的答案,因为没有一般的要求。根据需求,每个解决方案都有其位置。一刀切不适合任何人。真正的问题是您的需求是什么,然后您需要担心实现和满足这些需求。是否需要一种排序,是否可以用另一种方式解决?这种类型在您的总体绩效数字中占多少比例?帐篷里的其他长杆是什么 绝对法
Data size | qsort | bubble
----------+-------+-------
100 | 61 | 76
| 76 | 76
| 77 | 61
| 61 | 60
| 61 | 61 avg qsort = 67, bubble = 67
1000 | 77 | 93
| 61 | 45
| 76 | 77
| 77 | 76
| 76 | 77 avg qsort = 73, bubble = 74
| |
10000 | 92 | 414
| 77 | 413
| 61 | 413
| 76 | 405
| 61 | 421 avg qsort = 73, bubble = 413