How to extract an element from a deque? - c++

Given the following code :
void World::extractStates(deque<string> myDeque)
{
unsigned int i = 0;
string current; // current extracted string
while (i < myDeque.size()) // run on the entire vector and extract all the elements
{
current = myDeque.pop_front(); // doesn't work
// do more stuff
}
}
I want to extract each iteration the element at the front , but pop_front() is a void
method . How can I get the element (at the front) then ?
Regards

Use front to read the item and pop_front to remove it.
current = myDeque.front();
myDeque.pop_front();
This way of doing things may seem counter-productive, but it is necessary in order for deque to provide adequate exception-safety guarantees.

Related

Fast algorithm to remove odd elements from vector

Given a vector of integers, I want to wrote a fast (not obvious O(n^2)) algorithm to remove all odd elements from it.
My idea is: iterate through vector till first odd element, then copy everything before it to the end of vector (call push_back method) and so on until we have looked through all original elements (except copied ones), then remove all of them, so that only the vector's tail survive.
I wrote the following code to implement it:
void RemoveOdd(std::vector<int> *data) {
size_t i = 0, j, start, end;
uint l = (*data).size();
start = 0;
for (i = 0; i < l; ++i)
{
if ((*data)[i] % 2 != 0)
{
end = i;
for (j = start, j < end, ++j)
{
(*data).push_back((*data)[j]);
}
start = i + 1;
}
}
(*data).erase((*data).begin(), i);
}
but it gives me lots of errors, which I can't fix. I'm very new to the programming, so expect that all of them are elementary and stupid.
Please help me with error corrections or another algorithm implementation. Any suggestions and explanations will be very appreciative. It is also better not to use algorithm library.
You can use the remove-erase idiom.
data.erase(std::remove_if(data.begin(), data.end(),
[](int item) { return item % 2 != 0; }), data.end());
You don't really need to push_back anything (or erase elements at the front, which requires repositioning all that follows) to remove elements according to a predicate... Try to understand the "classic" inplace removal algorithm (which ultimately is how std::remove_if is generally implemented):
void RemoveOdd(std::vector<int> & data) {
int rp = 0, wp = 0, sz = data.size();
for(; rp<sz; ++rp) {
if(data[rp] % 2 == 0) {
// if the element is a keeper, write it in the "write pointer" position
data[wp] = data[rp];
// increment so that next good element won't overwrite this
wp++;
}
}
// shrink to include only the good elements
data.resize(wp);
}
rp is the "read" pointer - it's the index to the current element; wp is the "write" pointer - it always points to the location where we'll write the next "good" element, which is also the "current length" of the "new" vector. Every time we have a good element we copy it in the write position and increment the write pointer. Given that wp <= rp always (as rp is incremented once at each iteration, and wp at most once per iteration), you are always overwriting either an element with itself (so no harm is done), or an element that has already been examined and either has been moved to its correct final position, or had to be discarded anyway.
This version is done with specific types (vector<int>), a specific predicate, with indexes and with "regular" (non-move) assignment, but can be easily generalized to any container with forward iterators (as its done in std::remove_if) and erase.
Even if the generic standard library algorithm works well in most cases, this is still an important algorithm to keep in mind, there are often cases where the generic library version isn't sufficient and knowing the underlying idea is useful to implement your own version.
Given pure algorithm implementation, you don't need to push back elements. In worst case scenario, you will do more than n^2 copy. (All odd data)
Keep two pointers: one for iterating (i), and one for placing. Iterate on all vector (i++), and if *data[I] is even, write it to *data[placed] and increment placed. At the end, reduce length to placed, all elements after are unecessary
remove_if does this for you ;)
void DeleteOdd(std::vector<int> & m_vec) {
int i= 0;
for(i= 0; i< m_vec.size(); ++i) {
if(m_vec[i] & 0x01)
{
m_vec.erase(m_vec.begin()+i);
i--;
}
}
m_vec.resize(i);
}

How to iterate through a list while adding items to it

