Insertion sort implementation using iterators and vectors - c++

I'm trying to implement insertion sort algorithm using iterators and it doesn't seem to work as I thought... Do you have any ideas of how to implement it?
Also, I can't use code like this one: https://www.geeksforgeeks.org/insertion-sort-using-c-stl/ because I'm intending to make an animation and it will get more complicated.
This is my source code so far:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> seq = { 5, 4, 3, 2, 1 };
std::vector<int>::iterator itj;
std::vector<int>::iterator leftmost;
// insertion sort
for (std::vector<int>::iterator iti = seq.begin() + 1; iti != seq.end(); iti = std::next(iti))
{
itj = std::prev(iti);
leftmost = iti;
while (std::distance(seq.begin(), itj) >= 0 && *itj > *leftmost)
{
std::next(itj) = itj;
itj = prev(itj);
}
std::next(itj) = leftmost;
}
// printing
for (std::vector<int>::iterator iti = seq.begin(); iti != seq.end(); iti = std::next(iti))
{
std::cout << *iti << " ";
}
}

Here's a very elegant implementation of insertion sort using iterators lifted directly from the reference page on rotate:
// insertion sort
for (auto i = v.begin(); i != v.end(); ++i) {
std::rotate(std::upper_bound(v.begin(), i, *i), i, i+1);
}
All you have to do is understand how std::rotate works, and this becomes easy to understand. (rotate is anyway a really powerful algorithm that you should be comfortable with).

Here is an implementation taken from SGI STL1:
template<class Random_it, class T>
void unguarded_linear_insert(Random_it last, T val) {
auto next = last;
--next;
while (val < *next) {
*last = *next;
last = next;
--next;
}
*last = val;
}
template<class Random_it>
void linear_insert(Random_it first, Random_it last) {
auto val = *last;
if (val < *first) {
std::copy_backward(first, last, last + 1);
*first = val;
}
else
unguarded_linear_insert(last, val);
}
template<class Random_it>
void insertion_sort(Random_it first, Random_it last) {
if (first == last)
return;
for (auto i = first + 1; i != last; ++i)
linear_insert(first, i);
}
Note how the val < *first condition and std::copy_backward are used to simplify the loop inside unguarded_linear_insert: only one condition, namely val < *next can be checked in that loop.
1 The same implementation can be found in libstdc++.

Related

Iterator for all combinations of 2 ranges

Is it possible to use the boost::iterators library to create iterators that show the combined results of 2 ranges? Note that for usage, we need the output to be iterators. Nor do we expect to first manually create a vector of all combinations. (Note: We compile with C++17)
A contrived example:
auto v = std::vector<int>({1,2,3});
auto s = std::set<double>({0.5, 1.5});
auto range = combineElements(v.begin(), v.end(), s.begin(), s.end(), [](int i, double d){ return std::pair{i, d}; });
for (auto [i, d] : range)
std::cout << std::to_string(i) << ',' <<std::to_string(d) << ";";
// Expected output: 1,0.5;1,1.5;2,0.5;2,1.5;3,0.5;3,1.5;
I've checked the documentation of boost::iterators and found:
Zip: This combined the nth element of the first range, with the nth of the second. However, doesn't combine nth with mth element.
Generator: The generator that needs to be provided could do manual bookkeeping keeping 6 iterators: begin, end, and current for both ranges. However, it doesn't have a way to stop it.
Function input: Similar to Generator, we could put those iterators in the state and create an end-state for the end-iterator using the end-iterators. However, the state ain't provided to the generator to calculate the value of the iterator.
Permutation: Works on a single range
Transform: Works on a single range
Am I correct to conclude that in this situation the only option is to write customer iterator by hand?
Am I correct to conclude that in this situation the only option is to write customer iterator by hand?
Pretty much yes. You might want to decompose it into an iterator adaptor that repeats each element N times, and one that repeats the whole range M times, which would allow you to zip the pair of those.
template <class Iterator>
class repeat_iterator
: public boost::iterator::iterator_adaptor< repeat_iterator<Iterator>, Iterator >
{
typedef boost::iterator::iterator_adaptor< repeat_iterator<Iterator>, Iterator > super_t;
friend class boost::iterator::iterator_core_access;
size_t len = 1;
size_t curr = 0;
public:
repeat_iterator() {}
explicit repeat_iterator(Iterator x, size_t len, curr = 0)
: super_t(x), len(len), curr(curr) {}
private:
void increment() {
if (++curr == len) {
curr = 0;
++base_reference();
}
}
void decrement() {
if (curr-- == 0) {
curr = len - 1;
--base_reference();
}
}
void advance(typename super_t::difference_type n)
{
n += curr;
base_reference() += n / len;
curr = n % len;
}
template <class OtherIterator>
typename super_t::difference_type
distance_to(unstride_iterator<OtherIterator> const& y) const
{
return ((base() - y.base()) * len) + (curr - y.curr);
}
};
template <class Iterator>
class cycle_iterator
: public boost::iterator::iterator_adaptor< cycle_iterator<Iterator>, Iterator >
{
typedef boost::iterator::iterator_adaptor< cycle_iterator<Iterator>, Iterator > super_t;
friend class boost::iterator::iterator_core_access;
Iterator first;
Iterator last;
public:
cycle_iterator() {}
explicit cycle_iterator(Iterator first, Iterator last)
: super_t(first), first(first), last(last) {}
private:
void increment() {
if (++base_reference() == last) {
base_reference() = first;
}
}
void decrement() {
if (base_reference() == first) {
base_reference() = last - 1;
}
}
void advance(typename super_t::difference_type n)
{
n += std::distance(first, base_reference());
n %= std::distance(first, last);
base_reference() = first + n;
}
};

