C++ list in list - c++

I have two lists
list<int> s;
list<std::list<int>> q;
and I did the following assignment
q.push_front(s);
How can I display the contents of q since this
for (q_iterator = q.begin(); q_iterator != q.end(); ++q_iterator)
for (s_iterator = q_iterator.begin(); s_iterator != q_iterator.end(); ++s_iterator)
cout << *s_iterator;
gives me an error?

You have to write the following way
for (q_iterator = q.begin(); q_iterator != q.end(); ++q_iterator)
for (s_iterator = q_iterator->begin(); s_iterator != q_iterator->end(); ++s_iterator)
cout << *s_iterator;
or the following way
for (q_iterator = q.begin(); q_iterator != q.end(); ++q_iterator)
for (s_iterator = ( *q_iterator ).begin(); s_iterator != ( *q_iterator ).end(); ++s_iterator)
cout << *s_iterator;
provided that q_iterator and s_iterator are already declared. Otherwise you could write for example
for ( auto q_iterator = q.begin; /*...*/ )
Also you can use the range based for statement. For example
for ( const auto &s : q )
{
for ( int x : s ) std::cout << x << ' ';
std::cout << std::endl;
}

You probably know it, but I just want to make sure you remember about a space between angle braces.
std::list<std::list<int> >

Related

How to read data from a Vector

How can I use the following vector to read true/false from using a while or for loop.
With this implemtation of the loop I get an error for the oprator !=
no operator "!=" matches these operands
vector<bool> Verification;
Verification.push_back(true);
Verification.push_back(false);
Verification.push_back(true);
Verification.push_back(false);
Verification.push_back(true);
for (int it = Verification.begin(); it != Verification.end(); it++) {
if (it==true) cout<<"true";
else if (it == false) cout<<"false";
}
You are declaring it as the wrong type. The result of Verification.begin() is a std::vector<bool>::iterator. But you don't need to specify that.
Use a range-for loop instead
for (bool b : Verification)
{
std::cout << std::boolalpha << b;
}
There are various ways to iterate over an std::vector
Using iterator
Long example:
for( std::vector<bool>::iterator it = v.begin(); it != v.end(); ++it ) std::cout << *it;
or the same but shorter:
for( auto it = v.begin(); it != v.end(); ++it ) std::cout << *it;
Using index
Here:
for( unsigned int i = 0; i != v.size(); ++i ) std::cout << v[i];
Range loop
Here:
for( bool b : v ) std::cout << b;
(there are some more but we will omit them for clarity)
Looks like you mixed 1 and 2 hense you have compilation errors. Choose one.
The problem is that Verification.begin() gives you an iterator while it is an int.
To solve this you could modify your for loop to:
for (std::vector<bool>::iterator it = Verification.begin(); it != Verification.end(); it++) {
if (*it==true) cout<<"true";
else if (*it == false) cout<<"false";
}
Note *it means we're dereferencing the iterator it and then comparing the result.
Also you don't need the else if because you can just use else.
Alternative solution
You can also use a range-base for loop as shown below:
for (bool element : Verification)
{
std::cout << std::boolalpha << element;
}

C++ linked List nodes not changing

