在c++中为嵌入式系统排序有效和无效的数字数组
Sorting an array of valid and invalid numbers in c++ for an embedded system
我正在用c++写一个程序,将与Windows Embedded Compact 7一起使用。我听说在编写嵌入式代码时最好不要动态分配数组。我将跟踪0到50个对象,所以我最初分配了50个对象。
Object objectList[50];
int activeObjectIndex[50];
static const int INVALID_INDEX = -1;
int activeObjectCount=0;
activeObjectCount告诉我实际使用了多少对象,activeObjectIndex告诉我使用了哪些对象。如果第0、第7和第10个对象被使用,我想要activeObjectIndex = [0,7,10,-1,-1,-1,...,-1];
和activeObjectCount=3;
当不同的对象变为活动或非活动时,我希望activeObjectIndex列表保持有序。
目前我只是排序的activeObjectIndex在每个循环结束时的值可能会改变。
首先,在嵌入式系统中,是否有比我正在做的更好的方法来跟踪对象(可能是活动的,也可能不是活动的)?如果没有,是否有一个算法,我可以使用保持对象排序每次我添加或删除一个活动对象?或者我应该周期性地做一个冒泡排序或者别的什么来保持它们的顺序?
您遇到了一个很难的问题,答案需要对您的系统有相当多的了解。没有这些知识,我所能给出的答案都是不完整的。然而,15年的嵌入式设计经验教会了我以下几点:
- 你是正确的,你通常不想要在运行时分配对象。预先分配所有对象,并将它们移动到活动/非活动队列。
- 把东西分类通常是困难的。也许你不需要。你没有提到它,但我敢打赌你真的只需要保持你的对象在"使用"answers"自由"池,你正在使用索引来快速查找/删除对象。
我提出以下解决方案。将对象更改为以下内容:
class Object {
Object *mNext, *mPrevious;
public:
Object() : mNext(this), mPrevious(this) { /* etc. */ }
void insertAfterInList(Object *p2) {
mNext->mPrev = p2;
p2->mNext = mNext;
mNext = p2;
p2->mPrev = this;
}
void removeFromList() {
mPrev->mNext = mNext;
mNext->mPrev = mPrev;
mNext = mPrev = this;
}
Object* getNext() {
return mNext;
}
bool hasObjects() {
return mNext != this;
}
};
和使用你的对象:
#define NUM_OBJECTS (50)
Object gObjects[NUM_OBJECTS], gFree, gUsed;
void InitObjects() {
for(int i = 0; i < NUM_OBJECTS; ++i) {
gFree.insertAfter(&mObjects[i]);
}
}
Object* GetNewObject() {
assert(mFree.hasObjects());
Object obj = mFree->getNext();
obj->removeFromList();
gUsed.insertAfter(obj);
return obj;
}
void ReleaseObject(Object *obj) {
obj->removeFromList();
mFree.insertAfter(obj);
}
编辑修复一个小故障。应该现在工作,虽然没有测试。:)
std::vector的开销非常小。您可能遇到的问题是,动态调整大小将分配比所需更多的内存。然而,由于您有50个元素,这应该不是一个问题。试一试,只有当你看到强烈的影响时才改变它。
如果你不能/不想从std::vector中删除未使用的对象,你可以在你的Object中添加一个布尔值来指示它是否处于活动状态。这不会比使用activeObjectIndex需要更多的内存(甚至可能更少,取决于对齐问题)。
要用布尔值对数据进行排序(最后不活动),编写一个函数:
bool compare(const Object & a, const Object & b) {
if(a.active && !b.active) return true;
else return false;
}
std::sort(objectList,objectList + 50, &compare); // if you use an array
std::sort(objectList.begin(),objectList.end(), &compare); // if you use std::vector
如果你想用activeObjectIndex排序,那将会更复杂。如果你想使用一个总是有序的结构,使用std::set。然而,它将需要更多的内存(但对于50个元素,这不会是一个问题)。
理想情况下,实现以下功能:
bool operator<(const Object & a, const Object & b) {
if(a.active && !b.active) return true;
else return false;
}
这将允许直接使用std::sort(objectList.begin(), objectList.end())或声明一个std::set保持排序
跟踪活动/非活动的一种方法是将活动对象放在双链表中。当一个对象从非活动状态变为活动状态时,将其添加到列表中,而从活动状态变为非活动状态时,将其从列表中删除。您可以将这些添加到对象
Object * next, * prev;
如果不允许动态内存分配,我将使用简单的c-array或std::array
和指向last+1对象的索引。对象总是保持有序。
加法是通过将新对象插入到已排序列表的正确位置来完成的。要找到插入位置,可以使用lower_bound
或find_if
。对于50个元素,秒可能会更快。移除也是类似的。
您不应该担心列表排序,因为编写一个方法来搜索索引列表中的活动索引将是O(N)
,并且,在您的特殊情况下,平销到O(1)
,因为您的数组似乎足够小,可以进行这个小小的额外验证。
你可以维持最后一个被检查元素的索引,直到它达到极限:
unsigned int next(const unsigned int& last) {
for (unsigned int i = last + 1; i < MAX_ARRAY_SIZE; i++) {
if (activeObjectIndex[i] != -1) {
return i;
}
}
return -1;
}
然而,如果你真的想有一个侧索引,你可以简单地将数组的大小加倍,创建一个双链表的元素:
activeObjectIndex[MAX_ARRAY_SIZE * 3] = {-1};
activeObjectIndex[i] = "element id";
activeObjectIndex[i + 1] = "position of the previous element";
activeObjectIndex[i + 2] = "position of the next element";
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 无法访问嵌套类.类的使用无效
- 如何用数字处理log(0)
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 查找最接近的大于当前数字的数字的索引
- 找到两对数字,使它们的乘积的绝对差最小化
- 使用 std::locale 格式化法语数字时无效的 UTF-8 数据
- 用户输入逻辑运算符符号或数字,如果输入字符或字符串则无效
- 为什么此 DirectX 10 "D3DXVec3Lerp" 函数返回无效数字?
- 带有 cl 的 cmake:无效的数字参数 '/Wno-uninitialized'
- 无效数字总是降到0
- 错误 D8021:无效的数字参数'/wdtrue'
- 数组中的无效八进制数字是否有解决方法
- 在 pthread_t 为数字的平台上,0 保证为无效值
- 使用nmake编译Qt给出命令行错误D8021:无效的数字参数' /FS '