Implementing Merge Sort - c++

So, I am trying to implement merge sort, which I conceptually understand but am obviously having great difficulty programming (I'm quite inexperienced). I have looked up previous posts which has helped, but I can't get past this point. I am currently having the following errors :
13:20: error: âSizeâ was not declared in this scope
mergesort(array[Size], low, mid);
41:20: error: invalid conversion from âintâ to âint*â [-fpermissive]
mergesort(data[size], 0, size-1);
6:6: error: initializing argument 1 of âvoid mergesort(int*, int,
int)â [-fpermissive] void mergesort(int array[], int low, int high)
I am also very confused on how to proceed in general. I really don't know how to merge everything back together either. This did not seem like it would be nearly this difficult, but recursion really confuses me :/ Thanks for your help in advance.
#include <iostream>
using namespace std;
void merge(int[], int, int, int);
void mergesort(int array[], int low, int high)
{
int mid;
if(low < high)
{
mid = low + (high-low)/2;
mergesort(array[Size], low, mid);
mergesort(array[Size], mid+1, high);
merge(array[Size], low, mid, high);
}
}
void merge(int array, int low, int mid, int high)
{
}
int main()
{
int size;
cin >> size;
int data[size];
for(int i = 0; i < size; i++)
{
cin >> data[i];
}
mergesort(data[size], 0, size-1);
}

data[Size] attempts to get the Sizeth value from the array data. Size doesn't exist, and I don't think this is what you want. If you want to refer to the array itself, just use it's name: data.
You have the same problem later on with data[size], except size does exist in this case. The error message is telling you that it can't convert an int to an int*. When you declare a function parameter like int array[], it is actually just syntactic sugar for int* array. You are passing data[size] to this parameter, which attempts to access an int from data (although size is outside the bounds). Hence, the compiler does not know how to convert an int to a int* - they're different types.
Note that the following code is not standard C++, because variable-length arrays are not supported:
int size;
cin >> size;
int data[size];
That is, the size of an array needs to be known at compile-time, which size is not. You could instead use std::vector<int> data(size);.
Also, your declaration and definition for merge don't match - one takes an int as its first parameter, while the other takes int[].

It seems you are having difficulties understanding static arrays vs dynamic arrays.
I would suggest using std::vector instead of your data[size] declaration .
Regarding your errors :
Note that inside your mergesort function you are referring to Size which isn't defined . If you want to go with static array, I would suggest the following :
#define SIZE 200
...
int data[SIZE];
This will allow you to use the same SIZE thorughout the code.
However your array won't be the size of your input .
If you want to allocate an array at runtime , you need to change your code from
int size;
cin >> size;
int data[size];
To
int size;
cin >> size;
int* data = new int[size];
Then , in your mergesort function, you will have to pass the size as parameter.

Related

I am getting this strange compilation error in C++

I was doing the Coin change problem, I am trying to do it using Dynamic Programming. But I am getting this compilation which I don't quite understand. Someone told me that I have to assign the 'dp' array dynamically, but he was not sure why. PLease explain this concept .
#include<bits/stdc++.h>
using namespace std;
int solve(int *d, int size, int n , int ** dp){
if(n==0)
return 1;
if(n<0)
return 0;
if(size == 0)
return 0;
if(dp[n][size]>-1)
return dp[n][size];
int x = solve(d,size,n-d[0],dp);
int y = solve(d+1, size - 1, n, dp );
dp[n][size] = x+y;
return x+y;
}
int countWaysToMakeChange(int denominations[], int numDenominations, int value){
int dp[value+1][numDenominations+1];
memset(dp, -1, sizeof dp);
return solve(denominations, numDenominations, value, dp );
}
Error :
Compilation Failed
In file included from Runner.cpp:3:0:
Solution.h: In function 'int countWaysToMakeChange(int*, int, int)':
Solution.h:28:60: error: cannot convert 'int (*)[(numDenominations + 1)]' to 'int**' for argument '4' to 'int solve(int*, int, int, int**)'
return solve(denominations, numDenominations, value, dp);
^
Here is my Main file code:
#include<iostream>
using namespace std;
#include "Solution.h"
int main(){
int numDenominations;
cin >> numDenominations;
int* denominations = new int[numDenominations];
for(int i = 0; i < numDenominations; i++){
cin >> denominations[i];
}
int value;
cin >> value;
cout << countWaysToMakeChange(denominations, numDenominations, value);
}
There are two problems in the code.
First, in the function int countWaysToMakeChange(int denominations[], int numDenominations, int value)
int dp[value+1][numDenominations+1];
is illegal. Array bounds must be compile-time constants. Some compilers allow this sort of things as an extension (and it's legal in C), but it is not valid C++.
Second, the type of dp is "array of array of int". It is not a "pointer to pointer to int", and the compiler is complaining that it can't make that conversion when the code tries to pass dp as the fourth argument to solve.
Arrays are confusing. In most contexts, the name of an array decays into a pointer to its first element. That's why you can write code like this:
void f(int*);
void g() {
int array[20];
f(array);
}
Since dp is an array, its name decays into a pointer to its first element. But this is where it's easy to get lost: as I said earlier, the type of dp is "array of array of int"; when its name decays, the resulting type is "pointer to array of int".
If you want to pass dp to solve, solve has to take the same type: "pointer to array of int". But since you don't know the size of that array when you write solve you can't write that type in the argument list.
That's one reason why multi-dimensional arrays are often represented as one-dimensional arrays, with code to convert the two dimensions into one. The offset is x * width + y, or some minor variant on that. When you do that, your two-dimensional array becomes a one-dimensional array, and its name decays into a pointer to its first element, so you can pass it to a function that expects int*.

Is there a way to fix this error : no match for 'operator[]' (operand types are 'empl' and 'int')

Im getting homework done but i faced this problem i tried everything changing variables name, changing function ....
I looked into this problem on google still no idea how to fix this error.
#include<stdio.h>
#include<iostream>
struct empl {
char nom;
char pre;
float salaire;
double cin;
}empl;
struct empl t[50];
struct empl E;
int taille(int n)
{
printf("saisie la taille de tableaux\n");
scanf("%d\n", &n);
return 0;
}
int remplire(int n, struct empl t, int i)
{
for (i = 1; i <= n; i++)
{
printf("t[%d].nom= ", i);
scanf("%s\n", &t[i].nom);
printf("t[%d].prenom= ", i);
scanf("%s\n", &t[i].pre);
printf("t[%d].salaire= ", i);
scanf("%f\n", &t[i].salaire);
printf("t[%d].CIN= ", i);
scanf("%lf\n", &t[i].cin);
}
}
int main()
{
int i, n;
int taille(int n),
taille(n);
int remplire(int n, struct empl t, int i);
remplire(n, t, i);
}
Although your code is written mostly in C style, you seem to be compiling it with a C++ compiler, as it accepts #include <iostream> (though you do not appear to use anything from it), and it has a notion of operator overloading. C and C++ are distinct languages, and the distinction is somewhat relevant here.
In either language, however, the code you have presented is flawed. The problem is with the several expressions in function remplire that follow this pattern: &t[i].nom. Absent any operator overloading (which is not available in C anyway), the [] operator in those expressions requires one of its operands to designate either a pointer or an array, and the other to designate an integer. Although there is a file-scope variable t that is an array, inside remplire() that is shadowed by a function parameter with the same name. Inside that function, then, t refers the the parameter, which is a struct empl, not an array or pointer (or integer).
Your compiler ought to be giving you another clue, too, where you call that function ...
remplire(n,t,i);
..., passing the global t as an argument. The compiler very much should complain about a type mismatch between the second argument (t) and the corresponding function parameter.
Perhaps what you wanted to do is simply to declare remplire() to accept a structure pointer as its second parameter:
int remplire(int n, struct empl *t, int i)
While you're at it, do remove the redundant local declaration of that function inside main(). You don't need that as long as remplire() is defined before main(), and if you want to have a separate declaration of that function then it would best be placed at file scope, and probably in a header file.
First of all iostream is C++ header coming from standard library and will not work for C program. And now issues:
int taille (int n)
{
printf("saisie la taille de tableaux\n");
scanf("%d\n",&n);
return 0;
}
This function is called with an input parameter - that means you can pass a value into a function, but not access the parameter and hope it will be used in other places. To correct this you should declare the function should look like this:
int taille (int * n)
{
printf("saisie la taille de tableaux\n");
scanf("%d\n", n);
return 0;
}
Next function - similar problem, it should look like this:
int remplire (int n , struct empl * t ,int i)
{
for (i=1;i<=n;i++)
{
printf("t[%d].nom= ",i);
scanf("%s\n",&t[i].nom);
printf("t[%d].prenom= ",i);
scanf("%s\n",&t[i].pre);
printf("t[%d].salaire= ",i);
scanf("%f\n",&t[i].salaire);
printf("t[%d].CIN= ",i);
scanf("%lf\n",&t[i].cin);
}
}
Or even like this:
int remplire (int n , int i)
as t is global variable. Also this function should return some value as it is declared to return int.
And now the main function:
int main()
{
int i,n;
int taille(int n),
taille(n);
int remplire(int n,struct empl t,int i);
remplire(n,t,i);
}
Don't redeclare functions inside another function, even if it is permissible it does not mean you should do it. Also main function should return 0 if everything works fine. To correct the function write it like this:
int main()
{
int i,n;
taille(& n);
remplire(n,& t,i);
}
Some good advice, please read some books to learn how to program in C if you want to go that way.
There are many issues in your code.
Starting reading a good C textbook is advised.
You probably want this:
#include <stdio.h>
#include <iostream>
struct empl {
char nom[30];
char pre[30];
float salaire;
double cin;
}empl;
struct empl t[50];
struct empl E;
int taille(int & n)
{
printf("saisie la taille de tableaux\n");
scanf("%d", &n);
return 0;
}
void remplire(int n, struct empl *t)
{
for (int i = 0; i < n; i++)
{
printf("t[%d].nom= ", i);
scanf("%s", &t[i].nom);
printf("t[%d].prenom= ", i);
scanf("%s", &t[i].pre);
printf("t[%d].salaire= ", i);
scanf("%f", &t[i].salaire);
printf("t[%d].CIN= ", i);
scanf("%lf", &t[i].cin);
}
}
int main()
{
int n;
taille(n);
remplire(n, t);
}
It's still poor code and it's written mostly in C style, but it compiles and works as intended.
In C++ you'd do this totally differently.
You've declared this global array variable t
struct empl t[50];
and also declared a parameter t in this function
int remplire (int n , struct empl t ,int i)
Inside the function it's going to treat any instance of t as to be the parameter as that is nearer in scope than the global variable. So when you have code like this...
scanf("%s\n",&t[i].nom);
...it's going to throw up errors because t isn't an array.
The solution is to use variable names that have meaning like "employee_array" rather than single letters.
Also that call to scanf is wrong as for strings you don't need to pass in a pointer to the variable, so it should look like
scanf("%s\n",t[i].nom);
But you'd also need to make nom be a string too - currently it's only a char.

What is the difference between A and A[] in function parameter?

//function prototype at the top
void fillRandArray(int A[], int number, int maxNum);
//function declaration
void fillRandArray(int* A, int number, int maxNum) {
for(int i = 0; i < number; i++) {
A[i] = rand() % maxNum + 1;
}
}
int A[MAX_STUDENTS];
fillRandArray(A, number, 44);
I dont understand the code, so the prototype set int A[]
then the declaration set int* A
when we pass the argument, shouldn't we pass like this...
fillRandArray(A[MAX_STUDENTS], number, 44); <---- ???
The code below is passing the name of an array, which is an address.
void fillRandArray(int A[], int number, int maxNum);
The code below this is passing just the name of an address, which happens to be A in this case. They are basically doing the same thing.
void fillRandArray(int* A, int number, int maxNum)
You would not pass the argument like the following:
fillRandArray(A[MAX_STUDENTS],..., ...);
because you told the compiler to expect an address, not an element of the array. So you would just pass it A (i.e. the name of array, which is also the starting address). So it would look like this:
fillRandArray(A, number, 44);
Ask more questions, if I didn't explain it well enough.
The problem is that C-style arrays can't be passed as arguments
to a function. When you write int a[] as a parameter in
a function, the compiler translates it to int* a. In
addition, if you provide a dimension (e.g. int a[10]), it is
simply ignored.
Also, an array can convert to a pointer, and will do so in a lot
of contexts. This is what happens in fillRandArray(A, number,
44); the array A is implicitly converting to a pointer.
As for fillRandArray(a[MAX_STUDENTS], number, 44), this
indexes into the array for the first element; with your
declaration, it passes an int (not an array or a pointer),
except that it accesses one beyond the end of the array, so it's
undefined behavior.
In general, you want to avoid this (although with main, you
can't): the function should either take an std::vector<int>&
a, or in a few special cases, an int (&a)[N] (in which case,
the function should be a template, and N be a template
parameter). So you might write:
template <size_t N>
void fillRandArray( int (&a)[N], int maxNumber )
{
for ( int i = 0; i != N; ++ i ) {
a[i] = rand() % maxNum + 1;
}
}
(But for this sort of thing, std::vector is far preferrable.)

cannot display the result of each one of my function

I wrote a code that computes the sum of components of an array which is randomly filled with values between 0 and 1. I have to write two functions, one is iterative, and the other one is recursive. Both should do the same work. The two functions I wrote work fine when I call only one at the time. However, if i try to call the two functions in the main, I can see the result of one only, but cannot see the result from the other one. In addition, my recursive function tends to get called one extra time. I have noticed that if I put getch() as comment in recursive_function(). I know I am missing something, but I cannot figure that out. Thanks for your help. here is the code. i am using Dev-C++.
#include <iostream>
#include<conio.h>
#include <stdlib.h>
using namespace std;
//headers of the thre functions
int random_value(int array[], int size);
int iterative_function (int array[], int size, int sum);
int recursive_function ( int size, int array[], int index, int sum);
int main()
{
int size;int array[size]; int sum=0;
int index=0;
cout<<"enter the size of the array"<<endl;
cin>>size; //enter the size ofthe array...
random_value(array, size);
iterative_function (array, size, sum);
recursive_function ( size, array, index, sum);
getch();
return 0;
}
int random_value(int array[], int size)
{ cout<<"here is the value returned by rand()"<<endl;
for(int i=0;i<size;i++)
{ array[i]=( rand() % (0-2));
cout<<array[i]<<endl;
}
}
int iterative_function (int array[], int size, int sum)
{
int i,j, number, value; i=0;
cout<<"from the iterative function"<<endl;
cout<<"------"<<endl;
for(i=0;i<size;i++)
sum=sum+array[i];
cout<<"sum of the array="<<sum<<endl;
getch();
return 0; //exit the function. Program terminated succesfully.
}
int recursive_function ( int size, int array[], int index, int sum)
{
if(size>index)
{
sum=sum+array[index];
index++;
recursive_function( size, array, index, sum);
}
cout<<"from the recursive function"<<endl;
cout<<"------"<<endl;
cout<<"new sum= "<< sum<<endl;
getch();
return 0;
}
#include <iostream>
#include<conio.h>
<conio.h is not a standard header, i.e. it is not available with all compilers, and you don't need it.
To see the result output of your program:
run it from the command line, or
in Visual Studio run it via keypress [Ctrl F5] (no debugging), or
set a breakpoint on the closing brace of main, and run it under a debugger (in Visual Studio e.g. via keypress [F5]).
#include <stdlib.h>
As far as I can see you’re not using anything from this header. However, it does provide the symbolic constants EXIT_SUCCESS and EXIT_FAILURE, which are intended for return statement in main. E.g., it can be more clear to write EXIT_SUCCESS there than to write 0, because many folks misunderstand what 0 means in this context.
using namespace std;
This is OK for a short program or within a namespace.
However, keep in mind that short programs very often end up as not-so-short programs.
And then a using namespace std; can easily cause name collisions, in particular with the name std::distance.
//headers of the thre functions
int random_value(int array[], int size);
int iterative_function (int array[], int size, int sum);
int recursive_function ( int size, int array[], int index, int sum);
Although it is partly a matter of preference, there is no advantage in forward-declaring the functions before main, it is more work, and it sometimes causes problems when the forward declarations don’t quite match the definitions – as with any unnecessary redundancy, violations of the DRY principle (Don’t Repeat Yourself).
Instead, just place the function definitions before main.
That way it is also much easier to see what refers to what, because functions that are used by others then necessarily come before those other functions.
int main()
{
int size;int array[size]; int sum=0;
This should not compile, because in C++ only a dynamically allocated array can have a size that is unknown at compile time.
However, C99 supports “variable length arrays” a.k.a. VLAs with the above syntax, and as a language extension the g++ compiler supports that.
On the third and gripping hand, even with the g++ language extension the above declares an array of indeterminate length, because the size variable has not been initialized and has an indeterminate value.
With the g++ compiler that value is most likely 0, but it can easily be any other value.
To turn off the g++ VLA language extension, and some other language extensions, use the following g++ options:
-pedantic -std=c++0x -Wall
For standard C++, instead of a C99 VLA you should use a C++ std::vector<int>.
In order to get a declaration of the std::vector class template, include the standard library header <vector>.
int index=0;
cout<<"enter the size of the array"<<endl;
cin>>size; //enter the size ofthe array...
When you're using a std::vector, then here, knowing its size, would be the place to declare that vector.
Or, if declared earlier, here would be the place to resize it.
random_value(array, size);
This would better be a function that returned a vector of random values.
You would then use that to initialize the declared vector.
iterative_function (array, size, sum);
recursive_function ( size, array, index, sum);
getch();
Regarding the getch() call, see the above comments about <conio.h>.
return 0;
Regarding the value 0 here, see the above comments about <stdlib.h>.
}
int random_value(int array[], int size)
{ cout<<"here is the value returned by rand()"<<endl;
for(int i=0;i<size;i++)
{ array[i]=( rand() % (0-2));
Here you have Undefined Behavior, accessing elements of a possibly zero-size array.
cout<<array[i]<<endl;
}
}
int iterative_function (int array[], int size, int sum)
{
int i,j, number, value; i=0;
cout<<"from the iterative function"<<endl;
cout<<"------"<<endl;
for(i=0;i<size;i++)
sum=sum+array[i];
Here you are again invoking Undefined Behavior, often called just “UB”, by accessing non-existing array elements.
In addition, even if the array had been of non-zero size, it has not been initialized and so would contain just zeroes or arbitrary values (by the Holy Standard called “indeterminate values”).
cout<<"sum of the array="<<sum<<endl;
getch();
See the above comment about <conio.h>.
return 0; //exit the function. Program terminated succesfully.
}
There is no point in letting the above function always return the same value. From an information-theoretical perspective, that return value carries zero bits of information. Instead just let the function’s result value be void.
int recursive_function ( int size, int array[], int index, int sum)
{
if(size>index)
{
sum=sum+array[index];
index++;
recursive_function( size, array, index, sum);
}
Instead of incrementing the index, which is non-idiomatic and therefore difficult to spot for experienced readers, just use index + 1 in the recursive call.
It is a good idea to add const to just about every declaration where it is possible.
That would, for example, have forced you to use index + 1. :-)
cout<<"from the recursive function"<<endl;
cout<<"------"<<endl;
cout<<"new sum= "<< sum<<endl;
getch();
See the above comment about <conio.h>.
return 0;
See the above comment about function always returning the same value.
}
Summing up, with all the Undefined Behavior it is just happenstance if things appear to work.
Fix the UB's (in particular replace C99 VLA with std::vector) first of all, then perhaps ask new question if it still does not work as it should. ;-)
You create your array using size but it's initialized AFTER that. You simply get random stuffs...
Declare int pointer, read size, allocate the array with new then try again (do not forget to delete).
First of all the array that you've declared is of unknown size, declare the array after getting input for size
Remember that in recursive_function() it calls itself many times - and every time it is called (either by main() or by itself) it will run all commands in its body (since you never return early)... now can you see a problem with the getch() in there?

swapping 2 items in an array, but not passing it by reference

void swap(int a[], int size){
...............
}
int main(){
int x[4] = {4,5,3,12} ;
swap(x,4) ;
// print array here - some elements are swapped
}
So I'm not sure how it is possible for the swap-function to change the order of elements
since it is passed by value in void swap?
If I do something like this: void swap( int (&a)[], int size)
then the original array in my main function would get changed, but how does swap function swap elements, if it just copies the array, and hence should not make any effect on the array in main?
Arrays are not copied when passed as a function arguments. They are "decayed" (automatically converted) to pointers to appropriate first elements. So this code
void swap(int a[], int size) { ... }
is equivalent to
void swap(int* a, int size) { ... }
which should now explain the behavior observed.
(And if indeed you want to prevent that conversion, pass the array by reference).
In C and C++, when you pass an array to a function, you are actually only passing its address (yes, by value, but of course that doesn't change anything since an address passed by value or not always points to the same location).
In the function, whatever element of the array you access or change would be the original one.
So basically, your answer is that you got everything right and no need to do anything.
Example:
void swap(int a[], int size){
for (int i = 0; i < size/2; ++i)
{
a[i] ^= a[size-1-i]; // If you are interested
a[size-1-i] ^= a[i]; // try to understand
a[i] ^= a[size-1-i]; // how this works
}
}
int main(){
int x[4] = {4,5,3,12} ;
swap(x,4) ;
// print array here - some elements are swapped
}
The array is not passed by value, it decays into an int*. Check this code:
void swap(int a[], int size){
}
void swap(int* a, int size){
}
int main()
{
}
Now see what the compiler says:
$ g++ -Wall test.cpp
test.cpp: In function ‘void swap(int*, int)’:
test.cpp:4:6: error: redefinition of ‘void swap(int*, int)’
test.cpp:1:6: error: ‘void swap(int*, int)’ previously defined here
It works because you are not passing the array by value. Passing an array to a function is the same as passing a pointer to the first element in the array. Thus, you are not actually passing by value.
For this reason, I recommend using the more obvious notation:
void swap(int* a, int size)
You would use the double pointer:
void swap(int** a, int size)
or
void swap(int & a[], int size)
only if you want the function to change the memory address of the original array.
i.e. You reallocate the memory and want the caller to receive the new array. Of course, in this case you would probably cause a nasty leak.
If you want to enforce call by value behavior then make the argument const.
void swap(const int* a, int size)
This will prevent the method from being allowed to alter the array in any way. This is useful when you are passing a video buffer or something to a user but you do not want them to corrupt the data.