在c ++中为嵌入式系统排序有效和无效数字的数组

时间:2012-12-24 21:01:36

标签: c++ c algorithm sorting embedded

我正在编写一个用于Windows Embedded Compact 7的C ++程序。我听说在编写嵌入代码时最好不要动态分配数组。我将跟踪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进行排序。

首先,是否有更好的方法来跟踪嵌入式系统中的对象(可能是也可能不是活动的),而不是我正在做的事情?如果没有,是否有一个算法可以用来在每次添加或删除活动对象时保持对象排序?或者我应该定期进行冒泡排序或其他什么来保持秩序?

5 个答案:

答案 0 :(得分:1)

std :: vector的开销非常小。您可能遇到的问题是动态调整大小将分配比所需更多的内存。但是,由于你有50个元素,这应该不是问题。尝试一下,只有在看到强烈影响时才进行更改。

如果您不能/不想从std :: vector中删除未使用的对象,您可以在对象中添加一个布尔值来指示它是否处于活动状态?这不需要比使用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。

答案 1 :(得分:1)

跟踪活动/非活动状态的一种方法是让活动对象位于双向链接列表中。当对象从非活动状态变为活动状态时,则添加到列表中,并从列表中激活为非活动状态。您可以将这些添加到对象

Object * next, * prev;

所以这不需要内存分配。

答案 2 :(得分:1)

如果不允许动态内存分配,我会使用简单的c-array或std::array和索引,它指向最后的+ 1对象。对象始终按排序顺序保存。

通过将新对象插入到排序列表的正确位置来完成添加。要查找插入位置lower_boundfind_if,可以使用。对于50元素,第二可能会更快。删除是类似的。

答案 3 :(得分:1)

您不应该担心列表已排序,因为编写一个方法来搜索索引列表中哪些是活动的O(N),并且在您的特定情况下,分摊到{{1} },因为你的数组似乎足够小,可以进行额外的验证。

您可以维护检查的最后一个元素的索引,直到达到限制:

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;

}

答案 4 :(得分:1)

你有一个难题,答案需要对你的系统有相当多的了解。没有这些知识,我能给出的答案就不会完整。然而,15年的嵌入式设计教会了我以下内容:

  1. 你是对的,你通常想要在运行时分配对象。预分配所有对象,并将它们移动到活动/非活动队列。
  2. 保持整理通常很难。也许你不需要。你没有提到它,但我敢打赌你真的只需要将你的对象保存在“二手”和“免费”池中,并且你正在使用索引来快速查找/删除对象。
  3. 我提出以下解决方案。将您的对象更改为以下内容:

    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);
    }
    

    编辑修复一个小故障。现在应该工作,虽然没有经过测试。 :)