I am reading on tail recursion as below
Tail recursion refers to a recursive call at the last line. Tail
recursion can be mechanically eliminated by enclosing the body in a
while loop and replacing the recursive call with one assignment per
function argument.
For example
void print(Iterator start, Iterator end, ostream& out=cout) {
if(start == end)
return;
out << *start++ << endl;
print(start, end, out);
}
is converted to iterative by above specification as
void print(Iterator start, Iterator end, ostream& out=cout) {
while(true) {
if(start == end)
return;
out << *start++ << endl;
}
}
In above passage it is mentioned that "replacing recursive call with one assignment per function argument, but in given example we didn't have any assignment?
Can any one explain and provide example for above explanation about how to translate recursive to iterative function?
The assignment is hidden in the increment operator:
start++;
is in fact an assignment:
start = start+1;
Actually, the example (part one) is not very good.
out << *start++ << endl;
print(start, end, out);
should be
out << *start << endl;
print( start+1, end, out);
I don't think, whatever passage you are referring is important; just focus on the main problem, where you want to convert a recursive function to a normal iterative function, which can be done (effortlessly) as,
void print(Iterator start, Iterator end, ostream& out=cout) {
while(start != end) {
out << *start++ << endl;
}
}
It is hidden a little in C++, but start++ is assigning a new value to each time in the loop.
What they are talking about is, that you assign the arguments of the tail function call to the parameter variables of this function invocation, but in this case it is not neccessary, as you are calling the function with the exact same arguments (because like others said, the change to the first argument start happened before the function call).
Actually, if done precisely, the iterative function should look like
void print(Iterator start, Iterator end, ostream& out=cout) {
while(true) {
if(start == end)
return;
out << *start++ << endl;
start = start;
end = end;
out = out;
}
}
But these assignments are completely unneccessary, even if conpectually correct.
The general conversion of recursive to iterative would look like this.
Original code:
void print(Iterator start, Iterator end, ostream& out=cout) {
if(start == end)
return;
out << *start++ << endl;
print(start, end, out);
}
Converted code:
void print(Iterator start, Iterator end, ostream& out=cout) {
while(true) {
if(start == end)
return;
out << *start << endl;
// One assignment per function argument for 'general' tail recursion
start = start + 1; // (1)
end = end; // (2)
out = out; // (3)
}
}
The three assignments as in the explanation are included. Assignment (1) is embedded in the start++, assignments (2) and (3) are optimized away.
Related
I know similar questions have been asked but I can't seem to find an answer for printing via a recursively called function. I am trying to print preorder, postorder, and inorder traversals of an AVL tree and have implemented the functions recursively.
i.e.
void inOrder(Node* root)
{
if(root != nullptr) {
inOrder(root->left);
cout << root->data << ", ";
inOrder(root->right);
}
}
The data should print comma-separated except for the last value, but I am not sure how to do so. I've done research but can't find anything that seems to apply when traversing an AVL tree recursively. Is this possible or should I implement the functions without recursion?
The pattern I usually use for this sort of thing is to use a separator pointer that I change in the loop. The first iteration it's "", so prints nothing, and every subsequent iteration prints the separator. For your recursive case it would be passed as a parameter, and look like this:
void inOrder(Node* root, char ** sep)
{
if(root != nullptr) {
inOrder(root->left, sep);
cout << **sep << root->data;
*sep = ", ";
inOrder(root->right, sep);
}
}
Call it like:
char * sep = "";
inOrder(root, &sep);
It looks a lot nicer for loops. The main advantage is there is no if/else branch in every loop, just a fast pointer assignment to update the separator.
Make an internal implementation function that maintains a flag that indicates whether the data item to be output is the first one. Then prepend the output with a comma for all items but the first.
void inOrderImpl(Node* root, bool& first)
{
if(root != nullptr) {
inOrderImpl(root->left, first);
if (first)
first = false;
else
cout << ", ";
cout << root->data;
inOrderImpl(root->right, first);
}
}
void inOrder(Node* root)
{
bool first = true;
inOrderImpl(root, first);
}
As my comment suggested, an ambitious (and better) way to write the code to do any of the BST traversals would be to use a more generic approach:
template <typename Fn>
void inOrder(Node* root, Fn& func)
{
if(root != nullptr)
{
inOrder(root->left, func);
func(root);
inOrder(root->right, func);
}
}
So given the above, you can basically do anything, since func will be called using the current value of root.
So how does this help us? Consider now the following:
struct TreePrinter
{
bool initial = true;
void operator()(Node *root)
{
if ( initial )
initial = false;
else
std::cout << ",";
std::cout << root->data;
}
};
The above is a class that has overriden operator(). This allows us to pass this to the traversal function, and the traversal function simply calls it.
Note that the initial is a state that gets set in the TreePrinter object.
Then this is how it's implemented:
TreePrinter tp;
Node root;
//...
inOrder(&root, tp);
Here is a live example using a dummy BST.
So not only can you just print a comma, any callable object (function pointer, function object, lambda, etc.) can be provided that can basically use the passed in root to do whatever needs to be done.
I am trying to iterate through a list and then, if the object's plate number matches the one given through the parameters, and if the toll (calculated in toll()) is less than or equal to the given cents, remove/erase the object from the list. I keep getting the error that the list iterator cannot be incremented and I'm clueless as to how to fix it.
void one_time_payment(string& plate_number, int cents) {
// TODO: REWRITE THIS FUNCTION
std::list<LicenseTrip>:: iterator it;
for (it = listLicense.begin(); it != listLicense.end(); std::advance(it, 1)) {
if (it->plate_number().compare(plate_number) == 0) {
cout << "Matching Plate Found" << endl;
if (it->toll() <= cents) {
cout << "Can be paid" << endl;
it = listLicense.erase(it); //Error: list iterator cannot be incremented
}
}
}
cout << "End of Iterator" << endl;
}
This is, I'm guessing, not a compile error but rather an assertion that triggered. You have a bug!
Let's say you're on the last element, and all your conditions apply. So we do:
it = listLicense.erase(it);
Now, it is end(). But right after that, at the end of the body of the for loop, we advance it! This is undefined behavior! Hence: list iterator cannot be incremented.
To help us write this correctly, there is a list::remove_if:
listLicense.remove_if([&](const LicenseTrip& trip){
return trip.plate_number() == plate_number &&
trip.toll() <= cents;
});
So, as Barry explained, the problem that was causing the failed assertion was that the iterator would attempt to advance it beyond end() which would give undefined behavior. In my case, the it would only be needed once (only used to locate a LicenseTrip with a matching plate_number), so it sufficed to put a break; after the listLicense.erase(it). The final working code is as follows:
void one_time_payment(string& plate_number, int cents) {
std::list<LicenseTrip>:: iterator it;
for (it = listLicense.begin(); (it != listLicense.end()) ; std::advance(it, 1)) {
if (it->plate_number().compare(plate_number) == 0 && it->toll() <= cents)
if (it->toll() <= cents) {
listLicense.erase(it);
break;
}
}
}
im studying c++ primer, and in one exercise, i have to do a recursive function that prints the elements on a vector.
I did this:
void printVector(vector<int>::iterator it1, vector<int>::iterator it2) {
cout << *it1 << " ";
if (it1 != it2-1)
printVector((it1 + 1), it2);
}
is there another form to declare it, without the
if(it1!= ***IT2-1***)
i feel like its a mediocre solution couse i cant find another way.
thanks!!
Your function does not accept empty range, which it should, and it is a good idea to put exit condition into begin of a recursive function:
void printVector(vector<int>::iterator it1, vector<int>::iterator it2)
{
if( it1 == it2 ) return;
cout << *it1++ << " ";
printVector(it1, it2);
}
Yes.
void printVector(vector<int>::iterator begin, vector<int>::iterator end)
{
if (begin != end) {
cout << *begin << " ";
printVector(++begin, end)(;
}
}
Yes, you probably want to go at it in another way. It is pretty silly to do recursion when a simple loop will do. Instead, recursion is a tool to use in a more divide an conquer style. I.e. divide into two parts, then apply the same function to the first part and then to the second part.
Usually you then have some kind of cutoff point as to when you can actually do whatever it is you want to do, say for instance that you have less than N number of elements to work with or similar. This example is pretty contrived, because it only brings overhead to do it recursively.
template<class Iter>
void printVector(Iter begin, Iter end)
{
const auto dist = std::distance(begin, end);
if (0 == dist) {
return;
} else if (1 == dist) {
std::cout << *begin;
} else {
// Find the middle
auto pivot = begin + dist/2;
// Apply to first part
printVector(begin, pivot);
// Print separator
std::cout << " ";
// Apply to second part
printVector(pivot, end);
}
}
Please forgive any typos and other issues. Oh, I made it a template as well so that it accepts any random access iterators. That was mostly because it felt annoying to type vector<int>::iterator twice. That should probably be vector<int>::const_iterator by the way.
I have extensively tested the swap and partition function for the following code and they appear to be correct; however, when I try to execute quicksort it goes into an infinite loop. I'm assuming the issue happens from my returned value in partition, but I am not entirely sure what it is.
void swap_G(int *begin, int *end)
{
int temp = *begin;
*begin = *end;
*end = temp;
return;
}
int* partition(int* begin, int* end)
{
if (begin >= end) {
return begin;
}
int pivot = *end;
int* temp_Begin = begin, *temp_End = end;
temp_End--;
while (temp_Begin < temp_End)
{
while (*temp_Begin < pivot && temp_Begin < temp_End)
{
temp_Begin++;
}
while (*temp_End > pivot && temp_End > temp_Begin)
{
temp_End--;
}
swap_G(temp_Begin, temp_End);
}
swap_G(end, temp_Begin);
return temp_Begin;
}
void quicksort_G(int* begin, int* end)
{
if (begin >= end)
{
return;
}
int* mid = partition(begin, end);
quicksort_G(begin, --mid);
quicksort_G(mid + 1, end);
}
Any reason for using all those pointers? A problem I see is with mid
int* mid = partition(begin, end);
quicksort_G(begin, --mid)
This is decrementing the pointer to mid. For example:
int* temp = new int( 6 );
std::cout << *temp << std::endl;
std::cout << *(--temp) << std::endl;
You'll get
6
-33686019
Printing the memory address would yield
std::cout << temp << std::endl;
std::cout << (--temp) << std::endl;
00BE48B0
00BE48AC//Decremented by sizeof(int). Garbage data
I would see if I could get rid of the pointers altogether. You're passing that mid which will be used as end in the next step. But in partition, end will be swapped. So when you return from the first recursive step mid is already messed up.
Problem is possibly in your partition function, and certainly in the way you use its result. The partition function should reorder array items such that the pivot value falls into its final position. Then recursive calls handle items before the pivot and after it, but the pivot itself does not get into processing in the deeper recursion levels. That guarantees the amount of data decreases with each recursion level, so the recursion must stop at some level.
Well I think the question pretty much sums it up. I have a forward_list of unique items, and want to remove a single item from it:
std::forward_list<T> mylist;
// fill with stuff
mylist.remove_if([](T const& value)
{
return value == condition;
});
I mean, this method works fine but it's inefficient because it continues to search once the item is found and deleted. Is there a better way or do I need to do it manually?
If you only want to remove the first match, you can use std::adjacent_find followed by the member erase_after
#include <algorithm>
#include <cassert>
#include <forward_list>
#include <iostream>
#include <ios>
#include <iterator>
// returns an iterator before first element equal to value, or last if no such element is present
// pre-condition: before_first is incrementable and not equal to last
template<class FwdIt, class T>
FwdIt find_before(FwdIt before_first, FwdIt last, T const& value)
{
assert(before_first != last);
auto first = std::next(before_first);
if (first == last) return last;
if (*first == value) return before_first;
return std::adjacent_find(first, last, [&](auto const&, auto const& R) {
return R == value;
});
}
int main()
{
auto e = std::forward_list<int>{};
std::cout << std::boolalpha << (++e.before_begin() == end(e)) << "\n";
std::cout << (find_before(e.before_begin(), end(e), 0) == end(e)) << "\n";
auto s = std::forward_list<int>{ 0 };
std::cout << (find_before(s.before_begin(), end(s), 0) == s.before_begin()) << "\n";
auto d = std::forward_list<int>{ 0, 1 };
std::cout << (find_before(d.before_begin(), end(d), 0) == d.before_begin()) << "\n";
std::cout << (find_before(d.before_begin(), end(d), 1) == begin(d)) << "\n";
std::cout << (find_before(d.before_begin(), end(d), 2) == end(d)) << "\n";
// erase after
auto m = std::forward_list<int>{ 1, 2, 3, 4, 1, 3, 5 };
auto it = find_before(m.before_begin(), end(m), 3);
if (it != end(m))
m.erase_after(it);
std::copy(begin(m), end(m), std::ostream_iterator<int>(std::cout, ","));
}
Live Example
This will stop as soon as a match is found. Note that the adjacent_find takes a binary predicate, and by comparing only the second argument, we get an iterator before the element we want to remove, so that erase_after can actually remove it. Complexity is O(N) so you won't get it more efficient than this.
FWIW, here's another short version
template< typename T, class Allocator, class Predicate >
bool remove_first_if( std::forward_list< T, Allocator >& list, Predicate pred )
{
auto oit = list.before_begin(), it = std::next( oit );
while( it != list.end() ) {
if( pred( *it ) ) { list.erase_after( oit ); return true; }
oit = it++;
}
return false;
}
Going to have to roll your own...
template <typename Container, typename Predicate>
void remove_first_of(Container& container, Predicate p)
{
auto it = container.before_begin();
for (auto nit = std::next(it); ; it = nit, nit = std::next(it))
{
if (nit == container.end())
return;
if (p(*nit))
{
container.erase_after(it);
return;
}
}
}
A more complete example...
There is nothing in the standard library which would be directly applicable. Actually, there is. See #TemplateRex's answer for that.
You can also write this yourself (especially if you want to combine the search with the erasure), something like this:
template <class T, class Allocator, class Predicate>
bool remove_first_if(std::forward_list<T, Allocator> &list, Predicate pred)
{
auto itErase = list.before_begin();
auto itFind = list.begin();
const auto itEnd = list.end();
while (itFind != itEnd) {
if (pred(*itFind)) {
list.erase_after(itErase);
return true;
} else {
++itErase;
++itFind;
}
}
return false;
}
This kind of stuff used to be a standard exercise when I learned programming way back in the early '80s. It might be interesting to to recall the solution, and compare that with what one can do in C++. Actually that was in Algol 68, but I won't impose that on you and give the translation into C. Given
typedef ... T;
typedef struct node *link;
struct node { link next; T data; };
one could write, realising that one needs to pass the address of the list head pointer if is to be possible to unlink the first node:
void search_and_destroy(link *p_addr, T y)
{
while (*p_addr!=NULL && (*p_addr)->data!=y)
p_addr = &(*p_addr)->next;
if (*p_addr!=NULL)
{
link old = *p_addr;
*p_addr = old->next; /* unlink node */
free(old); /* and free memory */
}
}
There are a lot of occurrences of *p_addr there; it is the last one, where it is the LHS of an assignment, that is the reason one needs the address of a pointer here in the first place. Note that in spite of the apparent complication, the statement p_addr = &(*p_addr)->next; is just replacing a pointer by the value it points to, and then adding an offset (which is 0 here).
One could introduce an auxiliary pointer value to lighten the code a bit up, as follows
void search_and_destroy(link *p_addr, T y)
{
link p=*p_addr;
while (p!=NULL && p->data!=y)
p=*(p_addr = &p->next);
if (p!=NULL)
{
*p_addr = p->next;
free(p);
}
}
but that is fundamentally the same code: any decent compiler should realise that the pointer value *p_addr is used multiple times in succession in the first example, and keep it in a register.
Now with std::forward_list<T>, we are not allowed access to the pointers that link the nodes, and get those awkward "iterators pointing one node before the real action" instead. Our solution becomes
void search_and_destroy(std::forward_list<T> list, T y)
{
std::forward_list<T>::iterator it = list.before_begin();
const std::forward_list<T>::iterator NIL = list.end();
while (std::next(it)!=NIL && *std::next(it)!=y)
++it;
if (std::next(it)!=NIL)
list.erase_after(it);
}
Again we could keep a second iterator variable to hold std::next(it) without having to spell it out each time (not forgetting to refresh its value when we increment it) and arrive at essentially the answer by Daniel Frey. (We could instead try to make that variable a pointer of type *T equal to &*std::next(it) instead, which suffices for the use we make of it, but it would actually be a bit of a hassle to ensure it becomes the null pointer when std::next(it)==NIL, as the standard will not let us take &*NIL).
I cannot help feel that since the old days the solution to this problem has not become more elegant.