Iterating over a container bidirectionally

Is there a better way than the below code, to iterate over a container in either direction, using the same iterators?
#include <iostream>
#include <map>
int main()
{
const bool descend = false;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
std::map<int, int>::iterator startIter = descend ? --(mapp.end()) : mapp.begin();
std::map<int, int>::iterator endIter = descend ? --(mapp.begin()) : mapp.end();
while (startIter != endIter)
{
std::cout << startIter->first << std::endl;
descend ? --startIter : ++startIter;
}
}
Your code is invalid as this statement --(mapp.begin()) leads to UB. I would write a thin wrapper:
template<class Iter, class F>
void apply( Iter begin, Iter end, F f, bool forward )
{
while( begin != end )
f( forward ? *begin++ : *--end );
}
live example
or just simply rewrite your loop into:
auto begin = mapp.begin();
auto end = mapp.end();
while ( begin != end)
{
const auto &p = forward ? *begin++ : *--end;
std::cout << p.first << std::endl;
}
Is there a better way than the below code, to iterate over a container
in either direction, using the same iterators?
Yes. Use std::map::reverse_iterator. It will be a better way than the code you posted, but that will not be using the same iterators anymore, which was one of your requirements.
However, this will be less error-prone than the code you have written. In addition to that, you do not need to re-invent the wheel, if that is already in C++.
See output here
#include <iostream>
#include <map>
template<typename Iterator>
void print(const Iterator Begin, const Iterator End)
{
for(Iterator iter = Begin; iter != End; ++iter)
std::cout << iter->first << "\n";
}
int main()
{
const bool descend = true;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
descend ?
print(mapp.crbegin(), mapp.crend()):
print(mapp.cbegin(), mapp.cend());
return 0;
}
The image from cppreference.com will explain graphically, how does it work.
Write self-documenting code and it becomes simple. Break that loop out into its own function and call it with the appropriate iterators.
This is why we have "reverse iterators" they can be used to go backwards through a container by using the normal forward semantics.
#include <iostream>
#include <map>
template<typename I>
void printMapContainer(I begin, I end)
{
for (;begin != end; ++begin)
{
std::cout << begin->first << "\n";
}
}
int main()
{
const bool descend = false;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
if (descend) {
printMapContainer(mapp.rbegin(), mapp.rend());
}
else {
printMapContainer(mapp.begin(), mapp.end());
}
}

Implementing selection sort on a singly linked list

