Printing the elements of an unordered_set - c++

So I am writing a small code to remove the duplicate characters from a string. I have done it using map, vector but wanted to use unordered_set.
#include <iostream>
#include <unordered_set>
#include <string.h>
using namespace std;
int main() {
char* str = "abbcdeffg";
std::unordered_set<char> ump;
for(int i = 0; i < strlen(str) ; i++)
{
ump.insert(str[i]);
}
for (auto it = ump.begin(); it != ump.end(); ++it)
{
cout << *it;
}
return 0;
}
However, the elements are being printed in the reverse order of their insertion. The output is gfedcba. Please can someone explain why?
And what would be the best way to print the elements in the original order. There is no operator--() in unordered_set as it has got forward iterator.
Thanks!

You cannot.
An unordered set does not have any inherent ordering.
That's why it's called an unordered set.
A vector (or, better yet, a deque) would be the appropriate output container here, but you could possibly make use an additional, temporary, set, to keep track of duplicates whilst you iterate.

Related

Append a copy of std::vector to the end of itself [duplicate]

This question already has answers here:
Nice way to append a vector to itself
(4 answers)
Closed 8 years ago.
I am trying to make a copy of a vector of string and append it to the end of its original vector, i.e. duplicating its contents. Example:
Input : vector<string> s = {"abc", "def"}
Output: vector<string> s = {"abc", "def", "abc", "def"}
I was using the insert method, i.e.
s.insert(s.end(), s.begin(), s.end());
However, this exhibits compiler-dependent results. In, LLVM clang, it gave me the expected answer.
With GCC it gave me
Output: vector<string> s = {"abc", "def", "", ""}
I am wondering why this happens and what's the safest way to achieve this vector duplication goal?
Here is the ideone.com link for the program above: http://ideone.com/40CH8q
Although it can possibly be done with iterators, a safe alternative is to avoid them:
size_t size = v.size(); // Of course we shouldn't access .size() in the loop...
v.reserve(size * 2); // Preallocation. Thanks #Ali for this performance hint
for (size_t i = 0; i < size; ++i)
v.push_back(v[i]);
In general, working with iterators while also modifying the data structure (not only its elements) is dangerous; you should read carefully when iterators are invalidated and when it's safe to reuse old iterators after a modification. Thus, it sometimes makes sense to use the "old" method to iterate through a random-access sequence: using an index variable.
As others have already pointed out, you need to make sure by calling vector::reserve() that the vector doesn't get reallocated during insertion. (It is also a good idea to call reserve if you chose to put the elements with push_back() into your vector.)
Then there is still the iterator invalidation issue (as detailed under vector::insert()) but the code below, as far as I know, bypasses that:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> s{"abc", "def"};
auto size = s.size();
s.reserve(2*size); // <-- This one is essential to ensure
// no reallocation during insertion
const string* first = s.data(); // using pointer, instead of iterator
copy(first, first+size, back_inserter(s));
for (const auto& e : s)
cout << e << '\t';
cout << endl;
}
As already stated, it seems all you need to do is make a call to reserve:
sv.reserve(sv.size() * 2);
This is because if a reallocation occurs, the iterators are invalidated. You can check this for yourself:
std::cout << sv.capacity() << "\n"; // 2
The new size will be bigger than the capacity so a reallocation occurs.
This can be done this way too
vector<string> data = {"abc", "def"}; // Input String Vector
int len = data.size();
for(int i = 0; i < len; i++)
{
data.push_back(data[i]); // Making Copy of String Vector
}
vector<string> data = {"abc", "def", "abc", "def"};
//Resultant String Vector

Producing permutations of a set of integers in C++. Getting Segmentation Fault

