哪种数据结构支持有效删除和随机访问?

时间:2013-03-07 13:32:27

标签: c++ arrays list data-structures random-access

我正在寻找一种数据结构,我可以在其中有效地删除项目并支持随机访问。

我还需要有效的插入,但由于元素的排序并不重要,我认为我可以预先分配内存以获得它可能必须存储的最大数量的元素,然后始终将新元素放在最后,以便不重新分配或移动其他因素是必要的。

据我所知,链表很适合删除,但访问其元素可能需要O(n)时间。另一方面,一个简单的数组(例如C ++中的vector)具有随机访问属性,但从这种结构中删除元素的复杂度为O(n)。

实际上,随机访问要求比我真正需要的要强。我只需要能够随机均匀地选择结构的元素。显而易见的高效访问属性意味着我需要的操作效率,但我不确定这两者是否相同。

提前致谢!

2 个答案:

答案 0 :(得分:6)

我相信你在问题中提示的解决方案实际上是你需要的,除了一个小细节。

你建议:

  

我认为我可以为可能必须存储的最大数量的元素预分配内存,然后始终将新元素放在最后,这样就不需要重新分配或移动其他元素。

如果您确实可以建立合理的最大条目数,那么我建议您预先分配一个数组(例如,如果在编译时已知最大值,则使用std::array,否则为std::vector )使用该数量的条目,建立元素计数(计算当前存储的元素数),并按以下步骤操作:

  1. 最初将计数设置为0
  2. 插入元素时,将其添加到末尾并递增计数
  3. 删除元素时,将其与最后一个元素交换并减少计数
  4. 对于随机访问(在您描述它的意义上,即字面上随机选取一个元素),您确定0和count之间的随机数,并选择该元素
  5. 我改变的唯一细节是元素删除,我建议你用开关位置实现最后一个元素

    可能的实施:

    #include <vector>
    #include <utility>
    #include <iostream>
    
    template <typename Elem>
    class randomaccesstable
    {
    public:
      randomaccesstable(std::size_t initial_size)
       : data_(initial_size) , count_(0)
      { }
    
      randomaccesstable &push_back(const Elem &elem)
      {
        if (count_ < data_.size())
          data_[count_++] = elem;
        else {
          data_.push_back(elem);
          ++count_;
        }
        return *this;
      }
    
      randomaccesstable &remove(const std::size_t index)
      {
        if (index < count_)
        {
          std::swap(data_[index],data_[count_-1]);
          --count_;
        }
        return *this;
      }
    
      const Elem &operator[](const std::size_t index) const
      { return data_[index]; }
    
      Elem &operator[](const std::size_t index)
      { return data_[index]; }
    
      std::size_t size() const
      { return count_; }
    
    private:
      std::vector<Elem>  data_;
      std::size_t        count_;
    };
    
    int main()
    {
      randomaccesstable<int> table(10);
      table.push_back(3);
      table.push_back(12);
      table.push_back(2);
    
      for (std::size_t i = 0 ; i < table.size() ; ++i)
        std::cout << table[i] << ' ';
      std::cout << '\n';
    
      table.remove(1);   // this removes the entry for 12, swapping it for 2
    
      for (std::size_t i = 0 ; i < table.size() ; ++i)
        std::cout << table[i] << ' ';
      std::cout << '\n';
    
      return 0;
    }
    

答案 1 :(得分:1)

我建议使用hash table。在那里你可以删除和查找具有恒定复杂性的元素。在C ++中,您可以使用std::unordered_map(C ++ 11)或boost::unordered_map(前C ++ 11)和java - HashMap