explicit list(
const A& Al = A( )
);
explicit list(
size_type n,
const T& v = T( ),
const A& Al = A( )
);
list(
const list& x
);
list(
const_iterator First,
const_iterator Last,
const A& Al = A( )
);
#include <list>
using namespace std;
list<Node> my_list;
int index = 0;
for ( list<Node>::iterator cursor = my_list.begin();
it!= my_list.end(); ++ cursor, ++ index ) {
cout << "index: " << index << “ value: “ << cursor->data() << endl;
}
At least based on what you have here, the problem isn't with how you traverse the list -- it's with using a list at all. You're asking for random access to the data, which means you should probably be using something like a vector or a deque instead of a list.
I really can't tell what this is trying to do, but you have a possible segfault in your inner loop:
for ( cursor = head_ptr; cursor !=NULL ||count<i; cursor=cursor->link() )
{
count++;
}
Your termination condition indicates that if count < i, you would keep looping even if cursor == NULL; when cursor=cursor->link() executes, you would try to dereference NULL.
Perhaps you meant cursor !=NULL && count<i ?
Related
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 ¤t : 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 ¤t : first )
{
std::cout << current << ' ';
}
std::cout << '\n';
for ( const auto ¤t : second )
{
std::cout << current << ' ';
}
std::cout << '\n';
std::cout << '\n';
second.reverse();
for ( const auto ¤t : first )
{
std::cout << current << ' ';
}
std::cout << '\n';
for ( const auto ¤t : second )
{
std::cout << current << ' ';
}
std::cout << '\n';
std::cout << '\n';
merge( first, second );
for ( const auto ¤t : first )
{
std::cout << current << ' ';
}
std::cout << '\n';
for ( const auto ¤t : 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.
I have used a nested for-loop to carry out insertion sort on a C++ STL <vector>. The first for-loop is over an iterator and the second one, over a reverse_itr.
I need to pass the index (iterator pointer value) from the first loop to the second. I have tried the following approach but it gives me this error
error: no match for ‘operator!=’ (operand types are
‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’ and
‘std::vector<int>::reverse_iterator’ {aka
‘std::reverse_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >’})
void insertionSort(int size, vector<int> arr) {
for(auto itr = arr.begin(); itr != arr.end() - 1; ++itr) {
int element = *(itr + 1);
cout << "Element being compared with preceding sub-array is : " << element << endl;
for(auto r_itr = (itr + 1); r_itr != arr.rend(); ++r_itr) {
if(*(r_itr+1) <= element) {
*r_itr = element;
break;
}
else {
*r_itr = *(r_itr+1);
}
}
}
}
I searched up quite a lot online, found a way to convert a reverse iterator to an iterator (using itr.base()) but not the other way round.
Also I am new to C++ STL and algorithms, please feel free to suggest any way to improve my code with respect to the "clean"-ness of code or the algorithm itself!
The class template std::vector has random access iterators. So there is no any need to convert a given "forward" iterator to a "reverse" iterator.
Just use with iterators the operator -- instead of the operator ++ or vice versa where it is required.
Pay attention to that the parameter size is not used in your function declared like
void insertionSort(int size, vector<int> arr);
If you want to sort a range from a vector then use two parameters declared as iterators that specify a range.
For example
void insertionSort( std::vector<int>::iterator first, std::vector<int>::iterator last );
Or you can write a more general function for vectors of any types using templates.
Here is a demonstrative program.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include <ctime>
void insertionSort( std::vector<int>::iterator first, std::vector<int>::iterator last )
{
if ( first != last )
{
for ( auto current = first; ++current != last; )
{
typename std::iterator_traits<decltype( current )>::value_type
value( *current );
auto prev = current, next = current;
while ( next != first && value < *--prev )
{
*next-- = *prev;
}
if ( next != current ) *next = value;
}
}
}
int main()
{
std::vector<int> v;
const int N = 10;
std::srand( ( unsigned int )std::time( nullptr ) );
std::generate_n( std::back_inserter( v ), N, [=]{ return std::rand() % N; } );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
insertionSort( std::begin( v ), std::end( v ) );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
return 0;
}
Its output might look like
0 6 6 7 4 3 4 6 6 1
0 1 3 4 4 6 6 6 6 7
Try changing it to for(vector<int>::reverse_iterator r_itr(next(itr)); r_itr != arr.rend(); ++r_itr)
To expand on their working, reverse_iterator is not implemented the same as iterator. The logical and physical address for an iterator are the same but for reverse_iterator, the logical and physical address are not the same. For example: s.end() and s.rbegin() have the same physical address but *s.end() will give you an error but *s.rbegin() will give you the last value of the container s.
The code below will make things clear:
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> S{ 1, 2, 3 };
set<int>::iterator itr = S.find(2);
cout << *itr << endl;
set<int>::reverse_iterator r_itr(itr);
cout << *r_itr << endl;
cout << itr._Ptr << ' ' << r_itr.base()._Ptr << endl;
//S.erase(r_itr); // ERROR!
S.erase(r_itr.base());
for (int e : S)
cout << e << ' ';
}
On my machine, it produced the following output:
2
1
00F85DA8 00F85DA8
1 3
#include <iostream>
#include <list>
#include <deque>
int main( void )
{
std::deque< std::deque< int > > integers_lists ;
const std::list< int > list0 { 1 , 2 , 3 } ;
for ( auto current = std::next( list0.cbegin() )
; current != std::next( list0.cend() )
; ++ current ) integers_lists.emplace_back( list0.cbegin() , current ) ;
for ( const auto& sub : integers_lists )
{
for ( auto each : sub ) std::cout << each << " " ;
std::cout << "\n" ;
}
return 0;
}
does STL guarantee the correctness of current != std::next( list0.cend() ) expression in this case.?
and where exactly that's pointed in Standard.?
std::next( list0.end() ) is invalid in almost any context.
Even if you simplified your program to this:
int main() {
std::list<int> list0 { 1 , 2 , 3 } ;
auto iter = std::next(list0.end());
}
it would be invalid. You can compare against an .end() iterator, but you cannot dereference it and nor can you iterate past it via std::next. It's undefined behaviour.
If you want to use each item in the list once, simply do:
for(auto & reference_to_current : list0) {
/* ... */
}
or, if you insist on using iterators,
for(auto current = list0.begin()
; current != list0.end()
; ++ current)
{ /* ... */ }
And yes, that will include every item, including the last item. The .end() iterator is special - it doesn't point to the last item, it points to the next slot just after the last item. "one-past-the-end".
Finally, next(list0.begin()) skips the first item. Are you sure you want to skip the first item?
Update: if you do want to skip the first item, but use all other items, you can use
if(list0.empty()) {
/* Error, list must not be empty */
} else {
for(auto current = std::next(list0.begin()) // skip first item
; current != list0.end()
; ++ current)
{ /* ... */ }
}
The if is very important, because we must not call std::next(list0.begin()) if the list is empty.
Is it possible to access the std::for_each iterator, so I can erase the current element from an std::list using a lambda (as below)
typedef std::shared_ptr<IEvent> EventPtr;
std::list<EventPtr> EventQueue;
EventType evt;
...
std::for_each(
EventQueue.begin(), EventQueue.end(),
[&]( EventPtr pEvent )
{
if( pEvent->EventType() == evt.EventType() )
EventQueue.erase( ???Iterator??? );
}
);
I've read about using [](typename T::value_type x){ delete x; } here on SO, but VS2010 doesn't seem to like this statement (underlines T as error source).
You are using the wrong algorithm. Use remove_if:
EventQueue.remove_if([&](EventPtr const& pEvent)
{
return pEvent->EventType() == evt.EventType();
});
The STL algorithms do not give you access to the iterator being used for iteration. This is in most cases a good thing.
(In addition, consider whether you really want to use std::list; it's unlikely that it is the right container for your use case. Consider std::vector, with which you would use the erase/remove idiom to remove elements that satisfy a particular predicate.)
no, use a regular for instead.
for( auto it = EventQueue.begin(); it != EventQueue.end(); ++it )
{
auto pEvent = *it;
if( pEvent->EventType() == evt.EventType() )
it = EventQueue.erase( it );
);
Erase is not the only time you may need to know iterator from lambda.
To do this in a more general way, I am using & operator (implicit conversion to iterator) like this :
int main (int argc, char* argv []) {
size_t tmp [6] = {0, 1, 2, 3, 4, 5};
std::list<size_t> ls ((size_t*)tmp, (size_t*) &tmp [6]);
//printing next element
std::for_each ((const size_t*)tmp, (const size_t*) &tmp [5], [] (const size_t& s) {
std::cout << s << "->";
std::cout << *(&s +1) << " ";
});
std::cout << std::endl;
}
I need to control the amount to touch points in my application, for this I am using a vector container and my basic setup is this:
//--------------------------------------------------------------
void testApp::touchDown(ofTouchEventArgs &touch){
isTouching = true;
touchPoints.push_back( ofVec2f( touch.x, touch.y ) );
}
//--------------------------------------------------------------
void testApp::touchMoved(ofTouchEventArgs &touch){
for ( int i = 0; i < touchPoints.size(); i++ ) {
if ( touch.id == i ) {
touchPoints[i] = ofVec2f( touch.x, touch.y );
}
}
}
//--------------------------------------------------------------
void testApp::touchUp(ofTouchEventArgs &touch){
isTouching = false;
int i = 0;
for ( vector<ofVec2f>::iterator iter = touchPoints.begin(); iter != touchPoints.end(); ) {
//int i = std::distance( touchPoints.begin(), iter );
cout << "i: " << i << endl;
if ( touch.id == i ) {
iter = touchPoints.erase( iter );
}
i++;
++iter;
}
}
But when I move up a finger the app freezes, so there most be something wrong in the touchUp(), any ideas?
Many things: First off, you cannot modify (erase/insert) a container and expect iterators to remain valid!
Let's see. I want to modify touchMove as well:
void testApp::touchMoved(const ofTouchEventArgs & touch)
{
if (touch.id < touchPoints.size())
touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
}
Next, the big one:
void testApp::touchUp(const ofTouchEventArgs & touch)
{
if (touch.id < touchPoints.size())
touchPoints.erase(touchPoints.begin() + touch.id);
}
Basically touch.id is just the index in the vector, so we can use that directly. To erase an element from the middle, we just call erase on the corresponding iterator. Since vector has random access iterators, we can say begin() + touch.id in constant time.
Update: Actually I think your code is broken: After you erase an element from the vector, the other elements move up, so you will lose the association between touch.id and the container element! What's needed is, you guessed it, an associative container:
struct testApp
{
std::map<int, ofVec2f> touchPoints;
bool isTouching;
void touchDown(const ofTouchEventArgs & touch)
{
isTouching = true;
touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
}
void touchMoved(const ofTouchEventArgs & touch)
{
touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
}
void touchUp(const ofTouchEventArgs & touch)
{
isTouching = false;
touchPoints.erase(touch.id);
}
};
If you've done iter=touchPoints.erase(iter) you shouldn't then do ++iter; you've already moved on to the next item.