I was trying to solve a problem which involved producing all the permutations of a set of numbers. The idea seemed simple enough (code below), but I keep getting segmentation faults. Can anyone tell me what I'm doing wrong?
void permute(set<int>& s, vector<int>& v) {
if(s.empty()) {
// read the permutation in v.
return;
}
set<int>::iterator i;
for(i = s.begin(); i != s.end(); i++) {
int x = *i;
s.erase(i);
v.push_back(x);
permute(s, v);
v.pop_back();
s.insert(x);
}
}
To produce all permutations in C++ use std::next_permutation. The problem here is that you cannot permutate the set, because the ordering is preset by the key comparator operator (in your case the less than operator). What you can do is store your values in a non associative container and then have a go.
#include <set>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
void permut(std::set<int> const &inp, std::vector<int> &all_permutations)
{
vector<int> tmp(inp.size());
copy(inp.begin(), inp.end(), tmp.begin());
vector<int> all_permutations;
do
{
copy(tmp.begin(), tmp.end(), back_inserter(all_permutations));
} while (std::next_permutation(tmp.begin(), tmp.end()));
}
The permute() function calls itself recursively while iterating over the mutable containers and making changes. This violates iterator validity promises.
You might try something based on std::next_permutation()
I have not gone into the precise behaviour you can expect from a set, but it seems pretty clear that the things you are doing inside the for loop are enough to make the iterator invalid. I would suggest redesigning things so that you have two sets, and work through one (which starts off full) while generating the permutation in the other (which starts off empty).

how to delete set in c++ or how to resize the set to 0

I want to resize the set to 0 but it's giving an error on line 16. How can I resize the set to empty set? In line 16 the resize algorithm is giving an error.
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main()
{
set<int> p;
set<int> a[2];
p.insert(0);
p.insert(1);
a[0] = p;
a[0].insert(3);
set<int>::iterator it;
for (it = a[0].begin(); it != a[0].end(); ++it)
std::cout << ' ' << *it;
a[0].resize(0);
cout << a[0].size();
return 0;
}
Just use the clear method of std::set
std::set does not have a resize member. Perhaps you were thinking of std::vector?
But for any STL container, the idiomatic way to clear it is with the clear().
a[0].clear();
std::set doesn't have resize function.
Use clear() method of std::set container
a[0].clear();
You can delete a (set of integers), as follows:
std::set<int>().swap(a);

Vectors in C++ : Why i'm getting so much errors for this simple copy & print program?

