簡體   English   中英

在向量中插入多個值

[英]Insert multiple values into vector

我有一個std::vector<T>變量。 我還有兩個類型為T的變量,第一個表示我要插入的向量中的值,而第二個表示要插入的值。

所以我想說我有這個容器: 1,2,1,1,2,2

並且就上面的定義而言,這兩個值是2和3。 然后我希望編寫一個函數來更新容器,而不是包含:

1,2,3,1,1,2,3,2,3

我正在使用c ++ 98和boost。 我可以用什么std或boost函數來實現這個功能?

迭代向量並使用std :: insert是一種方法,但當你意識到你需要記住跳過你剛剛插入的值時它會變得混亂。

這是我可能會做的:

vector<T> copy;
for (vector<T>::iterator i=original.begin(); i!=original.end(); ++i)
{
    copy.push_back(*i);
    if (*i == first)
        copy.push_back(second);
}
original.swap(copy);

如果你願意,可以打電話預約。 你知道至少需要為original.size()元素留出空間。 你也可以在向量上做一個初始的iteraton(或使用std::count )來確定要保留的元素的確切數量,但是如果沒有測試,我不知道這是否會提高性能。

我提出了一個在內存和O(n)內存和O(2n)時間內工作的解決方案。 通過本傑明提出的解決方案,Laethnes和O(2n)在記憶中提出的解決方案及時代替O(n ^ 2)。

// First pass, count elements equal to first.
std::size_t elems = std::count(data.begin(), data.end(), first);
// Resize so we'll add without reallocating the elements.
data.resize(data.size() + elems);
vector<T>::reverse_iterator end = data.rbegin() + elems;
// Iterate from the end. Move elements from the end to the new end (and so elements to insert will have some place).
for(vector<T>::reverse_iterator new_end = data.rbegin(); end != data.rend() && elems > 0; ++new_end,++end)
{
  // If the current element is the one we search, insert second first. (We iterate from the end).
  if(*end == first)
  {
    *new_end = second;
    ++new_end;
    --elems;
  }
  // Copy the data to the end.
  *new_end = *end;
}

這個算法可能有問題,但想法是每個元素只復制一次:

  1. 首先計算我們需要插入多少元素。
  2. 其次,從最后遍歷數據並將每個元素移動到新的結尾。

這就是我可能會做的事情:

typedef ::std::vector<int> MyList;
typedef MyList::iterator MyListIter;

MyList data;

// ... fill data ...

const int searchValue = 2;
const int addValue = 3;

// Find first occurence of searched value
MyListIter iter = ::std::find(data.begin(), data.end(), searchValue);

while(iter != data.end())
{
    // We want to add our value after searched one
    ++iter;

    // Insert value and return iterator pointing to the inserted position
    // (original iterator is invalid now).
    iter = data.insert(iter, addValue);

    // This is needed only if we want to be sure that out value won't be used
    // - for example if searchValue == addValue is true, code would create
    // infinite loop.
    ++iter;

    // Search for next value.
    iter = ::std::find(iter, data.end(), searchValue);
}

但正如你所看到的,我無法避免你提到的增量。 但我不認為那會是壞事:我會把這些代碼放在單獨的函數中(可能在某種“core / utils”模塊中) - 當然 - 將這個函數實現為模板,所以我只會寫它曾經 - 只有一次擔心增加價值是恕我直言可以接受的。 非常接受。

template <class ValueType>
void insertAfter(::std::vector<ValueType> &io_data,
                 const ValueType &i_searchValue,
                 const ValueType &i_insertAfterValue);

甚至更好(恕我直言)

template <class ListType, class ValueType>
void insertAfter(ListType &io_data,
                 const ValueType &i_searchValue,
                 const ValueType &i_insertAfterValue);

編輯:

好吧,我會用一點點不同的方式解決問題:首先計算搜索值出現的次數(最好存儲在某種緩存中,可以保存並重復使用)所以我可以准備數組(只有一次分配)並使用memcpy來移動原始值(對於類似int的類型,當然)或memmove(如果向量分配的大小已經足夠)。

在適當的位置,O(1)額外的記憶和O(n)時間( 在Coliru生活 ):

template <typename T, typename A>
void do_thing(std::vector<T, A>& vec, T target, T inserted) {
    using std::swap;

    typedef typename std::vector<T, A>::size_type size_t;
    const size_t occurrences = std::count(vec.begin(), vec.end(), target);
    if (occurrences == 0) return;

    const size_t original_size = vec.size();
    vec.resize(original_size + occurrences, inserted);

    for(size_t i = original_size - 1, end = i + occurrences; i > 0; --i, --end) {
        if (vec[i] == target) {
            --end;
        }
        swap(vec[i], vec[end]);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM