Rotate circular array in place c++ - c++

I am having trouble writing a function to rotate a circular array. I need to rotate it in place (no temp arrays) and I need to move around as few elements as possible. For background information the class "Quack" is just a queue mixed with a stack. So items can be pushed and popped off of both ends of the circular array. Here is what I have so far:
void Quack::rotate(int r)
{
front = (front + capacity + r) % capacity;
back = (back + capacity + r) % capacity;
}
front and back are ints that act as indexes for the array. r is the amount to rotate. capacity is the max size of the array.
The problem is if the array has "garbage" values in it, I end up rotating those into the array. For example lets say the ACTUAL array of chars is {a, b, c, d, e, f, g}, and front is 5 and back is 3. If I printed the circular array I would see {f, g, a, b, c, d}. Since front is 5 and back is 3, the index 4 is a "garbage" value (it got popped at some point). So my rotate function as it stands has a problem in that the index 4 gets "rotated in". If I rotate the array by 2, the ACTUAL array is still {a, b, c, d, e, f, g}, except now when I print it out since front and back are different I get {a, b, c, d, e, f}. What I want to see is {a, b, c, d, f, g}. My print function just prints from front to back (wrapping around as needed) so I need my rotate function to somehow eliminate the garbage value.
I think I need to move the back elements over so I have consecutive values without garbage in the middle. But I'm not sure how to do it.

So if the array isn't full you need to move some char's around. First you check if r is positive or negative. If it's negative you need to push the back over to be flush with the front for the number r or vise versa. example:
print out: c, b, a, z, f, g rotate 2
a z f g - c b
0 1 2 3 4 5 6
the c (items[5]) is in the front and g (items[3]) is back. If we just add r to both it will print garbage for the empty space. If r is 2, we want to copy c to items[4] and b to items[5]. Then items[0] should be the front and b now items[5] should be the back.
void Quack::rotate(int r)
{
if (nItems < capacity) { //if it's not full
if (r < 0) { // if r is negative
int r2 = r*(-1); //find absolute value
for (int i = 0; i < r2; i++) {
items[(back + 1 - i) % (capacity)] = items[(back - i < 0) ? capacity + back - i : back - i]; //push back the back chars up to the front r times
}
}
else {
for (int i = 0; i < r; i++){
items[(back + 1 + i)% capacity] = items[(front + i) % capacity];
}
}
}
front = ((front + r > 0) ? (front + r)%capacity : front + r + capacity); //if front + r is negative add capacity to it
back = (back + r) % capacity;
}

With a cyclic iterator and std::rotate:
#include <algorithm>
#include <iterator>
template <typename Iterator>
class cyclic_range
{
public:
typedef Iterator iterator;
cyclic_range(iterator first, iterator middle, iterator last)
: m_first(first), m_middle(middle), m_last(last)
{
if(m_middle == m_last) m_middle = m_first;
}
iterator first() const { return m_first; }
iterator middle() const { return m_middle; }
iterator last() const { return m_last; }
private:
iterator m_first;
iterator m_middle;
iterator m_last;
};
template <typename Iterator>
inline cyclic_range<Iterator>
make_cyclic_range(Iterator first, Iterator middle, Iterator last) {
return cyclic_range<Iterator>(first, middle, last);
}
/// A cyclic random access iterator operating on a iterator range [first, last).
/// If an iterator reaches the last (or is at last) position of the range the iterator
/// becomes equal to the first position of the range.
template <
typename RandomAccessIterator,
typename CyclicRange = cyclic_range<RandomAccessIterator> >
class cyclic_iterator
{
public:
typedef RandomAccessIterator inner_iterator;
typedef std::iterator_traits<inner_iterator> inner_iterator_traits;
typedef typename std::random_access_iterator_tag iterator_category;
typedef typename inner_iterator_traits::value_type value_type;
typedef typename inner_iterator_traits::difference_type difference_type;
typedef typename inner_iterator_traits::reference reference;
typedef typename inner_iterator_traits::pointer pointer;
typedef CyclicRange range_type;
public:
cyclic_iterator(inner_iterator pos, range_type range, bool at_end = false)
: m_pos(pos), m_range(range), m_at_end(at_end)
{
if(m_pos == range.last()) {
m_pos = range.first();
}
if(m_range.first() == m_range.last()) m_at_end = true;
}
const range_type& range() const { return m_range; }
/// True if the incremented or decremented iterator is at the middle of
/// the circular range.
bool at_end() const { return m_at_end; }
reference operator * () const noexcept {
return *m_pos;
}
pointer operator -> () const noexcept { return &*m_pos; }
cyclic_iterator& operator ++ () noexcept {
if(++m_pos == m_range.last()) m_pos = m_range.first();
m_at_end = (m_pos == m_range.middle());
return *this;
}
cyclic_iterator operator ++ (int) noexcept {
return ++cyclic_iterator(*this);
}
cyclic_iterator& operator += (difference_type n) noexcept {
if(n) {
if(n < 0) *this -= -n;
else {
n %= (m_range.last() - m_range.first());
difference_type avail = m_range.last() - m_pos;
if(n < avail) m_pos += n;
else {
m_pos = m_range.first();
n -= avail;
m_pos += n;
}
m_at_end = (m_pos == m_range.middle());
}
}
return *this;
}
cyclic_iterator operator + (difference_type n) const noexcept {
return cyclic_iterator(*this) += n;
}
cyclic_iterator& operator -- () noexcept {
if(m_pos == m_range.first()) m_pos = m_range.last();
--m_pos;
m_at_end = (m_pos == m_range.middle());
return *this;
}
cyclic_iterator operator -- (int) noexcept {
return --cyclic_iterator(*this);
}
cyclic_iterator& operator -= (difference_type n) noexcept {
if(n) {
if(n < 0) *this += -n;
else {
n %= (m_range.last() - m_range.first());
difference_type avail = m_pos - m_range.first();
if(avail < n) {
m_pos = m_range.last();
n -= avail;
}
m_pos -= n;
m_at_end = (m_pos == m_range.middle());
}
}
return *this;
}
cyclic_iterator operator - (difference_type n) const noexcept {
return cyclic_iterator(*this) -= n;
}
difference_type operator - (const cyclic_iterator& other) const noexcept {
return index() - other.index();
}
bool operator == (const cyclic_iterator& other) noexcept {
return (index() == other.index());
}
bool operator != (const cyclic_iterator& other) noexcept {
return ! (*this == other);
}
bool operator < (const cyclic_iterator& other) noexcept {
return index < other.index();
}
bool operator <= (const cyclic_iterator& other) noexcept {
return ! (other < this);
}
bool operator > (const cyclic_iterator& other) noexcept {
return (other < this);
}
bool operator >= (const cyclic_iterator& other) noexcept {
return ! (this < other);
}
private:
/// The index of the iterator position.
typedef std::size_t size_type;
size_type index() const noexcept {
size_type n = m_range.last() - m_range.first();
if( ! m_at_end) {
if(m_range.middle() <= m_pos) {
n = m_pos - m_range.middle();
}
else {
n = (m_pos - m_range.first()) + (m_range.last() - m_range.middle());
}
}
return n;
}
private:
inner_iterator m_pos;
range_type m_range;
bool m_at_end;
};
template <typename Iterator>
cyclic_iterator<Iterator> begin(const cyclic_range<Iterator>& range) {
return cyclic_iterator<Iterator>(range.middle(), range);
}
template <typename Iterator>
cyclic_iterator<Iterator> end(const cyclic_range<Iterator>& range) {
return cyclic_iterator<Iterator>(range.middle(), range, true);
}
// Test
// ====
#include <iostream>
#include <vector>
template <typename Iterator>
void print_cyclic_range(Iterator first, Iterator last) {
std::cout << "Cyclic Range: ";
for( ; first != last; ++first) {
std::cout << *first << ' ';
}
std::cout << '\n';
}
template <typename Iterator>
void print_range(Iterator first, Iterator last) {
std::cout << " Range: ";
for( ; first != last; ++first) {
std::cout << *first << ' ';
}
std::cout << '\n';
}
int main()
{
typedef cyclic_iterator<char*> cyclic_iterator;
char v[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'};
print_range(v, v + sizeof(v));
// The cyclic range from 'f' to (including) 'e'
cyclic_iterator::range_type range(v, v + 5, v + sizeof(v));
// The cyclic iterator pointing to 'f'
cyclic_iterator first = begin(range);
// The cyclic iterator pointing to 'e'
cyclic_iterator last = end(range) - 1;
print_cyclic_range(first, last);
// Rotate the cyclic range from 'f' to (including) 'd', excluding 'e'
std::rotate(first, first + 2, last);
print_range(v, v + sizeof(v));
print_cyclic_range(first, last);
return 0;
}
Giving:
Range: a b c d e f g
Cyclic Range: f g a b c d
Range: c d f g e a b
Cyclic Range: a b c d f g

Related

Class Iterator inside of container class

I need to build an inner class iterator to work with a container class FigureOfCircles
#define T Circle
class FigureOfCircles {
private:
Circle* c;
int size;
public:
class Iterator {
protected:
T* t;
public:
explicit Iterator (T* t1 = 0) : t(t1) { }
Iterator (const Iterator& x) : t(x.t) {}
T& operator*() const { return *t; }
T* operator->() const { return t; }
Circle& operator[](const std::size_t& n) { return t[n]; }
Iterator& operator++() { ++t; return *this; }
Iterator operator++(int) { return Iterator(t++); }
Iterator& operator--() { --t; return *this; }
Iterator operator--(int) { return Iterator(t--); }
Iterator operator- (int n) { return Iterator(t - n); }
Iterator operator+ (int n) { return Iterator(t - n); }
Iterator& operator-= (int n) { t -= n; return *this; }
Iterator& operator+= (int n) { t += n; return *this; }
bool operator== (const Iterator& x) const { return t == x.t; }
bool operator!= (const Iterator& x) const { return t != x.t; }
bool operator<= (const Iterator& x) const { return t <= x.t; }
bool operator> (const Iterator& x) const { return t > x.t; }
bool operator>= (const Iterator& x) const { return t >= x.t; }
bool operator< (const Iterator& x) const { return t < x.t; }
friend int operator- (const Iterator& x, const Iterator& y) { return x.t - y.t; }
Iterator& operator= (const Iterator& x) {
if (t == x.t) exit(-6);
t = x.t;
return *this;
}
};
FigureOfCircles (int sz) : size(sz) {
c = new T[size];
for (Iterator i = begin(); i != end(); ++i) *i = input();
}
FigureOfCircles(const FigureOfCircles& f) {
size = f.size;
c = new T[size];
for (Iterator i = begin(); i != end(); ++i) *i = f.c[i - begin()];
}
~FigureOfCircles() { if (c) delete[] c; }
Circle input() {
int size = 1;
Point* arr = new Point[size];
float r, x1, y1;
cout << endl << "Введiть к-сть точок, радiус i координати центру: ";
cin >> size >> r >> x1 >> y1;
for (int i = 0; i < size; i++) {
Point tmp;
cin >> tmp;
if (tmp.GetX() == x1 && tmp.GetY() == y1) exit(-7);
if (pow(tmp.GetX() - x1, 2) + pow(tmp.GetY() - y1, 2) != r * r) exit(-8);
arr[i] = tmp;
}
return Circle(size, r, arr, x1, y1);
}
Iterator begin() { return Iterator(c); }
Iterator end() { return Iterator(c+size); }
};
But I don’t understand what type should T be so that I can use the iterator object? If it is int, then what about
Iterator begin() { return Iterator(c); }
Iterator end() { return Iterator(c+size); }
Note:
FigureOfCircles (int sz) : size(sz) {
c = new T[size];
for (int i = 0; i < size; i++)
c[i].input();
for (Iterator i = begin(); i != end(); ++i) {
*i = T(i-begin());
}
}
...
int main () {
//...
FigureOfCircles f(2);
FigureOfCircles::Iterator i;
for (i = f.begin(); i != f.end(); i++) cout << *i << endl;
}
You have an array of Circles, pointed by c. An iterator should point to elements of this array. The simplest solution is to use a plain pointer. That is, T in your iterator should be just Circle.
If you want to use int (it should be std::ptrdiff_t), your iterator should also keep a pointer to the first element. In this particular example I don't see a reason to do it.
operator- should return the difference between pointers, std::ptrdiff_t, not Circle:
friend std::ptrdiff_t operator-(Iterator x, Iterator y) {
return x.t - y.t;
}
Take Iterator by value. It's just a single pointer, you don't need to take it by const-ref (effectively taking a pointer to a pointer).
Once you have iterators, you can use the standard library algorithms to make copies: instead of
for (Iterator i = begin(); i != end(); ++i) *i = f.c[i - begin()];
you can write
std::copy(f.begin(), f.end(), begin());
I suggest you use std::vector<Circle> instead of Circle*. Then you'll be able to borrow its iterators:
class FigureOfCircles {
private:
std::vector<Circle> c;
public:
std::vector<Circle>::iterator begin() {
c.begin();
}
std::vector<Circle>::iterator end() {
c.end();
}
};
This will also save you from writing a copy constructor and destructor.
While #Evg's answer is valid, it is not clear from your question why would even need to write your own iterator. If, instead of a pair of pointer+length members, you would use an std::vector or std::array - or even std::span which is oblivious to where you get your buffer from - you could use these classes' respective iterators instead of implementing your own.
It is only if you have some special behavior in your FigureOfCircles class - e.g. element skipping, non-standard iteration order and so on - that you really need a custom iterator.
PS - The naming is a bit awkward. If a Figure can only have Circles, then just call the class Figure. If there are Figures of something other than Circles, try: template <typename Element> class Figure { ... } and then you'll use Figure<Circle>.

Problems with constant iterators

I'm trying write a tempate function which takes a sequence (by 2 iterators) and calculates the number of permutations of this sequence, in which there are no consecutive identical elements.
Thats what i did
template<class Iterator>
size_t count_perm(Iterator p, Iterator q)
{
if (p == q)
return 1;
size_t count = 0;
while(std::next_permutation(p, q)){
if(std::adjacent_find(p,q) != q)
++count;
}
}
/*Example
std::array<int, 3> a1 = {1,2,3};
size_t c1 = count_perm(a1.begin(), a1.end()); // 6
std::array<int, 5> a2 = {1,2,3,4,4};
size_t c2 = count_perm(a2.begin(), a2.end()); // 36*/
This code not working if i pass const iterators. What should I change to make it work with const iterators?
This code not working if i pass const iterators. What should I change to make it work with const iterators?
You can't: std::next_permutation() modify the values so is incompatible with const iterators.
-- EDIT --
The OP ask
How can i implement this function in right way?
I suggest you to follows the suggestion from Jarod42: works over a copy.
I propose something as follows
template <class Container>
size_t count_perm (Container c) // note: c is a copy
{
if ( c.cbegin() == c.cend() )
return 1;
size_t count = 0U;
std::sort(c.begin(), c.end());
if (std::adjacent_find(c.cbegin(), c.cend()) != c.cend()))
{
std::size_t ui = c.size();
for ( count = ui ; --ui > 1 ; count *= ui )
;
// count now is c.size() ! (factorial of)
}
else
{
while (std::next_permutation(c.begin(), c.end()))
if (std::adjacent_find(c.cbegin(), c.cend()) != c.cend())
++count;
}
return count; // remember this return!
}
Fixed your templated function for you (still requires non-const iterators):
template<class Iterator> size_t count_perm(Iterator p, Iterator q)
{
if (p == q || std::all_of(p, q, [&](auto &el) {return el == *p; })))
return 0;
size_t count = 1;
std::sort(p, q);
while (std::next_permutation(p, q))
if (std::adjacent_find(p, q) == q)
++count;
return count;
}
you should return count
when no adjacent elements are found, std::adjacent_find returns end, so you should == q not != q
Your example produces 6 and 37. Should it be 36 instead of 37?
Solved this exercise as follows, it works with const iterators:
template<class Iterator>
size_t count_permutations(Iterator p, Iterator q)
{
using T = typename std::iterator_traits<Iterator>::value_type;
if (p == q)
return 1;
std::vector<T> v(p,q);
std::sort(v.begin(), v.end());
size_t count = 0;
do{
if(std::adjacent_find(v.begin(),v.end()) == v.end()) {
++count;
}
} while(std::next_permutation(v.begin(), v.end()));
return count;
}
Problem was to use std::type_traits<Iterator>::value_type instead Iterator::value_type (that not working with const iters and simple pointers (like int*))

Elegantly (iterating) parsing data in chunks?

We have some "iterable" collection of data, for instance: std::vector<Foo> bar.
We wish to process Foo elements from bar until some condition is met in which point we "yield" (think Python) the result of all these processed Foos and wait until the next chunk of parsed information is requested.
So far what we're doing is this:
ParsedChunk foobar( std::vector<Foo> bar, size_t* start_from) {
size_t& i = *start_from;
ParsedChunk result_so_far;
for (;i < bar.size(); i++) {
process_some_foo_and_update_chunk(result_so_far, bar[i]);
if (check_condition(? ? ?) {
return result_so_far;
}
}
}
Any suggestions for doing this better?
As I already pointed out in my comment, this is IMO a very good case for an custom iterator:
The iterator scans through your range, as long as some predicate holds, and
when the predicate isn't true for some element, calls a function with the sub range of elements where the predicate held (plus the one that didn't satisfy the predicate). The result of that function call is then the value you get when you dereference the iterator.
template<typename Fn, typename Predicate, typename Iterator>
struct collector {
using value_type = typename std::result_of<Fn(Iterator, Iterator)>::type;
using pointer = value_type const *;
using reference = value_type const &;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
value_type cache;
Fn fn;
Predicate predicate;
Iterator pos, from, stop;
collector(Fn&& fn, Predicate&& p, Iterator&& s, Iterator&& e)
: fn(std::forward<Fn>(fn)),
predicate(std::forward<Predicate>(p)),
pos(std::forward<Iterator>(s)),
from(pos),
stop(std::forward<Iterator>(e))
{
next_range();
}
collector & operator++(void) {
next_range();
return *this;
}
reference operator*(void) const {
return cache;
}
void next_range(void) {
from = pos;
if (pos == stop) return;
for (; pos != stop; ++pos) {
if (not predicate(*pos)) {
++pos;
break;
}
}
cache = fn(from, pos);
}
collector end_of_range(void) const {
auto copy = collector{*this};
copy.pos = copy.stop;
copy.from = copy.stop;
return copy;
}
bool operator==(collector const & rhs) const {
return (from == rhs.from) and (pos == rhs.pos) and (stop == rhs.stop);
}
bool operator!=(collector const & rhs) const {
return (from != rhs.from) or (pos != rhs.pos) or (stop != rhs.stop);
}
};
template<typename Fn, typename Predicate, typename Iterator>
auto make_collector_range(Fn&& fn, Predicate&& p, Iterator&& s, Iterator&& e) {
using I = typename std::decay<Iterator>::type;
using P = typename std::decay<Predicate>::type;
using F = typename std::decay<Fn>::type;
using C = collector<F,P,I>;
auto start = C{
std::forward<Fn>(fn), std::forward<Predicate>(p),
std::forward<Iterator>(s), std::forward<Iterator>(e)};
auto stop = start.end_of_range();
return make_pair(std::move(start), std::move(stop));
}
An example usage, calculating the sum of the numbers till 50, but not in one step, but in steps of 15 numbers each:
int main(int, char**) {
vector<int> numbers = vector<int>(50);
generate(begin(numbers), end(numbers),
[i = 0] (void) mutable{
return ++i;
});
copy(begin(numbers), end(numbers), ostream_iterator<int>{cout, " "});
cout << endl;
auto collected = make_collector_range(
[](auto const & from, auto const & to) {
return accumulate(from, to, 0);
},
[](auto const & num) {
return not ((num % 3 == 0) and (num % 5 == 0));
},
begin(numbers), end(numbers));
copy(collected.first, collected.second, ostream_iterator<int>{cout, " "});
cout << endl;
bool passed = accumulate(collected.first, collected.second, 0) == (50*51)/2;
cout << "test " << (passed ? "passed" : "failed") << endl;
return 0;
}
(Live demo here)
(Note: This example uses a fixed "step" width, and predicate and function are unrelated to each other and don't maintain state, but none of this is required by the iterator.)
I hope the intention of the code is clear, if not I can try to provide a more detailed explanation about its workings.

Implementation of Deque in C++

I'm writing an implementation of Deque as a programming exercise and it's not going too well at all. I'm missing a few key function that are needed to make the test main program I was given function correctly.
Here is my code so far:
#include <vector>
#include <iostream>
#include <cassert>
using namespace std;
template <class T> class DequeIterator;
template <class T>
class Deque {
public:
typedef DequeIterator<T> iterator;
Deque(): vecOne(), vecTwo() { }
Deque(unsigned int size, T& initial): vecOne(size/2, initial), vecTwo(size-(size/2), initial) { }
Deque(Deque<T> & d): vecOne(d.vecOne), vecTwo(d.vecTwo) { }
T & operator[](unsigned int);
T & front();//
T & back();//
bool empty(){ return vecOne.empty() && vecTwo.empty(); }
iterator begin() { return iterator(this,0); }
iterator end() { return iterator(this, size ()); }
void erase(const iterator &);
void erase(const iterator &, const iterator &);
void insert(const iterator &, const T &);
int size() { return vecOne.size() + vecTwo.size(); }
void push_front(const T & value) { vecOne.push_back(value); }
void push_back(const T & value) {vecTwo.push_back(value); }
void pop_front();
void pop_back();
protected:
vector<T> vecOne;
vector<T> vecTwo;
};
template <class T>//
T & Deque<T>::front()//returns the first element in the deque
{
if (vecOne.empty())
return vecTwo.front();
else
return vecOne.back();
}
template <class T>//
T & Deque<T>::back()//returns the last element in the deque
{
if (vecOne.empty())
return vecTwo.back();
else
return vecOne.front();
}
template <class T>//
T & Deque<T>::operator[] (unsigned int index)
{
int n = vecOne.size();
if (index < n)
return vecOne [ (n-1) - index ];
else
return vecTwo [ index - n ];
}
template <class T>//
Deque<T>::iterator DequeIterator<T>::operator ++ (int)
{
Deque<T>::iterator clone(theDeque, index);
index++;
return clone;
}
template <class T>//
void Deque<T>::pop_front()
{
}
template <class T>//
void Deque<T>::pop_back()
{
}
template <class T>//
void Deque<T>::erase (const iterator & itr)
{
int index = itr.index;
int n = vecOne.size();
if (index < n)
vecOne.erase (vecOne.begin() + ((n-1) - index));
else
vecTwo.erase (vecTwo.begin() + (n - index));
}
template <class T>//
void Deque<T>::erase (const iterator &, const iterator &)
{
}
template <class T>//
void Deque<T>::insert(const iterator &, const T &)
{
}
template <class T>
class DequeIterator {
friend class Deque<T>;
typedef DequeIterator<T> iterator;
public:
DequeIterator(): theDeque(0), index(0) { }
DequeIterator(Deque<T> * d, int i): theDeque(d), index(i) { }
DequeIterator(const iterator & d): theDeque(d.theDeque), index(d.index) { }
T & operator*() { return (*theDeque)[index]; }
iterator & operator++(int) { ++index; return *this; }
iterator operator++();
iterator operator--(int) { --index; return *this; }
iterator & operator--();
bool operator==(const iterator & r) { return theDeque == r.theDeque && index == r.index; }
bool operator!=(const iterator & r) { return theDeque == r.theDeque && index != r.index; }
bool operator< (const iterator & r) { return theDeque == r.theDeque && index < r.index; }
T & operator[](unsigned int i) { return (*theDeque) [index + i]; }
iterator operator=(const iterator & r) { theDeque = r.theDeque; index = r.index; }
iterator operator+(int i) { return iterator(theDeque, index + i); }
iterator operator-(int i) { return iterator(theDeque, index - i); }
protected:
Deque<T> * theDeque;
int index;
};
main()
{
Deque<int> d;
d.push_back(10);
d.push_back(20);
assert(d.front() == 10);
assert(d.back() == 20);
d.push_front(1);
d.push_front(2);
d.push_front(3);
assert(d.front() == 3);
assert(d.back() == 20);
d.pop_back();
d.pop_back();
d.pop_back();
assert(d.front() == 3);
assert(d.back() == 2);
d.push_back(1);
d.push_back(0);
Deque<int>::iterator i;
int counter = 3;
for (i = d.begin(); i != d.end(); i++)
assert(*i == counter--);
for (counter = 0; counter < d.size(); counter++)
assert(d[counter] == d.size()-counter-1);
i = d.begin() + 3;
Deque<int>::iterator j(i), k;
k = j = i - 2;
assert(*k == 2);
for (i = d.begin(); not(i == d.end()); ++i)
cout << *i << " ";
cout << endl;
d.erase(d.begin()+3);
//d.erase(d.begin(), d.begin()+2);
assert(d.size() == 1);
assert(d[0] == 1);
Deque<int> c(d);
c.front() = 3;
assert(c.back() == 3);
c.push_front(1);
c.insert(c.begin(), 0);
c.insert(c.begin()+2, 2);
for (i = c.begin(); not(i == c.end()); ++i)
cout << *i << " ";
cout << endl;
for (counter = 0; counter < c.size(); counter++)
assert(c[counter] == counter);
cout << "SUCCESS\n";
}
I was wondering if someone could tell me my function from line 66 is returning:
expected constructor, destructor, or type conversion before 'DequeIterator'
Because I'm not sure what I'm doing wrong in it. Also, if someone would be kind enough to give me an example of the pop_front() function so that I can use it to create the pop_back() function as well, that would be great. Lastly, I have on of the erase functions completed but I am not sure how to go about creating the second one, which basically erases a value within the range of two iterators, it is referenced in line 176.
Any help would be greatly appreciated. Thank you in advance.
As for the error, you probably need a typename before Deque<T>::iterator on that line.
typename Deque<T>::iterator DequeIterator<T>::operator++(int)
I think it is a great programming exercise to implement deque. But a prerequisite is to implement vector and list. deque is one of the most complicated std::containers to implement. You should start with one of the simpler ones (vector and list).
Well, you get the error on line 65 because you return an object of a class that hasn't been defined. You only have the forward declaration (prototype) for class DequeIterator, not the implementation.
void pop_back() {
vecTwo.pop_back();
}
void pop_front() {
vecOne.pop_back();
}

Is there a standard cyclic iterator in C++

Based on the following question: Check if one string is a rotation of other string
I was thinking of making a cyclic iterator type that takes a range, and would be able to solve the above problem like so:
std::string s1 = "abc" ;
std::string s2 = "bca" ;
std::size_t n = 2; // number of cycles
cyclic_iterator it(s2.begin(),s2.end(),n);
cyclic_iterator end;
if (std::search(it, end, s1.begin(),s1.end()) != end)
{
std::cout << "s1 is a rotation of s2" << std::endl;
}
My question, Is there already something like this available? I've checked Boost and STL and neither have an exact implementation.
I've got a simple hand-written (derived from a std::forward_iterator_tag specialised version of std::iterator) one but would rather use an already made/tested implementation.
There is nothing like this in the standard. Cycles don't play well with C++ iterators because a sequence representing the entire cycle would have first == last and hence be the empty sequence.
Possibly you could introduce some state into the iterator, a Boolean flag to represent "not done yet." The flag participates in comparison. Set it true before iterating and to false upon increment/decrement.
But it might just be better to manually write the algorithms you need. Once you've managed to represent the whole cycle, representing an empty sequence might have become impossible.
EDIT: Now I notice that you specified the number of cycles. That makes a big difference.
template< class I >
class cyclic_iterator
/* : public iterator< bidirectional, yadda yadda > */ {
I it, beg, end;
int cnt;
cyclic_iterator( int c, I f, I l )
: it( f ), beg( f ), end( l ), cnt( c ) {}
public:
cyclic_iterator() : it(), beg(), end(), cnt() {}
cyclic_iterator &operator++() {
++ it;
if ( it == end ) {
++ cnt;
it = beg;
}
} // etc for --, post-operations
friend bool operator==
( cyclic_iterator const &lhs, cyclic_iterator const &rhs )
{ return lhs.it == rhs.it && lhs.cnt == rhs.cnt; } // etc for !=
friend pair< cyclic_iterator, cyclic_iterator > cycle_range
( int c, I f, I l ) {//factory function, better style outside this scope
return make_pair( cyclic_iterator( 0, f, l ),
cyclic_iterator( c, f, l ) );
}
};
This should provide some ideas/solutions: 2 renditions, the second is a little lighter in weight. Both tested using a subrange of a vector and a list ...
#include <vector>
template <typename T, typename Container = std::vector<T>, typename Iterator = Container::iterator>
class RingIterator : public std::iterator <std::bidirectional_iterator_tag, T, ptrdiff_t>
{
Container& data;
Iterator cursor;
Iterator begin;
Iterator end;
public:
RingIterator (Container& v) : data(v), cursor(v.begin()), begin(v.begin()), end(v.end()) {}
RingIterator (Container& v, const Iterator& i) : data(v), cursor(i), begin(v.begin()), end(v.end()) {}
RingIterator (Container& v, const Iterator& i, const Iterator& j) : data(v), cursor(i), begin(i), end(j) {}
RingIterator (Container& v, size_t i) : data(v), cursor(v.begin() + i % v.size()), begin(v.begin()), end(v.end()) {}
bool operator == (const RingIterator& x) const
{
return cursor == x.cursor;
}
bool operator != (const RingIterator& x) const
{
return ! (*this == x);
}
reference operator*() const
{
return *cursor;
}
RingIterator& operator++()
{
++cursor;
if (cursor == end)
cursor = begin;
return *this;
}
RingIterator operator++(int)
{
RingIterator ring = *this;
++*this;
return ring;
}
RingIterator& operator--()
{
if (cursor == begin)
cursor = end;
--cursor;
return *this;
}
RingIterator operator--(int)
{
RingIterator ring = *this;
--*this;
return ring;
}
RingIterator insert (const T& x)
{
return RingIterator (data, data.insert (cursor, x));
}
RingIterator erase()
{
return RingIterator (data, data.erase (cursor));
}
};
template <typename T, typename Iterator>
class CyclicIterator : public std::iterator <std::bidirectional_iterator_tag, T, ptrdiff_t>
{
Iterator cursor;
Iterator begin;
Iterator end;
public:
CyclicIterator (const Iterator& i, const Iterator& j) : cursor(i), begin(i), end(j) {}
bool operator == (const CyclicIterator& x) const
{
return cursor == x.cursor;
}
bool operator != (const CyclicIterator& x) const
{
return ! (*this == x);
}
reference operator*() const
{
return *cursor;
}
CyclicIterator& operator++()
{
++cursor;
if (cursor == end)
cursor = begin;
return *this;
}
CyclicIterator operator++(int)
{
CyclicIterator ring = *this;
++*this;
return ring;
}
CyclicIterator& operator--()
{
if (cursor == begin)
cursor = end;
--cursor;
return *this;
}
CyclicIterator operator--(int)
{
CyclicIterator ring = *this;
--*this;
return ring;
}
};
#include <iostream>
#include <iomanip>
#include <list>
enum { CycleSize = 9, ContainerSize };
template <typename cyclicIterator>
void test (cyclicIterator& iterator, size_t mn)
{
int m = mn;
while (m--)
for (int n = mn; n--; ++iterator)
std::cout << std::setw(3) << *iterator << ' ';
--iterator;
m = mn;
while (m--)
for (int n = mn; n--; --iterator)
std::cout << std::setw(3) << *iterator << ' ';
}
template <typename containers>
void load (containers& container)
{
while (container.size() < ContainerSize)
container.push_back (container.size());
}
void main (void)
{
typedef std::vector<int> vContainer;
typedef vContainer::iterator vIterator;
typedef std::list<int> lContainer;
typedef lContainer::iterator lIterator;
vContainer v; load (v);
vIterator vbegin = v.begin() + 1;
RingIterator <int, vContainer, vIterator> vring (v, vbegin, v.end());
CyclicIterator <int, vIterator> vcycle (vbegin, v.end());
lContainer l; load (l);
lIterator lbegin = l.begin(); ++lbegin;
RingIterator <int, lContainer, lIterator> lring (l, lbegin, l.end());
CyclicIterator <int, lIterator> lcycle (lbegin, l.end());
test (vring, CycleSize);
test (vcycle, CycleSize);
test (lring, CycleSize);
test (lcycle, CycleSize);
}
The CGAL library defines Circulators. They are used like this.
template<class Circulator, class T>
bool contains(Circulator c, Circulator d, const T& value) {
if (c != 0) {
do {
if (*c == value)
return true;
} while (++c != d);
}
return false;
}
Note that they look like iterators at first glance but note that the logic (and the structure of the loop) is different than for iterators). if(not empty) do{..}while() instead of while(){...}.
Eric Niebler's ranges-v3 library (on which the upcoming C++20 ranges is based) has ranges::view::cycle. This adapts its source range into an endlessly repeating infinite range. However we require a single repeat which may be easily achieved using ranges::view::concat.
#include <ranges/v3/all.hpp>
int main() {
std::string s1 = "abc";
std::string s2 = "bca";
auto s2s2 = ranges::view::concat(s2, s2);
auto i = std::search(s2s2.begin(), s2s2.end(), s1.begin(), s1.end());
if (i != s2s2.end() && s1.size() == s2.size()) {
std::cout << "s1 is a rotation of s2\n";
}
}
You’re maybe looking for Boost’s Circular Buffer. But if you’ve already checked Boost, it might not be the one you want.
On the other hand, the very idea of cyclic iterator is not compatible to STL container ideology. You should not want cyclic iterator, as the user of this iterator may be surprized by its unusual behavior. Usually in STL you are iterating from the beginning to the end of container. Infinite loop in that case. Because the end is not reachable.
After all, obviously, you are not going to do more than 2 cycles to solve your task. No reason to have special iterator with confusing behavior. That is better to iterate usual linear container twice or may be even less then twice.