C ++固定大小的链表

时间:2013-04-07 01:33:36

标签: c++ list

非重复:

动机:

分配发生一次(在构造函数中)并且释放一次(在析构函数中)。

O(1)在列表中的任何位置插入和删除元素,而无需处理内存管理的开销。对于基于数组的实现,这是不可能的。

使用标准库是否有直接的方法来实现它?在Boost中是否有类似的实现?

3 个答案:

答案 0 :(得分:1)

我认为最简单的方法是拥有2个数据结构。一个固定大小的数组/向量,用于“分配”。您只需从数组中获取一个元素即可创建一个节点并将其插入到列表中。这样的东西似乎符合你的要求:

struct node {
    node *prev;
    node *next;
    int value;
};

node storage[N];
node *storage_ptr = storage;

然后创建一个新节点:

if(node == &[storage + N]) {
    /* out of space */
}

node *new_node = *storage_ptr++;
// insert new_node into linked list

这是固定大小,一次性分配,当storage超出范围时,节点将被破坏。

至于有效地从列表中删除项目,它是可行的,但稍微复杂一些。我将为“已删除”节点提供辅助链接列表。从主列表中删除node时,将其插入“已删除”列表的结尾/开头。

分配时,首先检查已删除的列表,然后再转到storage阵列。如果NULL使用storage,则将其从列表中删除。

答案 1 :(得分:1)

当我读到时,我首先想到的是使用不同分配器的方法,即预先分配给定数量的元素以避免分配价格的分配器。我不熟悉定义分配器,但如果你发现我对结果感兴趣。

没有它,这是一种不同的方法。我为自己保存了template ...的东西,但我想如果你需要,你可以自己做。

typedef std::list<...> list_t;

struct fslist: private list_t
{
    // reuse some parts from the baseclass
    using list_t::iterator;
    using list_t::const_iterator;
    using list_t::begin;
    using list_t::end;
    using list_t::empty;
    using list_t::size;

    void reserve(size_t n)
    {
        size_t s = size();
        // TODO: Do what std::vector does when reserving less than the size.
        if(n < s)
            return;
        m_free_list.resize(n - s);
    }

    void push_back(element_type const& e)
    {
        reserve_one();
        m_free_list.front() = e;
        splice(end(), m_free_list, m_free_list.begin());
    }

    void erase(iterator it)
    {
        m_free_list.splice(m_free_list.begin(), *this, it);
    }

private:
    // make sure we have space for another element
    void reserve_one()
    {
        if(m_free_list.empty())
            throw std::bad_alloc();
    }
    list_t m_free_list;
};

这是不完整的,但它应该让你开始。另请注意,splice()不会公开,因为将元素从或移动到不同的列表会改变大小和容量。

答案 2 :(得分:0)

我最终为这个名为rigid_list的人编写了一个模板。 它还远未完成,但它是一个开始:

https://github.com/eltomito/rigid_list

(由Ulrich Eckhardt的答案推动)