Heya I'm trying to implement selection sort algorithm on a singly linked list , I'm aware that there is some problem in the code but although My linked list includes the numbers 7 1 2 6 the output after running is 7777 . Any help would be appreciated.
template<class Type>
void UnOrderedLinkedList<Type>::selectionSort()
{
nodeType<Type>* loc;
nodeType<Type>* minIndex;
nodeType<Type>* temp;
temp = first;
if(temp == NULL)
cerr<<"Cannot sort an empty list."<<endl;
else
if(temp->link == NULL)
cerr<<"List has only one item so it is already sorted."<<endl;
else
while(temp != NULL)
{
minIndex = minLocation(temp, last);
swap(temp, minIndex);
temp = temp->link;
}
}
template<class Type>
nodeType<Type>* UnOrderedLinkedList<Type>::minLocation(nodeType<Type>* first, nodeType<Type>* last)
nodeType<Type>* minIndex;
nodeType<Type>* other;
minIndex = first;
other = minIndex->link;
while(other != NULL)
{
if(minIndex->info > other->info)
{
minIndex = other;
other = other->link;
}
else
{
other = other->link;
}
}
return minIndex;
}
Then to swap:
template<class Type>
void UnOrderedLinkedList<Type>::swap(nodeType<Type>* first, nodeType<Type>* second)
{
nodeType<Type>* temp;
temp->info = first->info;
first->info = second->info;
second->info = temp->info;
}
From your swap function:
nodeType<Type>* temp;
temp->info = first->info;
That is a clear case of undefined behavior! You declare a local variable, a pointer, without initialization. Then you directly uses the uninitialized variable, leading to said UB. Since you use pointers, you should actually be happy that the program didn't crash.
Here you don't need a pointer or a node as you don't actually swap nodes. All you need is an instance of what info is, and use that:
SomeType temp;
temp = first->info;
first->info = second->info;
second->info = temp;
The answer by #JoachimPileborg works of course, but note that you don't need to write a member function sort of your own singly linked list in order to do selection sort.
The reason is that a generic version of selection_sort (with O(N^2) complexity) is already compatible any singly linked list that exposes forward iterators, such as the one from the Standard Library, std::forward_list:
#include <algorithm> // min_element, iter_swap, is_sorted
#include <cassert> // assert
#include <forward_list> // forward_list
#include <functional> // less
#include <iostream> // cout
#include <ios> // boolalpha
#include <iterator> // distance, next
template<class FwdIt, class Compare = std::less<>>
void selection_sort(FwdIt first, FwdIt last, Compare cmp = Compare{})
{
for (auto it = first; it != last; ++it) {
auto const selection = std::min_element(it, last, cmp);
std::iter_swap(selection, it);
assert(std::is_sorted(first, std::next(it), cmp));
}
}
int main()
{
auto fl = std::forward_list<int> { 2, 4, 1, 0, -1, 8, 2 };
std::cout << std::boolalpha << std::is_sorted(fl.begin(), fl.end()) << '\n';
for (auto const& e : fl) std::cout << e << ", "; std::cout << '\n';
selection_sort(fl.begin(), fl.end());
std::cout << std::boolalpha << std::is_sorted(fl.begin(), fl.end()) << '\n';
for (auto const& e : fl) std::cout << e << ", "; std::cout << '\n';
}
Live Example
Note that std::forward_list also implements its own member function sort. This version -which does an O(N log N) merge sort- can not be implemented based on the public interface alone (actually you can, but with O(N) extra storage instead of the O(1) storage that forward_list guarantees).

How to keep track of current and previous iterator on a c++ vector?

I have one vector container and I would like to make a subtraction operation on the values of its content using the current iterator against the previous iterator, any help will be much appreciated
vector<MyClass>::iterator itPrevious = my_vec.begin();
vector<MyClass>::iterator itCurrent = itPrevious;
if (itCurrent != my_vec.end())
{
for (++itCurrent; itCurrent != my_vec.end(); ++itCurrent)
{
// do something with itPrevious and itCurrent
itPrevious = itCurrent;
}
}
std::vector's iterator is a RandomAccessIterator, so you can perform integer arithmetic on it. Thus, you don't need a separate "current" and "previous" pointer, as long as you start your iteration from begin() + 1:
vector<Foo> myVec = ...;
if(myVec.size() > 1) {
for(vector<Foo>::iterator iter = myVec.begin()+1; iter != myVec.end(); iter++) {
Foo current = *iter;
Foo previous = *(iter - 1);
Foo subtraction = current - previous;
...
}
}
Of course, you can't subtract the current and previous element if there are fewer than two elements in your vector. The size check might be redundant if you know your input vector will always have at least two elements, but I included it just to be safe.
Given you asked for a vector, you can use iterator arithmetic:
#include <vector>
#include <iostream>
int main() {
std::vector<int> v{ 1, 2, 3, 4 };
for ( auto i = v.begin(); i != v.end(); ++i ) {
if ( i != v.begin() )
*i = *i - *(i-1);
}
for ( auto i : v )
std::cout << i << std::endl;
}
if(v.size() < 2)
return;
auto curr = v.begin();
auto next = curr;
++next;
do
{
whatever(*next - *curr );
curr = next++;
} while( next != v.end() )
An alternative:
for (auto previous = v.begin(), current = previous + 1, end = v.end();
previous != end && current != end;
++previous, ++current)
{
std::cout << *current << " - " << *previous << " = " << *current - *previous << std::endl;
}
There are namely three more-or-less elegant ways to solve your problem.
Define a new functor
And use it in a for_each iteration
template<class T>
struct substractor {
substractor() : last(nullptr) {}
void operator()(T& item) const
{
if(last != nullptr)
*last -= item;
last = &item;
}
mutable T* last;
};
...
vector<int> v = {3, 2, 1};
for_each(v.begin(), v.end(), substractor<int>());
Define a new algorithm
Some kind of pair in-place transform here
template<typename It, typename Op>
void pair_transform(It begin, It end, Op op){
while(begin != end)
{
It next = std::next(begin);
if(next == end) break;
*begin = op(*begin, *next);
++begin;
}
}
...
vector<int> w = {3, 2, 1};
pair_transform(w.begin(), w.end(), std::minus<int>());
Keep it standard, use transform
IMHO the best one :) Concise, standard, nowhere else to look in order to understand this code.
vector<int> z = {3, 2, 1};
std::transform(z.begin(), z.end() - 1, z.begin() + 1, z.begin(),
std::minus<int>());