i'm trying to use algorithm lib & vector lib to first copy a set of numbers from an array into a vector then printing it using iteration, where is the problem of my code?
and one thing is that i chose 2 way to do this iteration first using vec.begin() ; vec.end() method & the other one is for (i = 0 ; i < vec.capacity() ; i++)
both facing errors.
what should i do?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int intArray[] = {5,6,8,3,40,36,98,29,75};
vector<int> vecList(9);
//vector<int>::iterator it;
copy (intArray, intArray+9,vecList);
//for(it = vecList.begin() ; it != vecList.end() ; it++)
for (int it = 0 ; it < vecList.capacity() ; it++)
{
cout<<*it<<endl;
}
system("pause");
return 0;
}
There are several improvements possible.
You confuse iterators with indices. An iterator it is a glorified pointer into the vector, that you need to derefence by typing *it. An index i is an offset from the beginning of the vector and saying vecList[i] will give you that element.
The initialization of the vector is best done using initializer lists (C++11), rather than reading from an array.
You need to loop to vecList.size(). The capacity of the vector is the size of the allocated storage space for the elements of the vector container. Looping is best done with a ranged-for loop as shown by Kerrek SB, or a std::for_each + a lambda expression, or a regular for loop as you did. In that case however, it's best to get into the habit of doing it != vecList.end() (instead of using <) and doing ++it instead of it++.
Note that I also used auto to avoid writing the explicit iterator type. It's also a good habit to get into using auto wherever you can.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
// initialize vector with a list of elements
vector<int> vecList {5,6,8,3,40,36,98,29,75};
// loop from begin() to end() of vector, doing ++it instead of it++
for (auto it = vecList.begin(); it != vecList.end(); ++it)
{
cout<<*it<<endl;
}
// the pause command is better done by setting a breakpoint in a debugger
return 0;
}
Output on Ideone (this uses the g++ 4.5.1 compiler, it's best to upgrade to at least that version to take advantage of C++11 features).
The problem is that you're confusing indexes and iterators.
w/ index:
for (int i = 0 ; i < vecList.size() ; it++)
{
cout<<vecList[i]<<endl;
}
w/ iterators
for (std::vector<int>::const_iterator it = vecList.begin() ; i != vecList.end() ; it++)
{
cout<<*it<<endl;
}
A. you need to iterate on vecList.size() not vecList.capacity() which mean how much memory the vector is reserving for himself (not how much of it is in use).
B. you tried to use the integer index it as an iterator with the call to *it, you should check Luchian Grigore answer for the right way to do it.
This isn't an answer, but I wanted to show how modern C++ allows you to do away with lots of the brittle dependencies on details:
int intArray[] = {5,6,8,3,40,36,98,29,75};
std::vector<int> vecList(std::begin(intArray), std::end(intArray));
for (int i : vecList) { std::cout << i << std::endl; }
Using iterators and algorithms idiomatically, you can often remove any explicit mention of details such as lengths of arrays, thus making your code more robust.
Typo mistake use : copy (intArray, intArray+9,vecList.begin());
so,
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
int main()
{
int intArray[] = {5,6,8,3,40,36,98,29,75};
vector<int> vecList(9);
vector<int>:: iterator it;
copy (intArray, intArray+9,vecList.begin());
for (it=vecList.begin();it!=vecList.end(); it++)
{
cout<<*it<<endl;
}
system("pause");
return 0;
}

Efficient way to remove items from vector

Currently, I plan to remove all items from vector, which is not found in a set.
For example :
#include <vector>
#include <set>
#include <string>
#include <iostream>
using namespace std;
int main() {
std::set<string> erase_if_not_found;
erase_if_not_found.insert("a");
erase_if_not_found.insert("b");
erase_if_not_found.insert("c");
std::vector<string> orders;
orders.push_back("a");
orders.push_back("A");
orders.push_back("A");
orders.push_back("b");
orders.push_back("c");
orders.push_back("D");
// Expect all "A" and "D" to be removed.
for (std::vector<std::string>::iterator itr = orders.begin(); itr != orders.end();) {
if (erase_if_not_found.find(*itr) == erase_if_not_found.end()) {
orders.erase(itr);
// Begin from start point again? Do we have a better way?
itr = orders.begin();
} else {
++itr;
}
}
for (std::vector<std::string>::iterator itr = orders.begin(); itr != orders.end(); ++itr) {
std::cout << *itr << std::endl;
}
getchar();
}
Although the above code work, it is not efficient, as I begin from vector's start point each time I delete an item.
Is there a better way?
Yes; you can use the erase/remove idiom with a custom predicate:
template <typename SetT>
struct not_contained_in_set_impl
{
not_contained_in_set_impl(const SetT& s) : set_(s) { }
template <typename T>
bool operator()(const T& v)
{
return set_.find(v) == set_.end();
}
const SetT& set_;
};
template <typename SetT>
not_contained_in_set_impl<SetT> not_contained_in_set(const SetT& s)
{
return not_contained_in_set_impl<SetT>(s);
}
Used as:
orders.erase(
std::remove_if(orders.begin(),
orders.end(),
not_contained_in_set(erase_if_not_found)),
orders.end());
[compiled in my head on the fly]
If you are willing to sort the range first, you have other options that may perform better (std::set_intersection, for example).
Yes, there is a better way - you can move the items that are to be removed at the end of the vector. Then just cut out the ending of the vector after the loop ends.
I would suggest to copy elements you want to keep in another vector instead of parsing again the vector from the beginning after each removal.
Also, you should store the iterator returned by end() method outside the loop if the collections are not modified anymore in the loop as calling end() is costly for some STL implementations. Some compilers are optimizing that, but not always.
It may help to sort first the vector, as the set is itself ordered.
A variant could be to order the vector by existance in the set, then chop all items at once.
I'm not sure if what you ask for is the intersection of two vectors, but if so, you might take a look at std::set_intersection.
It requires sorted vectors though.
The algorithm remove_if() will do this but you need a predicate to determine if the item is not in your set.
You can also use remove_copy_if() to copy your items into a new vector.
If your vector is sorted you can use set_intersection. That would also only allow one copy of each found element.