I have a list of line segments (a std::vector<std::pair<int, int> > that I'd like to iterate through and subdivide. The algorithm would be, in psuedocode:
for segment in vectorOfSegments:
firstPoint = segment.first;
secondPoint = segment.second;
newMidPoint = (firstPoint + secondPoint) / 2.0
vectorOfSegments.remove(segment);
vectorOfSegments.push_back(std::make_pair(firstPoint, newMidPoint));
vectorOfSegments.push_back(std::make_pair(newMidPoint, secondPoint));
The issue that I'm running into is how I can push_back new elements (and remove the old elements) without iterating over this list forever.
It seems like the best approach may be to make a copy of this vector first, and use the copy as a reference, clear() the original vector, and then push_back the new elements to the recently emptied vector.
Is there a better approach to this?
It seems like the best approach may be to make a copy of this vector first, and use the copy as a reference, clear() the original vector, and then push_back the new elements to the recently emptied vector.
Almost. You don't need to copy-and-clear; move instead!
// Move data from `vectorOfSegments` into new vector `original`.
// This is an O(1) operation that more than likely just swaps
// two pointers.
std::vector<std::pair<int, int>> original{std::move(vectorOfSegments)};
// Original vector is now in "a valid but unspecified state".
// Let's run `clear()` to get it into a specified state, BUT
// all its elements have already been moved! So this should be
// extremely cheap if not a no-op.
vectorOfSegments.clear();
// We expect twice as many elements to be added to `vectorOfSegments`
// as it had before. Let's reserve some space for them to get
// optimal behaviour.
vectorOfSegments.reserve(original.size() * 2);
// Now iterate over `original`, adding to `vectorOfSegments`...
Don't remove elements while you insert new segments. Then, when finished with inserting you could remove the originals:
int len=vectorOfSegments.size();
for (int i=0; i<len;i++)
{
std::pair<int,int>& segment = vectorOfSegments[i];
int firstPoint = segment.first;
int secondPoint = segment.second;
int newMidPoint = (firstPoint + secondPoint) / 2;
vectorOfSegments.push_back(std::make_pair(firstPoint, newMidPoint));
vectorOfSegments.push_back(std::make_pair(newMidPoint, secondPoint));
}
vectorOfSegments.erase(vectorOfSegments.begin(),vectorOfSegments.begin()+len);
Or, if you want to replace one segment by two new segments in one pass, you could use iterators like here:
for (auto it=vectorOfSegments.begin(); it != vectorOfSegments.end(); ++it)
{
std::pair<int,int>& segment = *it;
int firstPoint = segment.first;
int secondPoint = segment.second;
int newMidPoint = (firstPoint + secondPoint) / 2;
it = vectorOfSegments.erase(it);
it = vectorOfSegments.insert(it, std::make_pair(firstPoint, newMidPoint));
it = vectorOfSegments.insert(it+1, std::make_pair(newMidPoint, secondPoint));
}
As Lightning Racis in Orbit pointed out, you should do a reserve before either of these approaches. In the first case do reserve(vectorOfSegmets.size()*3), in the latter reserve(vectorOfSegmets.size()*2+1)
This is easiest solved by using an explicit index variable like this:
for(size_t i = 0; i < segments.size(); i++) {
... //other code
if(/*condition when to split segments*/) {
Point midpoint = ...;
segments[i] = Segment(..., midpoint); //replace the segment by the first subsegment
segments.emplace_back(Segment(midpoint, ...)); //add the second subsegment to the end of the vector
i--; //reconsider the first subsegment
}
}
Notes:
segments.size() is called in each iteration of the loop, so we really reconsider all appended segments.
The explicit index means that the std::vector<> is free to reallocate in the emplace_back() call, there are no iterators/pointers/references that can become invalid.
I assumed that you don't care about the order of your vector because you add the new segments to the end of the vector. If you do care, you might want to use a linked list to avoid quadratic complexity of your algorithm as insertion/deletion to/from an std::vector<> has linear complexity. In my code I avoid insertion/deletion by replacing the old segment.
Another approach to retain order would be to ignore order at first and then reestablish order via sorting. Assuming a good sorting algorithm, that is O(n*log(n)) which is still better than the naive O(n^2) but worse than the O(n) of the linked list approach.
If you don't want to reconsider the new segments, just use a constant size and omit the counter decrement:
size_t count = segments.size();
for(size_t i = 0; i < count; i++) {
... //other code
if(/*condition when to split segments*/) {
Point midpoint = ...;
segments[i] = Segment(..., midpoint); //replace the segment by the first subsegment
segments.emplace_back(Segment(midpoint, ...)); //add the second subsegment to the end of the vector
}
}

How to add random strings alphabetically to an array using a Bi-Sectional Search

This is my add function. I haven't finished it yet, I have to add strings into the array using sequential search to find the insertion point to add in alphabetical order. I just included this b/c we use it when we add random strings.
void StringList::add(string s)
{
str[numberOfStrings++]=s;
}
This is my bisectional search function
int StringList::bsearch(string key, int start, int end)
{
int middle = (end + start)/2;
if(key>str[middle])
{
return bsearch(key, middle+1, end);
}
else if (key<str[middle])
{
return bsearch(key, start, middle);
}
else if(start==end)
{
return -1;
}
}
Here is my code to add a random number of strings to the array. (In a seperate cpp file that uses a transducer)
if((token[0]=="ADDRAND")||(token[0]=="AR"))
{
int count = stringToInt(token[1]);
for(int i=0;i<count;i++)
{
stringList.add(randString(20));
}
result = "Random Strings added.\n";
}
How do I use the Bi-sectional search to add the random strings to the array in alphabetical order using this?
The first thing to do would be to modify your bsearch() so that it may return the index where to insert the string if not found (a good start may be returning start instead of -1, but I don't know if it's enough).
If even you are able to find the index where to insert, you have to push all the elements after that index by a step to make place for that string. So this will take linear time for each step. I don't think you would be able to use your bi-sectional search method to dynamically update array and keep it sorted. Either insertion of string in array or searching of index will take time if you try to keep sorted strings in contiguous string indices.
For this purpose, you need to use some tree structure such as AVL Tree or RB tree. Moreover stl set can serve the purpose if you need readymade structure.

How to delete arbitrary objects in repeated field? (protobuf)

I have some entries in the repeated field in my proto. Now I want delete some of them. How can I accomplish this? There is a function to delete the last element, but I want to delete arbitrary elements. I cant just swap them because the order is important.
I could swap with next until end, but isn't there a nicer solution?
For Protobuf v3
iterator RepeatedField::erase(const_iterator position) can delete at arbitrary position.
For Protobuf v2
You can use the DeleteSubrange(int start, int num) in RepeatedPtrField class.
If you want to delete a single element then you have to call this method as DeleteSubrange(index_to_be_del, 1). It will remove the element at that index.
According to the API docs, there isn't a way to arbitrarily remove an element from within a repeated field, just a way to remove the last one.
...
We don't provide a way to remove any element other than the last
because it invites inefficient use, such as O(n^2) filtering loops
that should have been O(n). If you want to remove an element other
than the last, the best way to do it is to re-arrange the elements so
that the one you want removed is at the end, then call RemoveLast()
...
What I usually do in these cases is to create a new Protobuf (PB) message. I iterate the repeated fields of the existing message and add them (except the ones you don't want anymore) to the new PB message.
Here is example:
message GuiChild
{
optional string widgetName = 1;
//..
}
message GuiLayout
{
repeated ChildGuiElement children = 1;
//..
}
typedef google_public::protobuf::RepeatedPtrField<GuiChild> RepeatedField;
typedef google_public::protobuf::Message Msg;
GuiLayout guiLayout;
//Init children as necessary..
GuiChild child;
//Set child fileds..
DeleteElementsFromRepeatedField(*child, guiLayout->mutable_children());
void DeleteElementsFromRepeatedField(const Msg& msg, RepeatedField* repeatedField)
{
for (RepeatedField::iterator it = repeatedField->begin(); it != repeatedField->end(); it++)
{
if (google_public::protobuf::util::MessageDifferencer::Equals(*it, msg))
{
repeatedField->erase(it);
break;
}
}
}
Although there's no straight-forward method you still can do this (for custom message using reflection). Code below removes count repeated field items starting from row index.
void RemoveFromRepeatedField(
const google::protobuf::Reflection *reflection,
const google::protobuf::FieldDescriptor *field,
google::protobuf::Message *message,
int row,
int count)
{
int size = reflection->FieldSize(*message, field);
// shift all remaining elements
for (int i = row; i < size - count; ++i)
reflection->SwapElements(message, field, i, i + count);
// delete elements from reflection
for (int i = 0; i < count; ++i)
reflection->RemoveLast(message, field);
}

Inserting an item at the beginning of a protobuf list

I'm trying to insert an item at the beginning of a protobuf list of messages. add_foo appends the item to end. Is there an easy way to insert it at the beginning?
There's no built-in way to do this with protocol buffers AFAIK. Certainly the docs don't seem to indicate any such option.
A reasonably efficient way might be to add the new element at the end as normal, then reverse iterate through the elements, swapping the new element in front of the previous one until it's at the front of the list. So e.g. for a protobuf message like:
message Bar {
repeated bytes foo = 1;
}
you could do:
Bar bar;
bar.add_foo("two");
bar.add_foo("three");
// Push back new element
bar.add_foo("one");
// Get mutable pointer to repeated field
google::protobuf::RepeatedPtrField<std::string> *foo_field(bar.mutable_foo());
// Reverse iterate, swapping new element in front each time
for (int i(bar.foo_size() - 1); i > 0; --i)
foo_field->SwapElements(i, i - 1);
std::cout << bar.DebugString() << '\n';