So I try to do the Heap Sort in C for a row of an 2d array
So basically I find the smallest sum of all the rows from the array and I try to sort the elements of that row, for that I'm trying to store the index of the smallest row with a pointer but when I use pointer the programm it's not returning the index but the adress
//funcion to find the smallest row sum
void min_rand(int(*a)[50], int n, int m, int *mi)
{
int min_row = 0;
int i, j;
for (j = 0; j < m; j++)
min_row += a[0][j];
for (i = 0; i < n; i++) {
int sum_row = 0;
for (j = 0; j < m; j++)
sum_row += a[i][j];
if (sum_row < min_row) {
min_row = sum_row;
*mi = i;
}
}
}
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void heapify_c(int(*a)[50], int n, int i, int mi)
{
int largest = i;
int l = 2 *i + 1;
int r = 2 *i + 2;
if (l < n && a[mi][l] > a[mi][largest])
largest = l;
if (r < n && a[mi][r] > a[mi][largest])
largest = r;
if (largest != i) {
swap(&a[mi][i], &a[mi][largest]);
heapify_c(a, n, largest, mi);
}
}
void heapSort_c(int(*a)[50], int n, int mi)
{
for (int i = n / 2 - 1; i >= 0; i--)
heapify_c(a, n, i, mi);
for (int i = n - 1; i > 0; i--) {
swap(&a[mi][0], &a[mi][i]);
heapify_c(a, i, 0, mi);
}
}
int main()
{
int a[50][50];
int n, m, mi;
min_rand(a, n, m, &mi);
heapSort_c(a, n, mi);
return 0;
}
I don't print the sorted elements in the e.g. above but I just want to know if I'm doing something so terrebly wrong cause I did this before with counting sort and it worked without any problems
Related
Given two sets of natural number A and B of size n such that each member of A has to be paired to at at most one member of B. There is also cost associated with each pairing i.e if the absolute difference b\l sum of all n-length possible pair permutations of elements of A with B.
The following (crude and far from being optimized and safe -- I used a global variable: horror!) code does the job:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define SWAP(x, y, T) do { T SWAP = x; x = y; y = SWAP; } while (0)
int factorial(int N) {
int product = 1;
for (int j = 1; j <= N; j++)
product *= j;
return product;
}
// Prints the array
void printArr(int a[], int n)
{
for (int i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
}
// Stores the array
void storeArr(int a[], int n, int counter, int** out)
{
for (int i = 0; i < n; i++) {
out[counter][i] = a[i];
}
}
int get_cost(int a, int b) {
int diff = abs(a - b);
if (diff >= 5 && diff < 10) {
return 0;
}
else if (diff < 5) {
return 1;
}
else {
return 2;
}
}
int cost_perm(int* a, int* b, int n) {
int cost = 0;
for (int i = 0; i < n; ++i) {
cost += get_cost( a[i], b[i] );
}
return cost;
}
// Globals are bad but...
int counter;
// Generating permutation using Heap Algorithm
void heapPermutation(int a[], int size, int n, int** out)
{
// if size becomes 1 then stores the obtained
// permutation
if (size == 1) {
storeArr(a, n, counter++, out);
return;
}
for (int i = 0; i < size; i++) {
heapPermutation(a, size - 1, n, out);
// if size is odd, swap 0th i.e (first) and
// (size-1)th i.e (last) element
if (size % 2 == 1)
SWAP(a[0], a[size - 1], int);
// If size is even, swap ith and
// (size-1)th i.e (last) element
else
SWAP(a[i], a[size - 1], int);
}
}
// Driver code
int main()
{
int a[] = { 169, 165, 161, 131, 145 };
int b[] = { 214, 174, 218, 188, 168 };
int n = sizeof a / sizeof a[0];
int numperm = factorial(n);
int** perm_of_a = calloc(numperm, sizeof(int*));
int** perm_of_b = calloc(numperm, sizeof(int*));
for (int i = 0; i < numperm; ++i) {
perm_of_a[i] = calloc(n, sizeof(int));
perm_of_b[i] = calloc(n, sizeof(int));
}
counter = 0;
heapPermutation(a, n, n, perm_of_a);
counter = 0;
heapPermutation(b, n, n, perm_of_b);
int min_cost = 1000;
int cost;
int mina = 0;
int minb = 0;
for (int i = 0; i < numperm; ++i) {
for (int j = 0; j < numperm; ++j) {
cost = cost_perm(perm_of_a[i], perm_of_b[j], n);
if (cost < min_cost) {
min_cost = cost;
mina = i;
minb = j;
}
}
}
printArr( perm_of_a[mina], n );
printArr( perm_of_b[minb], n );
printf( "%d\n", min_cost );
return 0;
}
You are trying to find one individual pair at each iteration, but you want to minimize the cost over all permutations.
You need to figure out how to generate all permutations of a vector and use code like this:
for permuted_A in all_permutations_of_A
for permuted_B in all_permutations_of_B
cost = cost(permuted_A, permuted_B)
if cost < min_cost
min_cost = cost
min_permuted_A = permuted_A
min_permuted_B = permuted_B
Once you figure out how to enumerate the permutations, the rest will be trivial.
The below code works fine except for a one dimensional array I am trying to pass to main() from the function order_coef. I believe I am doing something wrong in the line where I specify *ordered_array=*array;, but not really sure what it is. Some help would be very much appreciated. Thank you!
#include <stdio.h>
#define COEF 5
int save_coef (int i, int *array);
int order_coef (int i, int *array, int *ordered_array);
int save_x (int x);
int resolve_polinomyal (int *array, int x, int i);
int main()
{
int array[COEF], x = 1, i = 0, *ordered_array=0;
printf("Please, enter 5 coefficients:\n");
save_coef (i, array);
order_coef (i, array, ordered_array);
for (i = 0; i < COEF; ++i)
printf("\n%d\n", ordered_array[i]);
printf("Please, enter the value of x:\n");
save_x (x);
printf("%d", resolve_polinomyal (array, x, i));
return 0;
}
int save_coef (int i, int *array)
{
for (i = 0; i < COEF; ++i)
{
scanf("%d", &array[i]);
}
return 0;
}
int order_coef (int i, int *array, int *ordered_array)
{
int j, a;
for (i = 0; i < COEF; ++i)
{
for (j = i + 1; j < COEF; ++j)
{
if (array[i] > array[j])
{
a = array[i];
array[i] = array[j];
array[j] = a;
}
}
}
*ordered_array=*array;
return 0;
}
int save_x (int x)
{
scanf("%d", &x);
return 0;
}
int resolve_polinomyal (int *array, int x, int i)
{
for (i = 5-1; i > 0; --i)
{
array[i-1] = array[i] * x + array[i-1];
}
return array[0];
}
The first problem is you do not allocate for ordered_array.
When you declare
int array[COEF], x = 1, i = 0, *ordered_array=0;
it means you initialized ordered_array = NULL.
You can use the static or dynamic allocation:
int ordered_array[COEF];
//
int *ordered_array = malloc(COEF*sizeof(int));
The second problem is *ordered_array=*array not copy array to array. It assigns first value of array to first value of ordered_array.
If you want to copy the value from an array to another one, you should use memcpy or a loop to copy value by value.
For example:
// copy the values of array to ordered_array
memcpy(ordered_array, array, COEF * sizeof(int));
Based on #Hitokiri comment I am pasting here the final solution with my code updated:
#include <stdio.h>
#define COEF 5
int save_coef (int i, int *array);
int order_coef (int i, int *array, int *ordered_array);
int save_x (int x);
int resolve_polinomyal (int *array, int x, int i);
int main()
{
int array[COEF], x = 1, i = 0, ordered_array[COEF];
printf("Please, enter 5 coefficients:\n");
save_coef (i, array);
order_coef (i, array, ordered_array);
for (i = 0; i < COEF; ++i)
printf("\n%d", ordered_array[i]);
printf("\nPlease, enter the value of x:\n");
save_x (x);
printf("%d", resolve_polinomyal (array, x, i));
return 0;
}
int save_coef (int i, int *array)
{
for (i = 0; i < COEF; ++i)
{
scanf("%d", &array[i]);
}
return 0;
}
int order_coef (int i, int *array, int *ordered_array)
{
int j, a;
for (i = 0; i < COEF; ++i)
{
for (j = i + 1; j < COEF; ++j)
{
if (array[i] > array[j])
{
a = array[i];
array[i] = array[j];
array[j] = a;
}
}
}
for (i = 0; i < COEF; ++i)
ordered_array[i] = array[i];
return 0;
}
int save_x (int x)
{
scanf("%d", &x);
return 0;
}
int resolve_polinomyal (int *array, int x, int i)
{
for (i = 5-1; i > 0; --i)
{
array[i-1] = array[i] * x + array[i-1];
}
return array[0];
}
For instance when user input 4 and 2, it means the original set have 4 elements: (1,2,3,4) and the subset should have 2 elements. I figured out a way to present these subsets in a regular form like (1,2)(1,3)(1,4)(2,3)(2,4)(3,4) using the code below, but my assignment requires binary-like form like (1,2) should be (1,1,0,0) and (2,4) should be (0,1,0,1) etc. In (1,1,0,0), first binary 1 means the first element in original set (1,2,3,4) which is 1 is contained in the subset. And the second binary 1 means the second element in original set which is 2 is contained in subset. While the third and forth number 3 and 4 is not. So for example, a subset (1,2,5) from set (1,2,3,4,5) can be presented by (1,1,0,0,1)
void subset(int n, int k, int B[], int q, int r) {
if (q == k) {
for (int i = 0; i < k; i++) {
printf("%d ", B[i]);
}
printf("\n");
} else {
for (int i = r; i < n; i++) {
B[q] = i+1;
subset(n, k, B, q+1, i+1);
}
}
}
In main (n is number of elements in original set, k is number of elements in subsets):
int B[101];
subset(n, k, B, 0, 0);
Also my assignment needs this recursive function with 4 exact arguments( i is from (1,2,3,4...i) ):
void subsets(int B[], int n, int k, int i)
I've tried so many ways and failed. I'll be really appreciated if someone can help me out, thanks.
Updates:
thanks to rajender kumar, the binary-like output problem is solved by using the code below:
void printSubsets(int B[], int n, int k, int q, int i) {
if (q == k) {
int finalArry[MAX_SIZE+1] = {0};
for (int i = 0; i < k; i++) {
finalArry[B[i]] = 1;
}
printSet(finalArry, n);
} else {
for (int j = i; j < n; j++) {
B[q] = j+1;
printSubsets(B, n, k, q+1, j+1);
}
}
}
But I still need to remove one argument from either int q or int i.
This should do the job:
void subset(int n, int k, int B[], int i) {
if (k == 0) {
for (int d = 0; d < n; d++) {
printf("%d ", B[d]);
}
printf("\n");
} else if (i >= n || k > n - i) {
return;
} else {
B[i] = 1;
subset(n, k - 1, B, i + 1);
B[i] = 0;
subset(n, k, B, i + 1);
}
}
int main(int argc, char **argv) {
int n, k;
int B[4];
memset(B, 0, sizeof(B));
n = sizeof(B) / sizeof(B[0]);
k = 2;
printf("n=%d\nk=%d\n", n, k);
subset(n, k, B, 0);
return 0;
}
Add another boolean array and put entire array like this .
void subset(int n, int k, int B[], int q, int r) {
if (q == k) {
bool finalArry[n] = {0};
for (int i = 0; i < k; i++) {
finalArry[B[i]-1] = true;
}
for (int i = 0; i < n; i++) {
if(finalArry[i]){
cout<<1<<" ";
}
else{
cout<<0<<" ";
}
}
cout<<endl;
} else {
for (int i = r; i < n; i++) {
B[q] = i+1;
subset(n, k, B, q+1, i+1);
}
}
}
I have an n*2 sized array. I want to sort them using qsort based on their value of the 2nd column.
#include<stdio.h>
int cmp(const int **a, const int **b) {
//return 0;
//return *a[1] - *b[1]
// return *a - *b;
}
int main()
{
int t; // test cases
scanf("%d", &t);
for(int i=0; i<t; i++) {
int n;
scanf("%d", &n); // size of array
int **arr = (int **)malloc(n * sizeof(int *));
for(int j =0; j< n; j++) {
arr[j] = (int *) malloc(2*sizeof(int));
}
for(int j =0; j< 2; j++) {
for(int k =0; k< n; k++) {
scanf("%d", &arr[k][j]);
}
}
for(int k =0; k< n; k++) {
for(int j =0; j<= 1; j++) {
printf("%d\t", arr[k][j]);
}
printf("\n");
}
// qsort(arr, n, sizeof(arr[0]), cmp);
}
return 0;
}
So for input,
1 2
3 6
0 8
5 4
8 9
5 7
Output is,
1 2
5 4
3 6
5 7
0 8
8 9
I tried but couldn't sort them according to their 2nd column. I am confused with passing array element to the comparator. Also with what to pass as the size of the element? But I guess that first 2 among below are correct.
qsort(arr, n, sizeof(arr[0]), cmp);
//qsort(arr, n, sizeof((int *)), cmp);
//qsort(arr, n, 2 * sizeof((int)), cmp);
I tried various combinations for the comparator.
Please hint out the way or perhaps an explanation.
The prototype for the comparison function is specified in the prototype for the qsort function:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Your comparison function must be compatible, so you can define it this way:
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int *aa = *(int * const *)a;
int *bb = *(int * const *)b;
return (aa[1] > bb[1]) - (aa[1] < bb[1]);
}
Or without casts:
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int * const *aa = a;
int * const *bb = b;
int ia = (*aa)[1];
int ib = (*bb)[1];
return (ia > ib) - (ia < ib);
}
Note that you cannot use the simplistic comparison aa[1] - bb[1] as it can overflow for large values and at best produce incorrect output.
Furthermore, you input loop is incorrect: you should nest the loops in the opposite order:
for (int k = 0; k < n; k++) {
for (int j = 0; j < 2; j++) {
scanf("%d", &arr[k][j]);
}
}
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int * const *aa = a;
int * const *bb = b;
int ia = (*aa)[1];
int ib = (*bb)[1];
return (ia > ib) - (ia < ib);
}
int main() {
int t; // test cases
scanf("%d", &t);
for (int i = 0; i < t; i++) {
int n;
scanf("%d", &n); // size of array
int **arr = malloc(sizeof(*arr) * n);
for (int j = 0; j < n; j++) {
arr[j] = malloc(sizeof(*arr[j]) * 2);
}
for (int k = 0; k < n; k++) {
for (int j = 0; j < 2; j++) {
scanf("%d", &arr[k][j]);
}
}
qsort(arr, n, sizeof(arr[0]), cmp);
for (int k = 0; k < n; k++) {
for(int j = 0; j < 2; j++) {
printf("%d\t", arr[k][j]);
}
printf("\n");
}
for (int j = 0; j < n; j++) {
free(arr[j]);
}
free(arr);
}
return 0;
}
You can also simplify the code using an actual 2D array:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
const int *aa = a;
const int *bb = b;
return (aa[1] > bb[1]) - (aa[1] < bb[1]);
}
int main() {
int t; // test cases
scanf("%d", &t);
for (int i = 0; i < t; i++) {
int n;
scanf("%d", &n); // size of array
int (*arr)[2] = malloc(sizeof(*arr) * n);
for (int k = 0; k < n; k++) {
scanf("%d%d", &arr[k][0], &arr[k][1]);
}
qsort(arr, n, sizeof(arr[0]), cmp);
for (int k = 0; k < n; k++) {
printf("%d\t%d\n", arr[k][0], arr[k][1]);
}
free(arr);
}
return 0;
}
First of all you don't have a 2D array. You have a 1D array of pointers that each points to a 1D array of int.
So what you can do is to sort the 1D array of pointers. For that you can write a compare function that looks at the value of the pointed-to element.
It could look something like:
int cmp(const void * a, const void * b)
{
int* const * x = a;
int* const * y = b;
if ((*x)[1] < (*y)[1]) return -1;
if ((*x)[1] > (*y)[1]) return 1;
return 0;
}
As said above: It's the array of pointers that is sorted. You can visualize it like:
I'm trying to transpose a matrix in C while passing the matrix to a function and return a pointer to a transposed matrix. What am I doing wrong in the second while loop?
in main
ptr = (float *) getMatrix(numRowsB, numColsB);
transposePtr = transpose(ptr, numRowsB, numColsB);
printf("\nBtranspose =\n");
printMatrix(transposePtr, numColsB, numRowsB);
create matrix
float* getMatrix(int n, int m)
{
int i, j;
float *arrayPtr;
if ((n <= 0) || (m <= 0))
{
printf("function getMatrix(): matrix dimensions are invalid\n");
return NULL;
}
arrayPtr = (float *) malloc(n*m*sizeof(float));
if(arrayPtr == NULL)
{
printf("function getMatrix: Unable to malloc array\n");
return NULL;
}
transpose function
float* transpose(float *matrix, int n, int m)
{
int i = 0;
int j = 0;
float num;
float *transposed=(int*) malloc(sizeof(int)*n*m);
while(i < n-1)
{
while(j < m-1)
{
num = *(matrix+i*m+j);
*(transposed+j*m+i)= num;
j++;
}
i++;
}
return transposed;
}
print fucntion
void print(float *matrix, int n, int m)
{
int i = 0;//row counter
int j = 0;//col counter
for(i = 0; i < n; i++){
printf("\n");
for(j = 0; j < m; j++){
printf("%f ", *(matrix + i*n + j));
}
}
}
Example input:
1 2 3
4 5 6
Output:
1.000000 0.000000
2.000000 3396.580087
-0.000000 0.000000
Part of the problem was your print function
Here is a version of your functions that works:
float* transpose(float *matrix, int n, int m)
{
int i = 0;
int j = 0;
float num;
float *transposed=malloc(sizeof(float)*n*m);
while(i < n) {
j = 0;
while(j < m) {
num = *(matrix + i*m + j);
*(transposed + i+n*j) = num; // I changed how you index the transpose
j++;
}
i++;
}
return transposed;
}
void print(float *matrix, int n, int m)
{
int i = 0;//row counter
int j = 0;//col counter
for(i = 0; i < n; i++){
printf("\n");
for(j = 0; j < m; j++){
printf("%f ", *(matrix + i*m + j)); // Changed from n to m
}
}
}
There were a few things.
Use sizeof(float) instead of sizeof(int)
Your loop should be i < n and j < m instead of i < n-1 and j < m-1 and finally you need to reset j to zero every time
The matrix indexes in inner most loop of your transpose function was incorrect
Your print function was using the wrong variable in the multiplication
Also it is generally considered bad practice to cast the result of malloc in C.