Related
I want to find the number within a range in an array and must be in a recursive way. The function variables couldn't be modified.
Let's say in the range of 2 and 3
The input is : int a[] = {4, 1, 3, 1, 3, 2};
and the output will be = {3,3,2} , 3 found
Not sure how to code the recursive function in this case. The below I have tried not working.
int within(int a[], int N, int lower, int upper, int result[])
{
if(N == 1 && N <= upper && N>= lower)
return a[0];
return within(&a[1], N-1, lower, upper, result);
}
int main()
{
int a[] = {4, 1, 3, 1, 3, 2};
int result[6] = {0};
int i, nResult;
nResult = within(a, 6, 2, 3, result);
printf("%d data passed the bounds\n", nResult);
for (i = 0; i < nResult; i++){
printf("%d ", result[i]);
}
printf("\n");
return 0;
}
I want to find the number within a range in an array
Let's say in the range of 2 and 3
Normally a for loop or similar would be so much easier here
If it has to be recursive....
// need to have another number - r - number in range
// r starts at zero
//
// normally lower case for variable and capitals for things you #define
// N starts at the number of elements of a less one
//
int within(int a[], int N, int lower, int upper, int r, int result[])
{
if(a[0] <= upper && a[0]>= lower) {
result[r]= a[0];
r++;
}
if(N==0) {
return r;
} else {
r = within(&a[1], N-1, lower, upper, r, result);
return r;
}
}
the function will give a return value of the number of values found within the range.
The code above is recursive, but so much more complicated and fragile than a simple loop... such as the fragment below
for (i=0;i<N;i++) {
if(a[i] <= upper && a[i]>= lower) {
result[r]= a[i];
r++;
}
}
If it has to be recursive wihtout r...
// need to have another number - result[0] - number in range
// result[0] starts at zero
//
// normally lower case for variable and capitals for things you #define
// N starts at the number of elements of a less one
//
int within(int a[], int N, int lower, int upper, int result[])
{
if(a[0] <= upper && a[0]>= lower) {
result[0]++;
result[result[0]]= a[0];
}
if(N==0) {
return result[0];
} else {
result[0] = within(&a[1], N-1, lower, upper, result);
return result[0];
}
}
now result conatins
{number in range, first number in range, second number in range....}
Something like this. If you want to implement a recursive function, try to do it in the way that the recursive call happens at the end.
#include <stdio.h>
int find_in_range(int* out, int const *in, int length, int from, int to)
{
if (length == 0)
{
return 0;
}
int addon;
if (*in >= from && *in <= to)
{
*out = *in;
++out;
addon = 1;
}
else
{
addon = 0;
}
return find_in_range(out, in + 1, length - 1, from, to) + addon;
}
#define N 6
int main()
{
int in[N] = {4, 1, 3, 1, 3, 2};
int out[N] = {0};
int num_found = find_in_range(out, in, N, 2, 3);
for (int i = 0; i < num_found; ++i)
{
printf("%d ", out[i]);
}
printf("\n");
return 0;
}
You can modify the following code as per your requirements. This is just a proof of concept code:
#include <stdio.h>
#include <stdlib.h>
static int result[4];
static int ctr1 = 0;
static int ctr2 = 0;
void recFind(int* arr, int* key){
if(ctr2 == 8)
return;
if(*arr >= key[0] && *arr <= key[1])
result[ctr1++] = *arr;
arr++;
ctr2++;
recFind(arr, key);
}
int main(){
int arr[] = {1,3,3,6,4,6,7,8};
int key[] = {1,4};
recFind(arr, key);
printf(" { ");
for(int i = 0; i < 4; i++){
printf("%d ", result[i]);
}
printf("}\n");
}
As it follows from the description of the assignment the function should provide two values: the number of elements that satisfy the condition and an array that contains the elements themselves.
It is evident that the array should be allocated dynamically. And it is logically consistent when the function itself returns the number of elements while the pointer to the generated array is passed by reference as an argument.
The recursive function can look the following way
#include <stdio.h>
#include <stdlib.h>
size_t get_range( const int a[], size_t n, int lower, int upper, int **out )
{
size_t m;
if ( n )
{
m = get_range( a, n - 1, lower, upper, out );
if ( lower <= a[n-1] && a[n-1] <= upper )
{
int *tmp = realloc( *out, ( m + 1 ) * sizeof( int ) );
if ( tmp )
{
tmp[m] = a[n-1];
*out = tmp;
++m;
}
}
}
else
{
*out = NULL;
m = 0;
}
return m;
}
int main(void)
{
int a[] = { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
const size_t N = sizeof( a ) / sizeof( *a );
int lower = 2, high = 3;
int *out;
size_t n = get_range( a, N, lower, high, &out );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", out[i] );
}
putchar( '\n' );
free( out );
return 0;
}
The program output is
2 3 3 2
Below codes will work for you in recursive way. If you don't want to print the numbers just comment out printf statement inside function printfRange. Hope you can understand the logic :-
int within(int *a, int rngH, int rngL, int length)
{
int len = length;
static int i = 0;
static int found = 0;
if(len <=0 )
{
return i;
}
if (*a == rngH)
{
printf("%d,",*a);
i++;
found = 1;
within(++a,rngH, rngL,--len);
}
else if(*a == rngL && found > 0)
{
printf("%d,",*a);
i++;
within(++a,rngH, rngL,--len);
}
else
{
within(++a,rngH, rngL,--len);
}
return i;
}
int main() {
int a[] = {4, 1, 3, 1, 3, 2};
int total = within(a,3,2,6);
printf("\n");
printf("Total :%d\n",total);
return 0;
}
I've implemented the following quick-select algorithm in C using pointers instead of arrays to allow for dynamic memory allocation.
#include <stdio.h>
#include <stdlib.h>
int random(int min, int max)
{
return rand() % (max + 1 - min) + min;
}
int quickselect(int *a, int l, int k)
{
int piv = *(a+random(0, l));
int *less = malloc(sizeof(int)*l), *great = malloc(sizeof(int)*l); //allocate to the max possible size
int l_len = 0, g_len = 0;
for (int i = 0; i <= l; i++)
if (*(a+i) < piv)
*(less+l_len++) = a[i]; //set "array indice" (dereferneced pointer) and increment array len
else if (*(a+i) > piv)
*(great+g_len++) = a[i];
less = realloc(less, sizeof(int)*l_len); //re-allocate appropiate to the proper size
great = realloc(great, sizeof(int)*g_len);
if (k <= l_len)
return quickselect(less, l_len, k);
else if (k > l - g_len)
return quickselect(great, g_len, k - (l - g_len));
else
return piv;
}
int main()
{
int a[] = {5,2,6,3,7,1,0};
printf("%d", quickselect(a, sizeof(a)/sizeof(*a), 1));
return 0;
}
When run, I'm getting unexpected values ranging from the negative millions to the positive millions. The randomness of the function makes this hard to debug. Any help?
How can one iterate through order of execution?
I am developing a piece of software that have several steps to compute over some data, and i was thinking in may changing the order of those steps pragmatically so i can check what would be the best order for some data.
Let me exemplify: I have let's say 3 steps (it's actually more):
stepA(data);
stepB(data);
stepC(data);
And I want a contraption that allow me to walk thought every permutation of those steps and then check results. Something like that:
data = originalData; i=0;
while (someMagic(&data,[stepA,stepB,stepC],i++)){
checkResults(data);
data = originalData;
}
then someMagic execute A,B then C on i==0. A, C then B on i==1. B, A then C on i==2 and so on.
You can use function pointers, maybe something like the following:
typedef void (*func)(void *data);
int someMagic(void *data, func *func_list, int i) {
switch (i) {
case 0:
func_list[0](data);
func_list[1](data);
func_list[2](data);
break;
case 1:
func_list[0](data);
func_list[2](data);
func_list[1](data);
break;
case 2:
func_list[1](data);
func_list[0](data);
func_list[2](data);
break;
default: return 0;
}
return 1;
}
func steps[3] = {
stepA,
stepB,
stepC
}
while (someMagic(&data, steps, i++)) {
....
}
The key is to find a way to iterate over the set of permutations of the [0, n[ integer interval.
A permutation (in the mathematical meaning) can be seen as a bijection of [0, n[ into itself and can be represented by the image of this permutation, applied to [0, n[.
for example, consider the permutation of [0, 3[:
0 -> 1
1 -> 2
2 -> 0
it can be seen as the tuple (1, 2, 0), which in C, translate naturally to the array of integers permutation = (int []){1, 2, 0};.
Suppose you have an array of function pointers steps, then for each permutation, you'll then want to call steps[permutation[i]], for each value of i in [0, n[.
The following code implements this algorithm:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void stepA(int data) { printf("%d: %s\n", data, __func__); }
static void stepB(int data) { printf("%d: %s\n", data, __func__); }
static void stepC(int data) { printf("%d: %s\n", data, __func__); }
static void (* const steps[])(int) = {stepA, stepB, stepC,};
static int fact(int n) { return n == 0 ? 1 : fact(n - 1) * n; }
static int compare_int(const void *pa, const void *pb)
{
return *(const int *)pa - *(const int *)pb;
}
static void get_next_permutation(int tab[], size_t n)
{
int tmp;
unsigned i;
unsigned j;
unsigned k;
/* to find the next permutation in the lexicographic order
* source: question 4 (in french, sorry ^^) of
* https://liris.cnrs.fr/~aparreau/Teaching/INF233/TP2-permutation.pdf
. */
/* 1. find the biggest index i for which tab[i] < tab[i+1] */
for (k = 0; k < n - 1; k++)
if (tab[k] < tab[k + 1])
i = k;
/* 2. Find the index j of the smallest element, bigger than tab[i],
* located after i */
j = i + 1;
for (k = i + 1; k < n; k++)
if (tab[k] > tab[i] && tab[k] < tab[j])
j = k;
/* 3. Swap the elements of index i and j */
tmp = tab[i];
tab[i] = tab[j];
tab[j] = tmp;
/* 4. Sort the array in ascending order, after index i */
qsort(tab + i + 1, n - (i + 1), sizeof(*tab), compare_int);
}
int main(void)
{
int n = sizeof(steps) / sizeof(*steps);
int j;
int i;
int permutation[n];
int f = fact(n);
/* first permutation is identity */
for (i = 0; i < n; i++)
permutation[i] = i;
for (j = 0; j < f; j++) {
for (i = 0; i < n; i++)
steps[permutation[i]](i);
if (j != f - 1)
get_next_permutation(permutation, n);
}
return EXIT_SUCCESS;
}
The outer loop in main, indexed by j, iterates over all the n! permutations, while the inner one, indexed by i, iterates overs the n steps.
The get_next_permutation modifies the permutation array in place, to obtain the next permutation in the lexicographical order.
Note that it doesn't work when the permutation in input is the last one (n - 1, ..., 1, 0), hence the if (j != f - 1) test.
One could enhance it to detect this case (i isn't set) and to put the first permutation (0, 1, ..., n - 1) into the permutation array.
The code can be compiled with:
gcc main.c -o main -Wall -Wextra -Werror -O0 -g3
And I strongly suggest using valgrind as a way to detect off-by-one errors.
EDIT: I just realized I didn't answer the OP's question precisely. The someMagic() function would allow a direct access to the i-th permutation, while my algorithm only allows to compute the successor in the lexicographic order. But if the aim is to iterate on all the permutations, it will work fine. Otherwise, maybe an answer like this one should match the requirement.
I've come to a solution that is simple enough:
void stepA(STRUCT_NAME *data);
void stepB(STRUCT_NAME *data);
void stepC(STRUCT_NAME *data);
typedef void (*check)(STRUCT_NAME *data);
void swap(check *x, check *y) {
check temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(check *a, int l, int r,STRUCT_NAME *data) {
int i, j = 0, score;
HAND_T *copy, *copy2, *best_order = NULL;
if (l == r) {
j = 0;
while (j <= r) a[j++](data);
} else {
for (i = l; i <= r; i++) {
swap((a + l), (a + i));
permute(a, l + 1, r, data);
swap((a + l), (a + i));
}
}
}
check checks[3] = {
stepA,
stepB,
stepC,
};
int main(void){
...
permute(checks,0,2,data)
}
Okay so I've tried to print and Array and then reverse is using another array But I'm trying to create a For Loop that will take an array and reverse all of the elements in place without me having to go through the process of creating an entirely new array.
My for loop is running into some problems and I'm not sure where to go from here...i'm using i to take the element at the end and move it to the front and then j is being used as a counter to keep track of the elements...if there is an easier way to do this Any suggestions would be appreciated.
I'm New to this programming language so any extra info is greatly appreciated.
#include <stdlib.h>
#include <time.h>
int Random(int Max) {
return ( rand() % Max)+ 1;
}
void main() {
const int len = 8;
int a[len];
int i;
int j = 0;
Randomize() ;
srand(time(0));
//Fill the Array
for (i = 0; i < len; ++i) {
a[i] = rand() % 100;
}
//Print the array after filled
for (i = 0; i < len; ++i) {
printf("%d ", a[i]);
}
printf("\n");
getchar();
//Reversing the array in place.
for (i = a[len] -1; i >= 0, --i;) {
a[i] = a[j];
printf("%d ", a[j]);
j++;
}
}
A while loop may be easier to conceptualize. Think of it as starting from both ends and swapping the two elements until you hit the middle.
i = len - 1;
j = 0;
while(i > j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
i--;
j++;
}
//Output contents of now-reversed array.
for(i = 0; i < len; i++)
printf("%d ", a[i])
void reverse_range(int* buffer, int left, int right)
{
while (left < right)
{
int temp = buffer[left];
buffer[left++] = buffer[right];
buffer[right--] = temp;
}
}
call it to reverse array
int a[3] = {1, 2, 3};
reverse_range(a, 0, 2);
You are on the right track but need to think about that last for loop a little more and the assignment operation inside. The loop initialization is off, since i = a[len] - 1 will copy the value of the last entry to i. Since that value is a random number, your index will probably start out of bounds.
Next, you're copying half of the array to the other half and then back. That loop does the following:
a[7] = a[0]
a[6] = a[1]
a[5] = a[2]
a[4] = a[3] ...
At this point you've lost all of the initial values in a[4] through a[7].
Try this:
for( i = 0; i < len / 2; i++ ){
int temp = a[i];
a[i] = a[len - i];
a[len - i] = temp;
}
Use a debugger and step through the loop watching the value of i, temp, and each element in the array
Just my 2 cents...
#include <stdlib.h>
#include <stdio.h>
int main() {
int arry[] = {0, 1, 2, 3, 4, 5};
int* s = arry;
int* e = arry + (sizeof(arry) / sizeof(arry[0])) - 1;
while (s < e) {
*e ^= *s;
*s ^= *e;
*e ^= *s;
s++;
e--;
}
for (size_t i = 0; i < (sizeof(arry) / sizeof(arry[0])); i++) {
fprintf(stderr, "%d, ", arry[i]);
}
fprintf(stderr, "\n");
}
For starters, instead of this:
for (i = a[len] -1; i >= 0, --i;) {
you want this:
for (i = len-1; i >= 0, --i;) {
but you also only want to go half-way through the array, so it would be
for (i = len-1; i > j, --i;) {
Try this;
#include <stdlib.h>
#include <time.h>
int Random(int Max) {
return ( rand() % Max)+ 1;
}
void main() {
const int len = 8;
int a[len];
int i,end;
int j = 0;
Randomize() ;
srand(time(0));
//Fill the Array
for (i = 0; i < len; ++i) {
a[i] = rand() % 100;
}
//Print the array after filled
for (i = 0; i < len; ++i) {
printf("%d ", a[i]);
}
printf("\n");
getchar();
for (i = 0; i < n/2; i++) {
t = a[i];
a[i] = a[end];
a[end] = t;
end--;
}
}
Hope this helps... :)
Just for suggestion. Try to use meaningful variable name instead of just i,a.... That will help you while writing a bigger code. :)
You can reverse an array in place you don't need an auxiliary array for that, Here is my C code to do that
#include <stdio.h>
int main(void)
{
int arr[5]={1,2,3,4,5};
int size=sizeof(arr)/sizeof(int);
int success= reverse(arr,size);
if(success==1)
printf("Array reversed properly");
else
printf("Array reversing failed");
return 0;
}
int reverse(int arr[], int size)
{
int temp=0;
int i=0;
if(size==0)
return 0;
if(size==1)
return 1;
int size1=size-1;
for( i=0;i<(size/2);i++)
{
temp=arr[i];
arr[i]=arr[size1-i];
arr[size1-i]=temp;
}
printf("Numbers after reversal are ");
for(i=0;i<size;i++)
{
printf("%d ",arr[i]);
}
return 1;
}
Here's an easy and clean function for flipping arrays of all sizes. Change the parameters according to your type of array:
void flipArray(int *a, int asize){
int b[asize];
int *b_p = b;
for(int i=0; i<asize; i++){
//backwardsOrientation = (arraySize-1)-increment
b_p[asize-1-i] = a[i];
}
for(int i=0; i<asize; i++){
a[i] = b_p[i];
}
}
If you are not interested in writing functions for any numeric type, try macros for this task. This code same working with any built-in numeric type: int, float, double.
It has not a support for strings, since any string is ending on the character the NULL character \0. More a controlled version my similar answer is here https://stackoverflow.com/a/42063309/6003870 and contains solution for reverse a string.
A full code
#include <stdio.h>
// print items of an array by a format
#define PRINT_ARRAY(array, length, format) \
{ \
putchar('['); \
for (size_t i = 0; i < length; ++i) { \
printf(format, array[i]); \
if (i < length - 1) printf(", "); \
} \
puts("]"); \
}
// reverse an array in place
#define REVERSE_ARRAY(array, length, status) \
if (length > 0) { \
for (int i = 0; i < length / 2; ++i) { \
double temp; \
temp = array[i]; \
array[i] = array[length - i - 1]; \
array[length - i - 1] = temp; \
} \
*status = 0; \
} \
else if (length < 0) *status = -1; \
else *status = 1;
#define SUCCESS_REVERSE_ARRAY_MSG "An array succefully reversed"
#define FAILED_REVERSE_ARRAY_MSG "Failed reverse for an array"
#define NO_CHANGED_REVERSE_ARRAY_MSG "An array no changed"
/*
Print message about status reverse an array
*/
static void
print_msg_reverse_array_status(const int status)
{
if (status == 0) printf("Status: %s\n", SUCCESS_REVERSE_ARRAY_MSG);
else if (status == -1) printf("Status: %s\n", FAILED_REVERSE_ARRAY_MSG);
else if (status == 1) printf("Status: %s\n", NO_CHANGED_REVERSE_ARRAY_MSG);
}
int
main (const int argc, const char *argv[])
{
// keep value of status
int status;
puts("\tExample reverse of an integer array");
int arr_int[5] = {1, 2, 3, 4, 5};
status = 0;
PRINT_ARRAY(arr_int, 5, "%d");
REVERSE_ARRAY(arr_int, -1, &status);
// will be an error, since a length is less 0, and the array is not changed
print_msg_reverse_array_status(status);
PRINT_ARRAY(arr_int, 5, "%d");
status = 0;
REVERSE_ARRAY(arr_int, 0, &status);
// a length is equal to 0, so an array is not changed
print_msg_reverse_array_status(status);
PRINT_ARRAY(arr_int, 5, "%d");
status = 0;
REVERSE_ARRAY(arr_int, 5, &status);
print_msg_reverse_array_status(status);
PRINT_ARRAY(arr_int, 5, "%d");
puts("\n\tExample reverse of an float array");
float arr_float[5] = {0.78, 2.1, -3.1, 4, 5.012};
status = 0;
PRINT_ARRAY(arr_float, 5, "%5.3f");
REVERSE_ARRAY(arr_float, 5, &status);
print_msg_reverse_array_status(status);
PRINT_ARRAY(arr_float, 5, "%5.3f");
puts("\n\tExample reverse of an double array");
double arr_double[5] = {0.00001, 20000.002, -3, 4, 5.29999999};
status = 0;
PRINT_ARRAY(arr_double, 5, "%8.5f");
REVERSE_ARRAY(arr_double, 5, &status);
print_msg_reverse_array_status(status);
PRINT_ARRAY(arr_double, 5, "%8.5f");
return 0;
}
I am used the GCC for compilation and your result must be as next
Example reverse of an integer array
[1, 2, 3, 4, 5]
Status: Failed reverse for an array
[1, 2, 3, 4, 5]
Status: An array no changed
[1, 2, 3, 4, 5]
Status: An array succefully reversed
[5, 4, 3, 2, 1]
Example reverse of an float array
[0.780, 2.100, -3.100, 4.000, 5.012]
Status: An array succefully reversed
[5.012, 4.000, -3.100, 2.100, 0.780]
Example reverse of an double array
[ 0.00001, 20000.00200, -3.00000, 4.00000, 5.30000]
Status: An array succefully reversed
[ 5.30000, 4.00000, -3.00000, 20000.00000, 0.00000]
Testing environment
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.6 (jessie)
Release: 8.6
Codename: jessie
$ uname -a
Linux localhost 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux
$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
public static void ReverseArrayInPlace()
{
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int end = arr.Length - 1;
foreach (var item in arr)
{
Console.WriteLine(item);
}
for (int i = 0; i < arr.Length/2; i++)
{
var temp = arr[i];
arr[i] = arr[end];
arr[end] = temp;
end--;
}
Console.WriteLine("--------------------------");
foreach (var item in arr)
{
Console.WriteLine(item);
}
}
Here is how I did it in Java
It will be exactly same in C or C++ too
class Solution {
private void reverseHelper(char s[],int i, int j){
if(i >= j) return;
char temp = s[i];
s[i] = s[j];
s[j] = temp;
reverseHelper(s,i+1,j-1);
}
public void reverseString(char[] s) {
reverseHelper(s,0,s.length-1);
}
}
The space complexity here is O(1)
#include<Stdio.h>
#include<string.h>
#define max 25
int main()
{
char arr[max]="0123456789";
strrev(arr);
atoi(arr);
return 0;
}
//you can also use built in functions such as strrev(); string reverse atoi just
//changes string into integer
So.. I have something like this. It is supposed to create arrays with 10, 20, 50 100 .. up to 5000 random numbers that then sorts with Insertion Sort and prints out how many comparisions and swaps were done .. However, I am getting a runtime exception when I reach 200 numbers large array .. "Access violation writing location 0x00B60000." .. Sometimes I don't even reach 200 and stop right after 10 numbers. I have literally no idea.
long *arrayIn;
int *swap_count = (int*)malloc(sizeof(int)), *compare_count = (int*)malloc(sizeof(int));
compare_count = 0;
swap_count = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
compare_count = 0;
swap_count = 0;
free(arrayIn);
}
}
}
EDIT: ok with this free(arrayIn); I get this " Stack cookie instrumentation code detected a stack-based buffer overrun." and I get nowhere. However without it it's "just" "Access violation writing location 0x00780000." but i get up to 200numbers eventually
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
arr[i] = (RAND_MAX + 1)*rand() + rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
I am sure your compiler told you what was wrong.
You are passing a long** to a function that expects a int* at the line
fill_array(&arrayIn, n);
function prototype is
void fill_array(int *arr, int n)
Same problem with the other function. From there, anything can happen.
Always, ALWAYS heed the warnings your compiler gives you.
MAJOR EDIT
First - yes, the name of an array is already a pointer.
Second - declare a function prototype at the start of your code; then the compiler will throw you helpful messages which will help you catch these
Third - if you want to pass the address of a simple variable to a function, there is no need for a malloc; just use the address of the variable.
Fourth - the rand() function returns an integer between 0 and RAND_MAX. The code
a[i] = (RAND_MAX + 1) * rand() + rand();
is a roundabout way of getting
a[i] = rand();
since (RAND_MAX + 1) will overflow and give you zero... If you actually wanted to be able to get a "really big" random number, you would have to do the following:
1) make sure a is a long * (with the correct prototypes etc)
2) convert the numbers before adding / multiplying:
a[i] = (RAND_MAX + 1L) * rand() + rand();
might do it - or maybe you need to do some more casting to (long); I can never remember my order of precedence so I usually would do
a[i] = ((long)(RAND_MAX) + 1L) * (long)rand() + (long)rand();
to be 100% sure.
Putting these and other lessons together, here is an edited version of your code that compiles and runs (I did have to "invent" a print_array) - I have written comments where the code needed changing to work. The last point above (making long random numbers) was not taken into account in this code yet.
#include <stdio.h>
#include <stdlib.h>
// include prototypes - it helps the compiler flag errors:
void fill_array(int *arr, int n);
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count);
void print_array(int *arr, int n, int *swap_count, int *compare_count);
int main(void) {
// change data type to match function
int *arrayIn;
// instead of mallocing, use a fixed location:
int swap_count, compare_count;
// often a good idea to give your pointers a _p name:
int *swap_count_p = &swap_count;
int *compare_count_p = &compare_count;
// the pointer must not be set to zero: it's the CONTENTs that you set to zero
*compare_count_p = 0;
*swap_count_p = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count_p, compare_count_p);
print_array(arrayIn, n, swap_count_p, compare_count_p);
swap_count = 0;
compare_count = 0;
free(arrayIn);
}
}
}
return 0;
}
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
// arr[i] = (RAND_MAX + 1)*rand() + rand(); // causes integer overflow
arr[i] = rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
void print_array(int *a, int n, int* sw, int *cc) {
int ii;
for(ii = 0; ii < n; ii++) {
if(ii%20 == 0) printf("\n");
printf("%d ", a[ii]);
}
printf("\n\nThis took %d swaps and %d comparisons\n\n", *sw, *cc);
}
You are assigning the literal value 0 to some pointers. You are also mixing "pointers" with "address-of-pointers"; &swap_count gives the address of the pointer, not the address of its value.
First off, no need to malloc here:
int *swap_count = (int*)malloc(sizeof(int)) ..
Just make an integer:
int swap_coint;
Then you don't need to do
swap_coint = 0;
to this pointer (which causes your errors). Doing so on a regular int variable is, of course, just fine.
(With the above fixed, &swap_count ought to work, so don't change that as well.)
As I told in the comments, you are passing the addresses of pointers, which point to an actual value.
With the ampersand prefix (&) you are passing the address of something.
You only use this when you pass a primitive type.
E.g. filling the array by passing an int. But you are passing pointers, so no need to use ampersand.
What's actually happening is that you are looking in the address space of the pointer, not the actual value the pointer points to in the end. This causes various memory conflicts.
Remove all & where you are inputting pointers these lines:
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
So it becomes:
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count, compare_count);
print_array(arrayIn, n, swap_count, compare_count);
I also note that you alloc memory for primitive types, which could be done way simpler:
int compare_count = 0;
int swap_count = 0;
But if you choose to use the last block of code, DO use &swap_count and &compare_count since you are passing primitive types, not pointers!