I am trying to reorder Linked List such that given linked list (Head),
L0 → L1 → … → Ln - 1 → Ln
changes to,
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
void reorderList(ListNode* head) {
ListNode* h=head;
map<int,ListNode*> allNodes;
int count=0;
while(h!=nullptr){
ListNode* temp=new ListNode(h->val);
allNodes[count]=temp;
count++;
h=h->next;
}
auto rItr=allNodes.rbegin();
auto itr=allNodes.begin();
head=nullptr;// tried with and without this line same result
while(itr->first!=rItr->first){
head=itr->second;
head=head->next;
head=rItr->second;
itr++;
rItr++;
head=head->next;
}
head=itr->second;
}
I am creating new nodes and storing them in the map, Why is the Linked List not getting updated?
Input [1,2,3,4,5]
Expected output:
[1,5,2,4,3]
Actual Output
[1,2,3,4,5]
That is no change
To make the assignment there is no need to allocate new nodes. Moreover it is inefficient and requires additional memory.
Pay attention to that within your function you are changing the pointer to the head node but the original pointer to the head node is passed to the function by value. That is the function deals with a copy of the value of the original pointer to the head node. Changing the copy does not influence on the value stored in the original pointer to the head node.
As an idea I can suggest the following approach to the assignment.
First, find the middle of the list. Using the middle split the list
into two lists.
Second, reverse the second list.
Third, combine the two lists in one list.
Here is a demonstrative program that shows the approach using the standard container std::forward_list that represents a singly-linked list (it is not a production code.:)).
#include <iostream>
#include <forward_list>
#include <iterator>
template <typename T>
typename std::forward_list<T>::const_iterator
find_middle( const std::forward_list<T> &list )
{
auto middle = std::begin( list );
for ( auto last = std::begin( list );
last != std::end( list ) && ( std::advance( last, 1 ), last != std::end( list ) );
std::advance( last, 1 ) )
{
std::advance( middle, 1 );
}
return middle;
}
template <typename T>
void merge( std::forward_list<T> &first, std::forward_list<T> &second )
{
for ( auto position = std::begin( first );
position != std::end( first ) && !second.empty(); )
{
position = first.insert_after( position, second.front() );
std::advance( position, 1 );
second.erase_after( second.before_begin() );
}
if ( !second.empty() )
{
first.insert_after( std::end( first ), std::begin( second ), std::end( second ) );
second.clear();
}
}
int main()
{
std::forward_list<int> first = { 1, 2, 3, 4, 5 };
for ( const auto &current : first )
{
std::cout << current << ' ';
}
std::cout << '\n';
std::cout << '\n';
auto middle = find_middle( first );
if ( middle != std::begin( first ) )
{
std::forward_list<int> second;
second.splice_after( second.before_begin(), first, middle, std::cend( first ) );
for ( const auto &current : first )
{
std::cout << current << ' ';
}
std::cout << '\n';
for ( const auto &current : second )
{
std::cout << current << ' ';
}
std::cout << '\n';
std::cout << '\n';
second.reverse();
for ( const auto &current : first )
{
std::cout << current << ' ';
}
std::cout << '\n';
for ( const auto &current : second )
{
std::cout << current << ' ';
}
std::cout << '\n';
std::cout << '\n';
merge( first, second );
for ( const auto &current : first )
{
std::cout << current << ' ';
}
std::cout << '\n';
for ( const auto &current : second )
{
std::cout << current << ' ';
}
std::cout << '\n';
}
return 0;
}
The program output is
1 2 3 4 5
1 2 3
4 5
1 2 3
5 4
1 5 2 4 3
So what you need is to write a function that finds the middle node (similar to the function find_middle shown in the demonstrative program). Then to write a function that splits a list based on the middle node into two lists. Then to write a function that reverses a singly-linked list. And then it will be easy to write a function that combines two list in one list.

Map of Map data struct confusion

I am trying to setup a map of map structure in C++ but can't make it work as expected. I put together this sample program to illustrate the issue. Please excuse the mess if it seems convoluted but I want to preserve the case as much as I can.
So the current print out is: L1, size = 0
and what I was expecting is something like:
L1, size 1
L2, 4
It seems like the second level map is not established properly, maybe a scoping issue, but I can't quite figure it out. The program is as the following:
// So the map is
// AKEY -> { BKEY -> [ SegPair, SegPair .... ] }
#include <map>
#include <utility>
#include <iostream>
#include <vector>
typedef std::string AKEY;
typedef std::string BKEY;
typedef std::pair<int,int> SegPair;
typedef std::vector<SegPair> SegVec;
typedef std::map<BKEY, SegVec> Ensemble;
typedef std::map<AKEY, Ensemble> Oracle;
using std::string;
Oracle o = Oracle();
void setup(string akey, string bkey, int x, int y) {
auto pos = o.find(akey);
if (pos == o.end()) {
o[akey] = Ensemble();
}
Ensemble e = o[akey];
auto pos2 = e.find(bkey);
if (pos2 == e.end()) {
e[bkey] = SegVec();
}
SegPair p(x, y);
e[bkey].push_back(p);
}
int main(void) {
setup("L1", "L2", 3, 4);
for (auto it = o.begin(); it != o.end(); it++) {
std::cout << it->first;
Ensemble e = it->second;
std::cout << ", size = " << e.size() << "\n";
for (auto it2 = e.begin(); it2 != e.end(); it2++) {
std::cout << "\t" << it2-> first << "\n";
SegVec v = it2->second;
for (int i = 0; i < v.size(); i++)
std::cout<< v[i].second << " ";
}
}
}
I think your problem is with this line:
Ensemble e = o[akey];
You're creating a local, rather than capturing the lvalue in the map by reference, for mutation. Thus, any changes you make to e after that point will simply be discarded when e goes out of scope.
In setup, e is a copy of the object in o.
When you modify it, you're not modifying anything in o.
To fix, use a reference:
Ensemble& e = o[akey];
That will make e refer to the same thing as o[akey] instead of a copy.