Iterating C++ vector from the end to the beginning

Is it possible to iterate a vector from the end to the beginning?
for (vector<my_class>::iterator i = my_vector.end();
i != my_vector.begin(); /* ?! */ ) {
}
Or is that only possible with something like that:
for (int i = my_vector.size() - 1; i >= 0; --i) {
}
One way is:
for (vector<my_class>::reverse_iterator i = my_vector.rbegin();
i != my_vector.rend(); ++i ) {
}
rbegin()/rend() were especially designed for that purpose. (And yes, incrementing a reverse_interator moves it backward.)
Now, in theory, your method (using begin()/end() & --i) would work, std::vector's iterator being bidirectional, but remember, end() isn't the last element — it's one beyond the last element, so you'd have to decrement first, and you are done when you reach begin() — but you still have to do your processing.
vector<my_class>::iterator i = my_vector.end();
while (i != my_vector.begin())
{
--i;
/*do stuff */
}
UPDATE: I was apparently too aggressive in re-writing the for() loop into a while() loop. (The important part is that the --i is at the beginning.)
If you have C++11 you can make use of auto.
for (auto it = my_vector.rbegin(); it != my_vector.rend(); ++it)
{
}
Starting with c++20, you can use a std::ranges::reverse_view and a range-based for-loop:
#include<ranges>
#include<vector>
#include<iostream>
using namespace std::ranges;
std::vector<int> const vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(auto& i : views::reverse(vec)) {
std::cout << i << ",";
}
Or even
for(auto& i : vec | views::reverse)
Unfortunately, at the time of writing (Jan 2020) no major compiler implements the ranges library, but you can resort to Eric Niebler's ranges-v3:
#include <iostream>
#include <vector>
#include "range/v3/all.hpp"
int main() {
using namespace ranges;
std::vector<int> const vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(auto& i : views::reverse(vec)) {
std::cout << i << ",";
}
return 0;
}
The well-established "pattern" for reverse-iterating through closed-open ranges looks as follows
// Iterate over [begin, end) range in reverse
for (iterator = end; iterator-- != begin; ) {
// Process `*iterator`
}
or, if you prefer,
// Iterate over [begin, end) range in reverse
for (iterator = end; iterator != begin; ) {
--iterator;
// Process `*iterator`
}
This pattern is useful, for example, for reverse-indexing an array using an unsigned index
int array[N];
...
// Iterate over [0, N) range in reverse
for (unsigned i = N; i-- != 0; ) {
array[i]; // <- process it
}
(People unfamiliar with this pattern often insist on using signed integer types for array indexing specifically because they incorrectly believe that unsigned types are somehow "unusable" for reverse indexing)
It can be used for iterating over an array using a "sliding pointer" technique
// Iterate over [array, array + N) range in reverse
for (int *p = array + N; p-- != array; ) {
*p; // <- process it
}
or it can be used for reverse-iteration over a vector using an ordinary (not reverse) iterator
for (vector<my_class>::iterator i = my_vector.end(); i-- != my_vector.begin(); ) {
*i; // <- process it
}
User rend() / rbegin() iterators:
for (vector<myclass>::reverse_iterator it = myvector.rbegin(); it != myvector.rend(); it++)
template<class It>
std::reverse_iterator<It> reversed( It it ) {
return std::reverse_iterator<It>(std::forward<It>(it));
}
Then:
for( auto rit = reversed(data.end()); rit != reversed(data.begin()); ++rit ) {
std::cout << *rit;
Alternatively in C++14 just do:
for( auto rit = std::rbegin(data); rit != std::rend(data); ++rit ) {
std::cout << *rit;
In C++03/11 most standard containers have a .rbegin() and .rend() method as well.
Finally, you can write the range adapter backwards as follows:
namespace adl_aux {
using std::begin; using std::end;
template<class C>
decltype( begin( std::declval<C>() ) ) adl_begin( C&& c ) {
return begin(std::forward<C>(c));
}
template<class C>
decltype( end( std::declval<C>() ) ) adl_end( C&& c ) {
return end(std::forward<C>(c));
}
}
template<class It>
struct simple_range {
It b_, e_;
simple_range():b_(),e_(){}
It begin() const { return b_; }
It end() const { return e_; }
simple_range( It b, It e ):b_(b), e_(e) {}
template<class OtherRange>
simple_range( OtherRange&& o ):
simple_range(adl_aux::adl_begin(o), adl_aux::adl_end(o))
{}
// explicit defaults:
simple_range( simple_range const& o ) = default;
simple_range( simple_range && o ) = default;
simple_range& operator=( simple_range const& o ) = default;
simple_range& operator=( simple_range && o ) = default;
};
template<class C>
simple_range< decltype( reversed( adl_aux::adl_begin( std::declval<C&>() ) ) ) >
backwards( C&& c ) {
return { reversed( adl_aux::adl_end(c) ), reversed( adl_aux::adl_begin(c) ) };
}
and now you can do this:
for (auto&& x : backwards(ctnr))
std::cout << x;
which I think is quite pretty.
Use reverse iterators and loop from rbegin() to rend()
I like the backwards iterator at the end of Yakk - Adam Nevraumont's answer, but it seemed complicated for what I needed, so I wrote this:
template <class T>
class backwards {
T& _obj;
public:
backwards(T &obj) : _obj(obj) {}
auto begin() {return _obj.rbegin();}
auto end() {return _obj.rend();}
};
I'm able to take a normal iterator like this:
for (auto &elem : vec) {
// ... my useful code
}
and change it to this to iterate in reverse:
for (auto &elem : backwards(vec)) {
// ... my useful code
}
If you can use The Boost Library, there is the Boost.Range that provides the reverse range adapter by including:
#include <boost/range/adaptor/reversed.hpp>
Then, in combination with a C++11's range-for loop, you can just write the following:
for (auto& elem: boost::adaptors::reverse(my_vector)) {
// ...
}
Since this code is briefer than the one using the iterator pair, it may be more readable and less prone to errors as there are fewer details to pay attention to.
Here's a super simple implementation that allows use of the for each construct and relies only on C++14 std library:
namespace Details {
// simple storage of a begin and end iterator
template<class T>
struct iterator_range
{
T beginning, ending;
iterator_range(T beginning, T ending) : beginning(beginning), ending(ending) {}
T begin() const { return beginning; }
T end() const { return ending; }
};
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usage:
// for (auto e : backwards(collection))
template<class T>
auto backwards(T & collection)
{
using namespace std;
return Details::iterator_range(rbegin(collection), rend(collection));
}
This works with things that supply an rbegin() and rend(), as well as with static arrays.
std::vector<int> collection{ 5, 9, 15, 22 };
for (auto e : backwards(collection))
;
long values[] = { 3, 6, 9, 12 };
for (auto e : backwards(values))
;
can try this one (only for --i):
std:vector<int> vec = {1, 2, 3};
size_t i{ vec.size() - 1 };
while (i < size_t(-1))
{
auto& el = vec[i];
--i;
}
use this code
//print the vector element in reverse order by normal iterator.
cout <<"print the vector element in reverse order by normal iterator." <<endl;
vector<string>::iterator iter=vec.end();
--iter;
while (iter != vec.begin())
{
cout << *iter << " ";
--iter;
}
As I don't want to introduce alien-like new C++ syntax, and I simply want to build up on existing primitives, the below snippets seems to work:
#include <vector>
#include <iostream>
int main (int argc,char *argv[])
{
std::vector<int> arr{1,2,3,4,5};
std::vector<int>::iterator it;
// iterate forward
for (it = arr.begin(); it != arr.end(); it++) {
std::cout << *it << " ";
}
std::cout << "\n************\n";
if (arr.size() > 0) {
// iterate backward, simple Joe version
it = arr.end() - 1;
while (it != arr.begin()) {
std::cout << *it << " ";
it--;
}
std::cout << *it << " ";
}
// iterate backwards, the C++ way
std::vector<int>::reverse_iterator rit;
for (rit = arr.rbegin(); rit != arr.rend(); rit++) {
std::cout << *rit << " ";
}
return 0;
}