I want to find the index of biggest element of an array recursively. The declaration of the function can be like this:
int maxIndex(const int *p, int size)
I was studying recursion and I saw some examples, like finding the max array element recursively. That is simple like this:
int maxInt( const int * p, int size)
{
if(size == 1)
return *p;
int max = maxInt(p + 1, size -1 );
if(max > *p)
return max;
else
return p[0];
}
And I asked myself that how can I find the index which includes max element of the array.
I am not even sure it is possible. What do you think?
It is definitely possible: all you need to do is to modify code to return a pointer to max int, and then subtracting the initial pointer from the return value of maxInt in C, or using std::distance in C++.
const int* maxInt( const int * p, int size) {
if(size == 1)
return p;
int *maxPtr = maxInt(p + 1, size -1 );
if(*maxPtr > *p)
return maxPtr;
else
return p;
}
In C:
int index = maxInt(array, size) - array;
In C++:
ptrdiff_t index = std::distance(maxInt(array, size), array);
Note: Solving this problem using recursion should only be considered as part of a learning exercise, because of a very real possibility of overflowing the stack. The same applies to any other problem with potentially high number of recursive invocations and no tail call optimization.
Let's make a bonus question out of it. What's the main problem with recursion here? The main problem is that you end up having as many times maxInt called as you have elements. This is going to happen at the same time, i.e., call stack will look following:
maxInt
maxInt
maxInt
...
Given that the call stack is limited to several hundreds call on modern systems (even less, may be) this solution isn't practical. However, can we make it more practical? Yes, we can - if we transform the current recursion into something which is called tail recursion - that is, when recursion call is happening at the very end of the function - we can employ so-called 'tail-call optimization', which makes sure the recursion does not actually call a function, but behaves like a loop, and end up with the flexibility and performance of the loop. Like I said, the key is to make sure the function is called in the end. Here is how we can do this:
int maxInt( const int * p, int size, int curr_max)
{
curr_max = (curr_max > *p) ? curr_max : *p;
if(size == 1)
return curr_max;
return maxInt(p + 1, size -1, curr_max);
}
If you look into assembly language generated for this function is any optimization above O1, you will see that there is no recursion function call there, but instead there is a loop.
This solution can than be combined with one from dasblinkenlight to provide a solution to OP's homework.
Here's what you want with the function header you want. The index returned from maxInt needs to be adjusted at each level of recursion, which I do with the + 1 part.
int maxInt(const int* p, int size)
{
if (size == 1)
{
return 0;
}
int max = maxInt(p + 1, size - 1) + 1;
return p[max] > *p ? max : 0;
}
Keep in mind that every time the code in the question returns, it is returning the value pointed to, and not its index in the array (*p and p[0]).
to find the first index of a number....if same element are occurring multiple times example [9,8,10,8] and we have to find the first index of element 8.
int firstIndex(int input[], int size, int x) {
if(size==0)
{
return -1;
}
if(input[0]==x)
{
return 0 ;
}
int ans = firstIndex(input+1,size-1,x);
if(ans==-1)
{
return -1;
}else if(ans!=-1)
{
return ans+1;
}
}
Related
I implemented a mergesort algorithm but it returns the exact same array I pass as an input. The following is the code. I am suspecting the pseudocode that our professor gave us is wrong. But I am not sure. I have tried to implement is as best as I can.
int len(double *a) {
int count = 0;
while (a[count] != '\0') {
count++;
}
return count;
}
double* merge(double* b, double* c, int N) {
int i = 0;
int j = 0;
double* result = new double[N];
for(int k = 0; k < N; k++) {
if ((i < len(b)) && (j >= len(c) || b[i] <= c[j])) {
result[k] = b[i++];
} else {
result[k] = c[j++];
}
}
return result;
}
void merge_sort(double* a, int N) {
if (N >= 2) {
int mid = (N+1)/2;
double *left = new double[mid];
double *right = new double[mid];
for (int i = 0; i < mid; i++) {
left[i] = a[i];
}
for (int j = 0; j < mid; j++) {
right[j] = a[mid + j];
}
merge_sort(left, mid);
merge_sort(right, mid);
a = merge(left, right, N);
}
}
Any help would be really appreciated.
In the last line, you assign your result to the local var a, which is then lost. You need to return a, or pass the input as a reference/pointer, otherwise any changes are only to the local copy.
Arguments in the function are basically local variables, they behave like any local variable in this function, except their initial value is set by code that calls this function. a is a pointer that stores the address of first element of your double array.
As it's a local variable, you can modify it but when the function ends, it will be discarded like all other local variables of the function.
There are several ways to deal with this problem, each with their own up and downsides. The most obvious is to return final value of a when you're done sorting. You could also pass a pointer TO a pointer to this function, and then you would be able to modify the pointer outside the function:
void function(int** argument){
*argument = another_function();
}
, but that severely restricts the source of your input. It no longer could be a local array passed by address like this:
int x = 10;
int *y = &x; // if this is what you want to change
function(&y); // this works
// now x is still 10, y points to a different place in memory which can store a different value
int x[1]; // if you would like to change this array in place though...
function(x); // this is how you would call the function, but it would fail because it can't change the address that x refers to
You main issue is here:
// You pass in a pointer to the data here.
// the parameter `a` holds a pointer to the data.
void merge_sort(double* a, int N) {
if (N >= 2) {
// STUFF
// Here you write over `a` (which is fine)
// BUT: You don't pass the value back.
// So the caller never knows what the new value is.
a = merge(left, right, N);
}
}
To fix this. I think it is a mistake to allocate a new array in merge(). Rather re-use the array you have. You have already copied the data into left and right to be sorted. The merge should merge the data back into the original array a.
// Change this:
a = merge(left, right, N);
into
merge(a, left, right, N);
Now in merge() you can use a as the destination.
void merge(double* result, double* b, double* c, int N)
// No longer need to allocate space for result now.
There are a couple of other issues:
1: What do you need len() for?
int len(double *a) {
int count = 0;
while (a[count] != '\0') {
count++;
}
return count;
}
You should already know the length of all parts you should not be re-measuring it. Also this function is completely wrong (the double array is not \0 terminated).
2: The length of b and c is not obvious.
double* merge(double* b, double* c, int N) {
You get the wrong value because you call len() which is not correct.
You could calculate from N but that has issues in that you need to make sure both you merge functions use exactly the same method and that is error prone in the long run. I would personally pass the size of each array as parameters to the function.
3: You leak your intermediate arrays!
You call new to allocate storage.
double *left = new double[mid];
double *right = new double[mid];
But you don't deallocate these objects so they are leaked (for every call to new there should be a corespodning call to delete).
Overall. You can solve a cople of issues by using more C++ style techniques (rather than the C style you are using). Iterators and std::vector spring to mind.
I am trying out some codes that is based on finding all possible combinations that add up to a integer's value that is declared in the main function. However, the problem is when I call the function "findCombinations(n);", it gives an error at "int arr[n];". That is the only line which has an error which is stopping me from running the program. If you know of a solution, do let me know.
#include <iostream>
using namespace std;
void findCombinationsUtil(int arr[], int index,
int num, int reducedNum)
{
// Base condition
if (reducedNum < 0)
return;
// If combination is found, print it
if (reducedNum == 0)
{
for (int i = 0; i < index; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// Find the previous number stored in arr[]
// It helps in maintaining increasing order
int prev = (index == 0) ? 1 : arr[index - 1];
// note loop starts from previous number
// i.e. at array location index - 1
for (int k = prev; k <= num; k++)
{
// next element of array is k
arr[index] = k;
// call recursively with reduced number
findCombinationsUtil(arr, index + 1, num,
reducedNum - k);
}
}
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
int arr[n];
//find all combinations
findCombinationsUtil(arr, 0, n, n);
}
int main()
{
int n = 10;
findCombinations(n);
return 0;
}
C-style array dimensions must be known at compile-time in Standard C++.
You can make n be a compile-time function parameter like this:
template<int n>
void findCombinations()
{
// array to store the combinations
// It can contain max n elements
int arr[n];
//find all combinations
findCombinationsUtil(arr, 0, n, n);
}
int main()
{
const int n = 10;
findCombinations<n>();
return 0;
}
From http://www.cplusplus.com/doc/tutorial/arrays/:
NOTE: The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.
While some compilers will allow it, you should avoid dynamic size arrays.
Here are a few options:
If the size of the array will always be 10, initiate it to hard-coded const 10.
Use std::shared_ptr to an array pointer:
std::shared_ptr pArray;
pArray=std::make_shared(n)
Use std::vector to dynamically allocate the size. (IMHO this is the preferred option).
use c-style pointers (IMHO should only be used as last resort)
Template class (wasteful, as it created and compiles many instances of the same function)
Type of variable arr must be known at compile time. If you need storage of variable size, you have to allocate it.
Possible alternative (one of many)
#include <vector>
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
std::vector<int> arr(n); // allocate n elements
//find all combinations
findCombinationsUtil( &*arr.begin(), 0, n, n);
}
if compiler at least partially complies to C++11 e.g. it's late gcc 4.6 or higher or VS2010 and higher, then there is method data() that returns pointer to internal storage. But better to rewrite, templatize or overload findCombinationsUtil to use a container or iterator
Hello Im trying to fill my array with random numbers from 1 to 50 using a pointer. When I try to do this the program crashes.
This is the declaration.
populate(arraySize, numArray);
and the code
void populate(int size, int *ptr)
{
int counter = 0;
srand(unsigned(time(0)));
while (counter < size++)
{
ptr[counter] = (rand() % 50) + 1;
counter++;
}
}
There are no errors with the code and it runs it just crashes when this method is called
srand(unsigned(time(0)));
void populate(int size, int *ptr)
{
int counter = 0;
while (counter < size)
{
ptr[counter] = (rand() % 50) + 1;
counter++;
}
}
Remove the size++ and change it to size.
Another solution would be
int randomNumber () { return (std::rand()%50 +1); }
void populate(int size, int * ptr)
{
std::srand ( unsigned ( std::time(0) ) );
std::generate (ptr,ptr+size-1, randomNumber);
}
It is assumed that prior to call this function, user much do some range validation.
I guess you are trying to iterate through the array. You wrote counter < size++, which means incrementing size (I guess it's the variable that's supposed to hold the number of items) after checking for counter < size. The ++ operator does not give you another value that equals size + 1; instead, it increments size the same way size = size + 1 does. So size will increase the same time counter increases, and the index will eventually go out of bounds, and the program will crash when trying to write to that location.
Plus, as of srand, you only need to call it once (e.g. in your main()).
I'm trying to find and fix what is wrong with this code. It's a binary search implemented by recursion. I dont know why it's returning stack overflow and crashing.
bool find( const int x, const int* pBegin, const int* pEnd)
{
int medel = (*pBegin +(( *pEnd-1) - *pBegin)/2) ;
if(x == medel)
return true ;
else if( x > medel)
{
int begin = (medel +1);
return find (x, &begin, pEnd);
}
else if( x< medel)
{
int last = (medel-1);
return find(x,pBegin, &last);
}
}
void main()
{
int arr[10];
for (int i=0;i<10;++i)
arr[i] = i;
bool hittat = find(7, &arr[0], &arr[9]);
cout << "hittat = " << hittat << endl;
system("pause");
}
When I debug the code, I see that when the function "find" is called it takes weird arguments, like in this pic.
It should take 0 and 9, not these huge numbers :/
Is there anything wrong with my pointers?
You should compute the average of the pointers and check what it's the value of the element hallway between them. Instead you compute the average of the values pointed by them which is significantly different.
You're using medel (I'm assuming that should be middle) as a pointer to an int in some places, but as an int in others.
Try declaring it like this:
const int* middle = pBegin + (pEnd - pBegin + 1) / 2;
Then, when you want to access what is stored there, use *medel.
Also, you'll need a second terminating condition (for when it won't be found). Something like:
if (((middle == pEnd) && (x > *middle)) ||
((middle == pBegin) && (x < *middle))) {
// Terminating condition
return false;
}
You are mixing pointer on int and int with your medel, just set it to be a pointer and access his data with *medel
The problem shown in your picture looks like it was taken from your original code as seen in a prior question. There you had pEnd pointing past the end of an array, so that dereferencing it was not allowed (and yields weird values).
That should not occur with the code as posted.
Your current code only uses pointers to valid integers. But most of those don't point into your array, so what you do is not a search in your array. The program simply does calculations with integers. Only the values of the first and last element of your array are ever used.
The program is confusing, because you pass around the integer values as pointers to their storage. While you start with pointers into your array, you then mix in pointers to automatic variables (beginand end), where you have stored a calculated value. (You never use pointers to array elements other than the first and last.
my aim is to reverse an array 3,12,2,1 to 1,2,12,3. when i run this code i get garbage before my actually result. i can't seem to see where the problem is please assit
#include<iostream>
using namespace std;
int rev (int arr[], int a){
//int r;
for(int i =a-1; i>=0; i--){
cout<<arr[i]<<" ";
}
return 0;
}
int main(){
int arr[] = {6,41,12,5,2};
cout<<"The rev of {6,41,12,5,2}"<<endl;
cout<<rev(arr, sizeof(arr))<<endl;
system("pause");
return 0;
}
Use sizeof(arr)/sizeof(arr[0]) instead of sizeof(arr).
sizeof(arr) gives the total size of the array. sizeof(arr[0]) is the size of one array element (all elements have the same size). So sizeof(arr)/sizeof(arr[0]) is the number of elements.
An optimized answer to the question would be using reverse () from STL if you are allowed to use it:
std::reverse
http://www.sgi.com/tech/stl/reverse.html
int main()
{
int arr[] = {6,41,12,5,2};
cout<<"The rev of {6,41,12,5,2}"<<endl;
reverse(arr, arr + 5);
copy(arr, arr + 5, ostream_iterator<int>(cout, ", "));
}
sizeof return the size in bytes. In your example, if sizeof(int) = 4, it returns 20.
Because you're using an array, you have to keep the size of the array handy as well. sizeof computes the size of a value in memory, in this case the size of all the memory used to represent arr. You can do sizeof(arr)/sizeof(int) to get the number of elements in an array. This makes sense because it's taking the total size of the array and dividing it by the size of an element in the array. Beware however that this only works for arrays (int arr[4] = {6,41,12,5,2};). If it's a pointer to a heap-allocated array via something like int* i = new int[4]; you'll need to keep the size of the array hanging around.
Also, you're calling your reverse function from within a cout<< call, which will print the function's return value (in this case it's hard-coded to 0).
It also turns out there is a function in the C++ standard library (std::reverse) that can do this.
If I may speak subjectively and in an off-topic manner about your approach, it is very un-C-like. My personal favorite way to reverse an array goes like this:
void reverse(int *a, int n)
{
int *p = a, *q = a + n - 1;
while (p < q)
{
int swap = *p;
*p++ = *q;
*q-- = swap;
}
}
// Usage:
int a [] = { /* ... */ };
reverse(a, sizeof(a)/sizeof(*a));
Of course, since your question is tagged c++, there's always std::reverse().
Sizeof operator return the one extra (arrayLength + 1) here 6 will return when passs 6 it store in a when a-1 you get 5 but array index start from 0 length-1 that from 0 to 4 here i pointing to index 5 that is not last element last+1 that why you got garbage value