A am trying an implementation of some sorting algorithms and I have to calculate how much time they spend. This is the function I wrote:
void bubble_sort(int A[], int len) {
bool ord = false;
for (int i=0; i<len-1 && ord==false; i++) {
ord = true;
for (int j=len-1; j>i; j--) {
if (A[j]-1>A[j]) {
ord = false;
swap(A[j]-1, A[j]);
}
}
}
}
And of course here there is a typical swap() function:
void swap(int x, int y) {
int d;
d = x;
x = y;
y = d;
}
I am not having troubles with Insertion Sort, Selection Sort and Merge Sort. By the way bubble_sort is not sorting the numbers in my array.
I cannot find what's wrong. Do you have any ideas?
In C, function parameters are passed by value, not by reference.
your swap() function does nothing (it doesn't even return... didn't your compiler complain?)
To actually sort, you have to change swap() to
void swap(int *x, int *y) {
int d = *x;
*x = *y;
*y = d;
return;
}
and invoke it with
swap(&A[j-1], &A[j]);
You have to include -1 in array A. Not outside the []. Your code non just chech if value in A[j]minus 1 is bigger than value in A[j]. Which is obviously always false.
Also in swap function you dont pass the ponter of the Array A. Actually swap() does nothing.
Try
if (A[j-1]>A[j]) {
ord = false;
int temp=A[j-1];
A[j-1]=A[j];
A[j]=temp;
Related
I'm writing a function that returns the inverse of an array using recursivity but I keep getting these warnings :
Here is my code
#include <stdio.h>
#include <stdlib.h>
int inv( float* t[],int n)
{ float u;
if (n==0) return 0;
else
{
u=*t;
*t=*(t+n);
*(t+n)=u;
return(inv(*(t+1),n-1));
}
}
int main()
{
float t[]={1,2,3,4,5,6,7,8,9};
int n=sizeof t /sizeof *t;
int i=0;
inv(t,n);
for(i=0;i<n;i++)printf("%f",t[i]);
return 0;
}
int inv( float* t[],int n)
Here, float* t[] declares an array of pointers. Please note that *t[i] = *(*(t+i))
For i = 0, *(*(t+i)) = *(*(t)) = *(*t).
Here, *t is of type float*, and u is of type float.
Using the expression u=*t; gives you that error (assigning float* value to float)
Solution : Change int inv( float* t[],int n) to int inv( float t[],int n)
I use a procedure to arrange the array elements in descending order
#include <stdio.h>
#include <stdlib.h>
void revs(int i, int n, float *arr)
{
if(i==n)
{
return ;
}
else
{
revs(i+1, n, arr);
printf("%.f ", arr[i]);
}
return 0;
}
int main()
{
float t[]={1,2,3,4,5,6,7,8,9};
int n=sizeof t /sizeof t[0];
int i=0;
revs(0,n,t);
}
It looks like the intended action of OP's function inv is to reverse the elements of an array of n float values in place, using recursion.
In the original inv code, the parameter declaration float* t[] will be adjusted to be equivalent to float** t by the compiler. This needs to be changed to float t[] or equivalently float* t.
In the original inv code, the return value is either 0 or the result of the recursive call to itself, which can only be 0. Therefore the return value is of no use. It would be better to change the return type of the function to void.
In the inv function, the parameter n is set to the length of the array in the initial call from main. The function swaps the values of elements at indices 0 and n before recursing, but there is no element at index n. The last element has index n-1. The function should swap the elements at indices 0 and n-1 before recursing. After swapping the first and last elements, the remaining n-2 elements with indices from 1 to n-2 can be swapped by a recursive call. The original inv code uses the value n-1 in the recursive call, but it should be n-2.
If n is less than 2, the inv function does not need to do anything.
A possible implementation of inv based on OP's original code follows:
void inv(float* t,int n)
{
float u;
if (n>=2)
{
u=*t;
*t=*(t+n-1);
*(t+n-1)=u;
inv(t+1,n-2));
}
}
The same function can be written using array subscripting operators as follows:
void inv(float t[],int n)
{
float u;
if (n>=2)
{
u=t[0];
t[0]=t[n-1];
t[n-1]=u;
inv(&t[1],n-2));
}
}
i have a little question.
i'm studying C with devc++ (as start) and i have seen as argument function you can pass a function, this is ok but why?
for example u can write as argument:
void myfunc(void(*func)(int)){}
but if u simple call function with his name and argument it is not better?
like example:
void myfunction (){name of func to call(myargs); }
there's a difference?
it seems the same thing but with more simple and short code
edit:
i want only know
void map (int (*fun) (int),int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
}
why u use this instead of:
void map (int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
}
You can use a function pointer as a parameter if you want your function to do different things depending on what the user wants.
Here's a simple example:
#include <stdio.h>
int add(int x, int y)
{
return x + y;
}
int subtract(int x, int y)
{
return x - y;
}
int multiply(int x, int y)
{
return x * y;
}
int divide(int x, int y)
{
return x / y;
}
int operation(int x, int y, int (*func)(int, int))
{
printf(" x=%d, y=%d\n", x, y);
return func(x,y);
}
int main()
{
int x = 8, y = 4;
printf("x+y=%d\n", operation(x,y,add));
printf("x-y=%d\n", operation(x,y,subtract));
printf("x*y=%d\n", operation(x,y,multiply));
printf("x/y=%d\n", operation(x,y,divide));
return 0;
}
A very good example is the classic sorting function qsort. It's a library function, which means that you only have access to it's prototype. In order to make qsort general, you have to write your own compare function. A typical implementation looks like this for regular integers:
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
And then, if you have an array arr of integers you can sort it with qsort(arr, sizeof(arr), cmpfunc)
You might ask why this is not built in the qsort function? After all, it would be easy to make it work for both floats and integers. Yes, but imagine if you have an array of structs that look like this:
struct {
char *firstname;
char *lastname;
int age;
} persons[10];
How would you sort this? Well, that's not obvious. You might want all three. In that case, write three different compare functions.
i want only know
void map (int (*fun) (int),int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
}
why u use this instead of:
void map (int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
}
Let's answer the question with a question - what if you want to perform more than one type of mapping? What if you want to map both x2 and √x?
You could certainly do something like
void map( int x[], int l, int type )
{
for ( int i = 0; i < l; i++ )
{
if ( type == MAP_SQUARED )
x[i] = int_square( x );
else if ( type == MAP_ROOT )
x[i] = int_root( x );
...
}
}
which works, but is hard to read and cumbersome to maintain - every time you want to perform a new mapping, you have to add a new case to the map function.
Compare that to
void map( int x[], int l, int (*fun)(int) )
{
for ( int i = 0; i < l; i++ )
x[i] = fun( x[i] );
}
...
map( x, l, int_square );
map( y, l, int_root );
You don't have to hack the map function to get different mappings - you only have to pass the function that operates on the individual elements. If you want to perform a new mapping, all you have to do is write a new function - you don't have to edit the map function at all.
The C standard library uses this form of delegation in several places, including the qsort function (allowing you to sort arrays of any type in any order) and the signal function (allowing you to change how a program reacts to interrupts dynamically).
I am writing a program that creates an array of random numbers from 1 to 100 and sorts them in ascending order. Below is working code that does this, but I need to modify it so that the "swap" function makes use of pointers. The call for the swap function should look like this: swap(???,???) where the two inputs are pointers. What is the best way to accomplish this?
#include<stdio.h>
#include<math.h>
int main()
{
void fillArray(int sizeArray, int array[sizeArray]);
void printArray(int sizeArray, int array[sizeArray]);
void sortArray(int sizeArray, int array[sizeArray]);
int sizeArray;
printf("\nSize of the array? ");
scanf("%d", &sizeArray);
int array[sizeArray];
fillArray(sizeArray,array);
sortArray(sizeArray, array);
printArray(sizeArray, array);
}
void fillArray(int sizeArray, int array[sizeArray])
{
int increment;
for(increment=0; increment<sizeArray; increment++)
{
array[increment]=rand()%101;
}
}
void sortArray(int sizeArray, int array[sizeArray])
{
void swap(int increment2, int increment, int array[]);
int increment, increment2, temp;
for (increment=0; increment < sizeArray ; increment++)
{
for (increment2=increment+1; increment2 < sizeArray; increment2++)
{
swap(increment2, increment, array);
}
}
}
void swap(int increment2, int increment, int array[])
{
int temp;
if (array[increment2] < array[increment])
{
temp=array[increment];
array[increment]=array[increment2];
array[increment2]=temp;
}
}
void printArray(int sizeArray, int array[sizeArray])
{
int increment=0;
printf("\nHere's the sorted array:\n");
while(increment<21)
{
printf("\n array[%d] is %d", increment, array[increment]);
increment++;
}
}
The output should look like this:
output
Define your swap function as below:
void swap(int *increment2, int* increment)
Modify your for loop where you call the swap function:
for (increment=0; increment < sizeArray ; increment++)
{
for (increment2=increment+1; increment2 < sizeArray; increment2++)
{
swap(array[increment2], array[increment]);
}
}
Then, modify your swap function:
void swap(int *increment2, int* increment)
{
int temp;
if (increment2 < increment)
{
temp= *increment2;
*increment2=*increment;
*increment2=temp;
}
}
You need to fix your function call for the parameters to be with pointers.
void swap(int *increment2, int* increment)
Then in your swap function you need
You will need to deference the integer*.
Example
int n1;
int* x = 100
n1 = *x;
You may need to
deference in the future example
Your function accepts pointers
void swap(int *increment2, int* increment)
If you have integers or another data type to reference them, refer to their address, you can perform & for referencing.
int i = 5;
int* x;
x = &i;
x is now an integer pointer to the address of i.
Your calling code needs to pass the address of the integers to compare and swap. Either of the following forms is acceptable, and they are equivalent.
swap(array+increment2, array+increment);
swap(&array[increment2], &array[increment]);
The first form takes the address of the first element (array) and adds the index (increment2) to get the address of the correct element.
The second version is more straightforward, perhaps. It uses the & address-of operator to take the address of array[increment2], which is the desired integer.
Your swap function need to be defined as follows:
void swap(int** p2, int** p1)
{
int temp;
if (*p2 < *p1)
{
temp=*p1;
*p1=*p2;
*p2=temp;
}
}
Note how the pointers are dereferenced with the * operator to get the integer values for comparison (and storage in temp).
me and my friend are trying to pass a user-defined array to a function and do a "2d array" sort mechanism on that array which is defined outside the function.
we found a function online that sorts a predefined array within itself and tried to use that function.
our problem consist in trying to use the user-defined array in the function.
please check the code below (please note that we don't know how to use structs)
The question is: how do we use our orderListArray[][] in the sort array function?
#include <stdio.h>
#include <stdlib.h>
// define for sort array function later on
#define ARRAYSIZE(array) (sizeof(array)/sizeof(*(array)))
// function prototype
int sortArray();
int printOrderlist();
// data variables to be used throughout the code.
int itemNumber;
int itemAmount;
int maxItem = 0;
int lineCount = 0;
int priceToPrint = 0;
float totalPrice = 0;
// array we wish to implement into "sortArray" function
int orderListArray[][2];
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
int orderList()
{ // begin orderList
// makes sure user enters a maximum of 5 orders
int k = 0; // first place in array
int g = 0; // second place in array
do
{ // begin do1
printf("%d %d\n", k,g);
// asks for item number
puts("Enter item number (1-100):");
scanf("%d", &itemNumber);
// add scan to first spot (k) which is 0,0 (row 0, spot 0)
orderListArray[k][g] = itemNumber;
// add g++ to go to 0,1 ( row 0, spot 1)
g++;
// asks for amount
printf("%d %d\n", k, g);
printf("You can order %d more items\n", 5-itemAmount);
printf("Enter amount:\n");
scanf("%d", &itemAmount);
maxItem = maxItem + itemAmount;
// add itemAmount to g which is 0,1
orderListArray[k][g] = itemAmount;
k++; // go to row 1 instead of row 0
g--; // go back to spot 0 in row.
// lineCount is used when we print rows of array since that is not predefined
lineCount++;
} // end do1
// runs as long as the total amount of items inputed matches.
while (maxItem <= 4);
return 0;
} // end orderList
//////////////////////////////////////////////////////////////////////////////// //////////
//////////////////////////////////////////////////////////////////////////////// //////////
int main(void)
{
orderList();
sortArray();
return 0;
}
//////////////////////////////////////////////////////////////////////////////// //////////
//////////////////////////////////////////////////////////////////////////////// //////////
// is used in sortArray() to sort 2d array.
int compare(const void *a, const void *b) {
int x1 = *(const int*)a;
int x2 = *(const int*)b;
if (x1 > x2) return 1;
if (x1 < x2) return -1;
// x1 and x2 are equal; compare y's
int y1 = *(((const int*)a)+1);
int y2 = *(((const int*)b)+1);
if (y1 > y2) return 1;
if (y1 < y2) return -1;
return 0;
}
//////////////////////////////////////////////////////////////////////////////// //////////
//////////////////////////////////////////////////////////////////////////////// //////////
// sortArray function (here we want to implement the orderListArray[k][g]
// and run on that instead of predefined matrix which is included in the code
int sortArray(int b[], size_t size)
{ // begin sortArray
int matrix[][2] = {{8,6}, {4,2}, {1,0}, {4,8}, {2,4},
{4,3}, {1,2}, {2,2}, {8,3}, {5,5}};
printf("Original: ");
for (size_t i = 0; i < ARRAYSIZE(matrix); i++)
printf("(%d,%d) ", matrix[i][0], matrix[i][1]);
putchar('\n');
qsort(matrix, ARRAYSIZE(matrix), sizeof(*matrix), compare);
printf("Sorted : ");
for (size_t i = 0; i < ARRAYSIZE(matrix); i++)
printf("(%d,%d) ", matrix[i][0], matrix[i][1]);
putchar('\n');
return 0;
} // end sortArray
You have a bona fide 2D array. That's an array of arrays, so the elements are arrays, and therefore your compare function receives pointers to arrays as its arguments. Your comparison code is not actually wrong, but it would be a bit cleaner and clearer to acknowledge the correct types of the elements you are comparing:
int compare(const void *a, const void *b) {
const int (*x1)[2] = a;
const int (*x2)[2] = b;
if ((*x1)[0] > (*x2)[0]) return 1;
if ((*x1)[0] < (*x2)[0]) return -1;
if ((*x1)[1] > (*x2)[1]) return 1;
if ((*x1)[1] < (*x2)[1]) return -1;
return 0;
}
The main question seems to be represented by this code comment, however:
here we want to implement the orderListArray[k][g] and run on that instead of predefined matrix
It's not an especial problem for k to be an adjustable parameter, but it complicates matters greatly for g to be adjustable. To even declare your function requires either fudging types, or using a variable-length array. Either way, your function signature does not provide enough information. You must either know or assume both dimensions of your array, and you have only one parameter, size, to convey that information.
If you are assuming that the array to be sorted will be an array of pairs, as is matrix in your sample code, then simply write the function signature like so:
int sortArray(int b[][2], size_t size) // ...
and rely on the caller to provide the number of elements (pairs) via the size parameter. Then you could call qsort like so:
qsort(b, size, sizeof(*b), compare);
It's a lot messier if the matrix rows are variable length, because then you have to either dynamically choose a comparison function that is specific to the correct length, or generalize your comparison function and convey the row length to it by some means other than its arguments (thus, probably via a file-scope variable). Both of those approaches have significant drawbacks.
A third approach would be to rely on the caller of sortArray() to provide a suitable comparison function, but if you do that then you have to consider what value sortArray() is actually providing relative to calling qsort() directly.
I'm working on a simple library which operate on vectors.
It define a type of function that is regularly used:
typedef float (*vec_pair_fun) (float x, float y);
For ease-of-use reason, I want to create a sorting function that use a vec_pair_fun to compare each element of a vector.
At the moment, I'm doing this:
static vec_pair_fun sort_function;
// follow improvements suggested by #chux below
static int converted_sort_function(const void* a, const void* b){
//old code: return (int) qsort_function(*(float*)a,*(float*)b);
float f = sort_function(*(float*)a,*(float*)b);
return (f > 0.0f) - (f < 0.0f);
}
void vecx_sort(int x, float v[], vec_pair_fun func){
sort_function=func;
qsort(v,x,sizeof(float),converted_sort_function);
}
but I don't really like that workaround because it's not threadsafe as sort_function can be changed by another thread.
Any idea on how to improve this?
EDIT:
One way would be to sort the array myself.
Recoding qsort is really not what I planned to do, so I'm really open for suggestions
Q: Any idea on how to improve this?
A: Do not cast float result to int for compare.
Maybe not OP's main concern but (int) sort_function(*(float*)a,*(float*)b); is weak.
The FP point result could be -0.4 or 0.4, both of these convert to (int) 0.
The FP point result could be > INT_MAXand conversion to int is UB.
Suggest:
static int converted_sort_function(const void* a, const void* b){
float f = sort_function(*(float*)a,*(float*)b);
return (f > 0.0f) - (f < 0.0f);
}
As to your thread safe problem, consider qsort_s() which passes in a context pointer. qsort_s() is specified in C11 Annex K, so it may not exist in your compiler.
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
int (*compar)(const void *x, const void *y, void *context),
void *context);
Following wikibooks 5th C implementation and Apple's implementation of a quicksort algorithm, I was able to create my function.
It appear to be quicker than the stdlib version, and it has no global/static variable.
// x: length of v
// v: array of float
// func: a function that takes two float as argument and return a float
void vecx_qsort(unsigned int x, float v[], vec_pair_fun cmpf)
{
float pivot,tmp;
unsigned int al,l,r,ar,cnt;
while (x>8)
{
cnt=0;
al=l=1; r=ar=x-1;
pivot=v[x/2];
v[x/2]=v[0];
v[0]=pivot;
while (1)
{
while ( l<=r && (tmp=cmpf(v[l],pivot))<=0.0f ) {
if(tmp==0.0f){
cnt=1;
vecx_swap(1,v+al,v+l); //swap vl & val
al++;
}
l++;
}
while ( l<=r && (tmp=cmpf(v[r],pivot))>=0.0f ) {
if(tmp==0.0f){
cnt=1;
vecx_swap(1,v+r,v+ar);//swap vr & var
ar--;
}
r--;
}
if(l>r)
break;
cnt=1;
vecx_swap(1,v+r,v+l);
l++; r--;
}
if(cnt==0 && x<=32) // no swap made => almost sorted small array => insertion sort
break;
// swap values equal to pivot to the center
cnt = (al<(l-al))?al:l-al;
vecx_swap(cnt,v,v+l-cnt); // swap of element before al
cnt = ((ar-r)<(x-ar-1))?ar-r:x-ar-1;
vecx_swap(cnt,v+l,v+x-cnt); // swap of element after ar
l=l-al; // size of "smaller element array"
r=ar-r; // size of "bigger element array"
// Recursion on the shorter side & loop (with new indexes) on the longer
if (l>r) {
vecx_qsort(r, v+x-r, cmpf);
x=l;
}
else {
vecx_qsort(l, v, cmpf);
v+=x-r;
x=r;
}
}
// insertion sort
for (r=1; r<x; r++)
{
pivot=v[r];
for(l=r; l>0 && cmpf(pivot,v[l-1])<0.0f; l--)
v[l]=v[l-1];
v[l]=pivot;
}
}