Why does my std::set find() not work?

I have the following function and cannot figure out why it is not working.
Parameters are a set of Nonterminals and a vector of GrammarSymbol* (a word). Nonterminal is a subclass of GrammarSymbol. The function is supposed to filter all Nonterminals that are contained in the word as well as in the Nonterminal set and return them in a set.
std::set<Nonterminal> Filter(const std::set<Nonterminal>& symbolSet, const std::vector<GrammarSymbol*> w){
//resulting set
std::set<Nonterminal> rSet;
std::vector<GrammarSymbol*>::const_iterator wit;
std::set<Nonterminal>::const_iterator ntit;
//iterate over all symbols of the word
for(wit = w.begin(); wit != w.end(); wit++){
//test if current symbol is a nonterminal
const Nonterminal* nt = dynamic_cast<const Nonterminal*>(*wit);
if(nt != NULL){
std::cout << "current symbol " << nt->Str() << " is nonterminal" << std::endl;
for(ntit = symbolSet.begin(); ntit != symbolSet.end(); ntit++){
std::cout << ntit->Str() << " " << (!(*ntit < *nt) && !(*nt < *ntit))<< std::endl;
}
//look for the symbol in the nonterminal set
ntit = symbolSet.find(*nt);
//if the symbol was found, insert it into resulting set
if(ntit != symbolSet.end()){
rSet.insert(*ntit);
std::cout << "inserted " << ntit->Str() << "into set, size: " << rSet.size() << std::endl;
}
else{
std::cout << "not found in symbolSet" << std::endl;
}
}
}
return rSet;
}
This yields the output
current symbol (1, 2, 2) is nonterminal
(1, 2, 2) 1
(2, 3, 3) 0
(3, 2) 0
(4, 3) 0
(5, 3, 1) 0
not found in symbolSet
It works just fine if I don't rely on the filter function and filter on my own:
std::set<Nonterminal> Filter(const std::set<Nonterminal>& symbolSet, const std::vector<GrammarSymbol*> w){
//resulting set
std::set<Nonterminal> rSet;
std::vector<GrammarSymbol*>::const_iterator wit;
std::set<Nonterminal>::const_iterator ntit;
//iterate over all symbols of the word
for(wit = w.begin(); wit != w.end(); wit++){
//test if current symbol is a nonterminal
const Nonterminal* nt = dynamic_cast<const Nonterminal*>(*wit);
if(nt != NULL){
std::cout << "current symbol " << nt->Str() << " is nonterminal" << std::endl;
for(ntit = symbolSet.begin(); ntit != symbolSet.end(); ntit++){
std::cout << ntit->Str() << " " << (!(*ntit < *nt) && !(*nt < *ntit))<< std::endl;
if(!(*ntit < *nt) && !(*nt < *ntit)){
rSet.insert(*ntit);
}
}
}
}
return rSet;
}
Can anyone explain to me what happens here? As far as I know, std::set is supposed to compare elements with the operator<. Comparing seems to work just fine, as shown by the output.
I would just continue with the selfmade filter, but I fear there is a bigger underlying problem.
Thanks!
Edit: Nonterminal and operator< for Nonterminal:
class Nonterminal : public GrammarSymbol{
public:
/** The start state*/
Idx mStartState;
/** The stack symbol*/
Idx mOnStack;
/** The end state */
Idx mEndState;
//...
}
Idx is just a typedef for an int.
bool Nonterminal::operator<(const GrammarSymbol& other) const{
if(typeid(*this) != typeid(other)) return true; //other is a terminal
const Nonterminal& nt = dynamic_cast<const Nonterminal&>(other); //other is a nonterminal
if (mStartState < nt.StartState()) return true;
if (mOnStack < nt.OnStack()) return true;
if (mEndState < nt.EndState()) return true;
return false;
}
You operator < is incorrect
Consider
Nonterminal nt1 (1,2,3);
Nonterminal nt2 (3,2,1);
bool b1 = nt1 < nt2;
bool b2 = nt2 < nt1;
For nt1 < nt2 comparison:
1 < 3 immediatelly yelds true;
For nt2 < nt1:
3 < 1 doesn't hold, so you proceed to
2 < 2 which doesn't hold, so you proceed to
1 < 3 which holds
Thus both b1 and b2 will be true, which is nonsense
As for your second variant of filter, it works becase of logic error
for(ntit = symbolSet.begin(); ntit != symbolSet.end(); ntit++){
std::cout << ntit->Str() << " " << (!(*ntit < *nt) && !(*nt < *ntit))<< std::endl;
if(!(*ntit < *nt) && !(*nt < *ntit)){
rSet.insert(*ntit);
}
here rSet.insert(*ntit); will be called every time if(!(*ntit < *nt) && !(*nt < *ntit)) doesn't hold, not once as it should.

How do you determine the last valid element in a STL-Container

If i iterate over a STL container i sometimes need to know if the current item is the last one in the sequence. Is there a better way, then doing something like this? Can i somehow convert rbegin()?
std::vector<int> myList;
// ....
std::vector<int>::iterator lastit = myList.end();
lastit--;
for(std::vector<int>::iterator it = myList.begin(); it != myList.end(); it++) {
if(it == lastit)
{
// Do something with last element
}
else
{
// Do something with all other elements
}
Try the following
std::vector<int>::iterator it2 = (++it);
if ( it2 == myList.end() ) {
...
}
The following should work as well
if ( it+1 == myList.end() ) {
// it is last
...
}
Maybe you can iterate backwards (use rbegin/rend) and put your special task before the loop or replace the end check with it != lastit and put the special handling after the loop
I would have some doubts about my design if some elements need to be treated differntly, but this suggestion is a bit cleaner for me (don't forget to test for empty containers)
std::vector<int>::iterator lastit = myList.end();
if (lastit != myList.begin())
{
lastit--;
for(std::vector<int>::iterator it = myList.begin(); it != lastit; ++it)
{
// Do
}
// Do with last
}
Use reversed iteration, this way you will have only one end()-1-like computation (notice the rbegin()+1) and no comparsions:
for(vector<int>::iterator it = myValues.rbegin()+1; it != myValues.rend(); it++) {
cout << *it << endl;
}
cout << "Process last one: " << *myValues.rbegin() << endl;
Also, for the vector<>, computing end()-1 is probably fast, so you can also do it like following:
for(vector<int>::iterator it = myValues.begin(); it != myValues.end()-1; it++) {
cout << *it << endl;
}
cout << "Process last one: " << *myValues.rbegin() << endl;
If you don't want to process the element after the loop, you can:
for(vector<int>::iterator it = myValues.rbegin(); it != myValues.rend(); it++) {
if(it == myValues.rbegin())
cout << "Process last one: " << *it << endl;
else
cout << *it << endl;
}
For a random access iterator like that for vector, you don't need the temporarary. You can say:
if ( it + 1 == v.end() ) {
// at one before end
}
Edit: And even for non-random access types one could use std:;distance:
if ( distance( it, v.end() ) == 1 ) {
// at one before end
}
An important question is: why create a loop if you do something special for 1 element. Why not do something special to the 3rd element? To every 4rth? ...
Just iterate over the elements to be treated the same, write separate code to treat the others.
Have a look at answers to this question, too.
Why not:
if(!myList.empty())
last_it = myList.begin() + myList.size()-1;
else
last_it = myList.end();
//or
last_it = myList.empty() ? myList.end() : myList.begin() + myList.size() - 1;
If you're using a vector, it's actually much simpler to use an integer index to iterate:
std::vector<int> myList;
for (unsigned int i = 0; i < myList.size(); i++)
{
if (i == (myList.size() - 1))
{
processDifferently (myList[i])
}
else
{
process (myList[i])
}
}
Minimizing the number of calls to myList.size() is left as an exercise for the OP :)