What I want to achieve is to create a merged array of two sorted arrays, such as [0, 1, 2, 3, 4] + [2, 4, 6, 8, 10] => [0, 1, 2, 2, 3, 4, 4, 8, 10], by comparing the two elements in each array
And I am trying to apply such algorithm to dynamically allocated arrays and throwing pointer arguments to custom-made merge() function. Please refer to the following excerpt
int* merge(int*, int*);
int main(int argc, const char * argv[]) {
int* arrayA;
int* arrayB;
int* mergedArray;
int index;
arrayA = (int*) malloc(sizeof(int) * 5);
arrayB = (int*) malloc(sizeof(int) * 5);
//filling out the array A with number elements like [0, 1, 2, 3, 4]
for(index = 0; index < 5; index++){
*(arrayA + sizeof(int) * index) = index;
printf("%d", *(arrayA + sizeof(int) * index));
}
//filling out the array A with number elements like [2, 4, 6, 8, 10]
for(index = 0; index < 5; index++){
*(arrayB + sizeof(int) * index) = (index + 1) * 2;
printf("%d", *(arrayB + sizeof(int) * index));
}
printf("\n");
mergedArray = (int *) merge(arrayA, arrayB);
for(index = 0; index < 10; index++){
printf("%d", *(mergedArray + sizeof(int) * index));
}
return 0;
}
The merge functions is as follows
//My take on merge() function
int *merge(int *arrayA, int *arrayB) {
int *mergedArray;
int i = 0, j = 0, k = 0; // i for arrayA / j for arrayB / k for mergedArray
int arrayALength;
int arrayBLength;
mergedArray = (int *)malloc(sizeof(int) * 10);
arrayALength = 5;
arrayBLength = 5;
while (i < arrayALength && j < arrayBLength) {
printf("%d / %d\n", *(arrayA + (i) * sizeof(int)), *(arrayB + (j) * sizeof(int)));
if (*(arrayA + (sizeof(int) * i)) < *(arrayB + (sizeof(int) * j))) {
*(mergedArray + (k++ * sizeof(int))) = *(arrayA + (i++ * sizeof(int)));
printf("%d", *(mergedArray + (k - 1) * sizeof(int)));
} else {
*(mergedArray + (k++ * sizeof(int))) = *(arrayB + (j++ * sizeof(int)));
printf("%d", *(mergedArray + (k - 1) * sizeof(int)));
}
printf("\n");
}
for (; i < arrayALength; i++) {
*(mergedArray + (k++ * sizeof(int))) = *(arrayA + (i * sizeof(int)));
}
for (; j < arrayBLength; j++) {
*(mergedArray + (k++ * sizeof(int))) = *(arrayB + (j * sizeof(int)));
}
return mergedArray;
}
The result is...
01234
246810
0 / 2
0
1 / 2
1
2 / 2
2
2 / 4
2
4 / 4
4
4 / 0
0
4 / 1
1
4 / 2
2
0122401240Program ended with exit code: 0
If you take a look at the first line "01234" in the result, I am pretty confident that [0, 1, 2, 3, 4] is stored inside the memory where arrayA is pointing at, yet inside the merge() function if I print the corresponding element, it shows [0, 1, 2, 4], leaving out the element '3' in the middle.
Not only that the program's final result "0122401240" does show that there is logic fallacy in my code, which I could not find.
If you could see the logical error, please do not hesitate to point out one, and could you tell me why there was difference in elements in allocated memory?
Your code is really complex, you could simplify it a lot
A way to solve your issue is to make these two arrays contiguous so that you can handle it like a single array as shown in the code below
#include <stdlib.h>
#include <stdio.h>
int mysort(const void* a, const void* b){
return (*(int*)a-*(int*)b);
}
int main(){
int sz1= 5, sz2=5;
int* arr1 = malloc((sz1+sz2)*sizeof(int)); // Allocate for both arrays
int* arr2 = &arr1[sz1]; // Go to the 2nd array
my_fill(arr1); // Setup your arrays as you wish
my_fill(arr2);
qsort(arr1, sz1+sz2, sizeof(int), mysort); // Sort both arrays using the standard qsort.
}
Obviously, if you want to use a custom sorting algorithm such as merge sort, this is possible. You can replace qsort with your custom algorithm.
Your code should benefit from the fact that the input arrays are already sorted. Simply take the smallest value and copy it to the output array. For each input array maintain an index that tells you where the next unused element is.
Like:
#include <stdio.h>
#include <stdlib.h>
int* mergeSortedArraysToSingleSortedArray(int* arrA, size_t szA, int* arrB, size_t szB)
{
int* res = malloc((szA + szB) * sizeof *arrA);
if (res == NULL) return NULL;
size_t iA = 0;
size_t iB = 0;
size_t i = 0;
// Merge from A and B
while (iA < szA && iB < szB)
{
if (arrA[iA] <= arrB[iB])
{
res[i] = arrA[iA];
++iA;
}
else
{
res[i] = arrB[iB];
++iB;
}
++i;
}
// Take rest of A (if any)
while (iA < szA)
{
res[i] = arrA[iA];
++iA;
++i;
}
// Take rest of B (if any)
while (iB < szB)
{
res[i] = arrB[iB];
++iB;
++i;
}
return res;
}
int main(void)
{
int arrA[] = {0, 1, 2, 3, 4};
int arrB[] = {2, 4, 6, 8, 10};
size_t szA = sizeof(arrA)/sizeof(*arrA);
size_t szB = sizeof(arrB)/sizeof(*arrB);
int* arrMerged = mergeSortedArraysToSingleSortedArray(arrA, szA, arrB, szB);
if (arrMerged)
{
for (size_t i = 0; i < szA + szB; ++i)
{
printf("%d ", arrMerged[i]);
}
printf("\n");
}
return 0;
}
Output:
0 1 2 2 3 4 4 6 8 10
Related
This is the task I have got:
I need to write a function (not recursive) which has two parameters.
An array of integers.
An integer representing the size of the array.
The function will move the duplicates to an end of the array.
And will give the size of the different digits.
Example:
5 , 2 , 4 , 5 , 6 , 7 , 2, n = 7
we will get back 5 , 2 , 4 , 6 , 7 , 5 , 2 and 5
We must keep the original sort as it is (which means like in example 5 must)
It does not matter how we sort the duplicates ones but just keep the sort for the original array as it is)
The function has to print the number of different digits (like in example 5)
The the input range of numbers in array [-n,n]
I can only use 1 additional array for help.
It has to be O(n)
I tried it so many times and feel like am missing something. Would appreciate any advice/suggestions.
int moveDup(int* arr, int n)
{
int* C = (int*)calloc(n * 2 + 1, sizeof(int));
assert(C);
/*int* count = C + n;*/
int *D = arr[0];
int value = 0, count = 0;
for (int i = 0; i < n; i++)
{
value = arr[i];
if (C[value + n] == 0)
{
*D = arr[i];
D++;
count++;
}
C[value + n] = C[value + n] + 1;
}
while (1 < C[value + n])
{
*D = i;
D++;
C[value + n]--;
}
free(C);
return count;
}
This algorithm will produce the required results in O(n) arithmetic complexity:
Input is an array A with n elements indexed from A0 to An−1 inclusive. For each Ai, −n ≤ Ai ≤ n.
Create an array C that can be indexed from C−n to C+n, inclusive. Initialize C to all zeros.
Define a pointer D. Initialize D to point to A0.
For 0 ≤ i < n:
If CAi=0, copy Ai to where D points and advance D one element.
Increment CAi.
Set r to the number of elements D has been advanced from A0.
For −n ≤ i ≤ +n:
While 1 < CAi:
Copy i to where D points and advance D one element.
Decrement CAi.
Release C.
Return r. A contains the required values.
A sample implementation is:
#include <stdio.h>
#include <stdlib.h>
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int moveDuplicates(int Array[], int n)
{
int *memory = calloc(2*n+1, sizeof *Array);
if (!memory)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
int *count = memory + n;
int *destination = Array;
for (int i = 0; i < n; ++i)
// Count each element. If it is unique, move it to the front.
if (!count[Array[i]]++)
*destination++ = Array[i];
// Record how many unique elements were found.
int result = destination - Array;
// Append duplicates to back.
for (int i = -n; i <= n; ++i)
while (0 < --count[i])
*destination++ = i;
free(memory);
return result;
}
int main(void)
{
int Array[] = { 5, 2, 4, 5, 6, 7, 2 };
printf("There are %d different numbers.\n",
moveDuplicates(Array, NumberOf(Array)));
for (int i = 0; i < NumberOf(Array); ++i)
printf(" %d", Array[i]);
printf("\n");
}
here is the right answer, figured it out by myself.
int moveDup(int* arr, int n)
{
int* seen_before = (int*)calloc(n * 2 + 1, sizeof(int));
assert(seen_before);
int val = 0, count = 0, flag = 1;
int j = 0;
for (int i = 0; i < n; i++)
{
val = arr[i];
if (seen_before[arr[i] + n] == 0)
{
seen_before[arr[i] + n]++;
count++;
continue;
}
else if (flag)
{
j = i + 1;
flag = 0;
}
while (j < n)
{
if (seen_before[arr[j] + n] == 0)
{
count++;
seen_before[arr[j] + n]++;
swap(&arr[i], &arr[j]);
j++;
if (j == n)
{
free(seen_before);
return count;
}
break;
}
/*break;*/
j++;
if (j == n)
{
free(seen_before);
return count;
}
}
}
}
second right answer
int* mem = (int*)calloc(2 * n + 1, sizeof * arr);
assert(mem);
int* count = mem + n;
int* dest = arr;
for (i = 0; i < n; ++i)
{
if (count[arr[i]]++ == 0)
{
*dest = arr[i];
*dest++;
}
}
res = dest - arr;
for (i = -n; i <= n; ++i)
{
while (0 < --count[i])
{
*dest++ = i;
}
}
free(mem);
return res;
I have an array [1, 2, 3, 4, 5, 6, 7, 8] and I need to get [__, __, 1, 2, 3, 4, 5, 6] where I can put my new elements in the blank spaces. I tried to do it in a standard way:
int temp1 = arr[len - 1];
int temp2 = arr[len - 2];
for (int i = len - 1; i > 1; i -= 2) {
arr[i] = arr[i - 1];
arr[i - 1] = arr[i - 2];
}
arr[0] = temp1;
arr[1] = temp2;
but it seems to do nothing at all.
You're only moving elements by one space, not by two. Take a look at the following:
#include <stdio.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
int len = sizeof(arr) / sizeof(int);
printf("len = %d\n", len);
int temp1 = arr[len - 1];
int temp2 = arr[len - 2];
printf("temp1 = %d\n", temp1);
printf("temp2 = %d\n", temp2);
for(int i = len-1 ; i > 1 ; --i)
{
printf("Moving arr[%d] to arr[%d]\n", i-2, i);
arr[i] = arr[i-2];
}
arr[0] = temp1;
arr[1] = temp2;
for(int i = 0 ; i < len ; ++i)
printf("arr[%d] = %d\n", i, arr[i]);
}
onlinegdb here
EDIT
And if you'd rather do away with the loop and just copy the memory in one shot you can use:
#include <stdio.h>
#include <string.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
int len = sizeof(arr) / sizeof(int);
printf("len = %d\n", len);
int temp1 = arr[len - 1];
int temp2 = arr[len - 2];
printf("temp1 = %d\n", temp1);
printf("temp2 = %d\n", temp2);
memmove(((int *)arr)+2, arr, (len-2)*sizeof(int));
arr[0] = temp1;
arr[1] = temp2;
for(int i = 0 ; i < len ; ++i)
printf("arr[%d] = %d\n", i, arr[i]);
}
Note here that I've used memmove instead of memcpy because the source and destination buffers overlap. memmove handles this correctly, while memcpy is not required to do so.
onlinegdb here
I suppose that code rewrite right this way
int arr[8] = { 1,2,3,4,5,6,7,8 };
for( int i = 0 ; i < 8 ; i++ ){
arr[7-i] = arr[7-i-1];
}
for( int i = 0 ; i < 8 ; i++ ){
arr[7-i] = arr[7-i-1];
}
//here, arr[8] = { 1,1,1,2,3,4,5,6 }
//so, you can put new two elements in arr[0], arr[1]
the below might be useful for you,
#include <stdio.h>
#include <memory>
int main()
{
int temp1[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int temp2[10] = { 0 }; // to avoid garbage values in 0 & 1 positions or you may find a place holder to indicate empty
memcpy(&temp2[2], temp1, sizeof(temp1));
for (int i = 0; i < 10; ++i)
printf("%d ", temp2[i]);
}
How to separate the even position number of an array from the odd position number in C.
Example
int arr[]= {2,3,4,5,6,7,8,9,1};
int odd[]= {2,4,6,8,1};
int even[] = {3,5,7,9};
Use % to get the remainder. If the remainder is nonzero, then the index is odd, otherwise even. But index starts from 0 and not 1, thus the first element's index is 0 and is even. if you want to sort according to that (seems to be you do), add 1 to index.
#include <stdio.h>
int main() {
int arr[] = {2, 3, 4, 5, 6, 7, 8, 9, 1}; // our array
const size_t max_size = sizeof(arr) / sizeof(arr[0]);
int odd[max_size];
size_t odd_cnt = 0;
int even[max_size];
size_t even_cnt = 0;
for (size_t i = 0; i != max_size; ++i) {
if ((i + 1) % 2) { // if (i + 1) % 2 is nonzero, i + 1 is odd
odd[odd_cnt++] = arr[i];
} else {
even[even_cnt++] = arr[i];
}
}
for (size_t i = 0; i != odd_cnt; ++i) {
printf("%d ", odd[i]);
}
printf("\n");
for (size_t i = 0; i != even_cnt; ++i) {
printf("%d ", even[i]);
}
printf("\n");
return 0;
}
I am really stucked on this problem, my C code has worked very well using multidimensional arrays but i need to do the same using pointers but i'll describe the problem first.
Having the following matrix, i will get a number which will be the number of permutations (the number of swapping of columns that will move to the right and the last column will move to the first column).
For example
The number of column's permutations: 5
| 1 2 3 | -----> | 2 3 1 |
| 3 1 2 | -----> | 1 2 3 |
| 2 3 1 | -----> | 3 1 2 |
I wrote the following code using pointers, as you can see i build the matrix with multidimensional array and assign all of it into a pointer:
short elementMatrix[3][3] = {{1, 2, 3},
{3, 1, 2},
{2, 3, 1}};
short *element_matrix;
element_matrix = *elementMatrix;
int counter = 1;
while (counter <= 5)
{
for (int i = 0; i < 3; i++)
{
int temp = elementMatrix[i][PR.elem_mat_size - 1];
*outElementMatrix = *outElementMatrix + i * PR.elem_mat_size + PR.elem_mat_size - 1;
for (int j = 3 - 1; j >= 0; j--)
{
*(outElementMatrix + i * PR.elem_mat_size + j) = *(outElementMatrix + i * PR.elem_mat_size + j - 1);
if (j == 0)
{
*(outElementMatrix + i * PR.elem_mat_size + j) = *outElementMatrix;
}
}
}
counter++;
}
Since you want to swap out columns, it makes sense to have the pointers represent the columns. That way, you can swap a pointer to swap a column. So let's have an array of 3 pointers to a column.
short* col[3];
Each column consists of 3 shorts, so allocate that much memory.
for (int i = 0; i < 3; i++) {
col[i] = (short*)malloc(3 * sizeof(short));
}
Now to initialize the Matrix. This is a bit verbose, so if anyone knows a better way, edit away. :)
col[0][0] = 1; col[1][0] = 2; col[2][0] = 3;
col[0][1] = 3; col[1][1] = 1; col[2][1] = 2;
col[0][2] = 2; col[1][2] = 3; col[2][2] = 1;
Now we do the swap. Note how you need a temp variable, like Rishikesh Raje suggested. Also note that three swaps bring it back to the original, so instead of swapping n times, you only have to swap n % 3 times. Of course it's going to be pretty much instant with 5 or 2 swaps, but if you have to do like a billion, the difference should be noticeable.
for (int i = 0; i < 5; i++) {
short* temp = col[2];
col[2] = col[1];
col[1] = col[0];
col[0] = temp;
}
We assure that the result is correct by printing it:
for (int i = 0; i < 3; i++) {
printf("%d %d %d\n", col[0][i], col[1][i], col[2][i]);
}
You can consider the permutations as a rotation of each row in the matrix and, unless you have to somehow use the matrix after each step, calculate only the final result.
I'll use an extra buffer to help with the swaps.
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
// rotate the values of an array using a buffer to ease the swappings
void rotate_(size_t n, void *arr, void *tmp, size_t offset)
{
assert(n && arr && tmp && offset <= n);
// casting to perform pointer arithmetic
memcpy(tmp, (char *)arr + (n - offset), offset);
memmove((char *)arr + offset, arr, n - offset);
memcpy(arr, tmp, offset);
}
void rotate_columns_short(size_t r, size_t c, short mat[r][c], short *buf, int n)
{
// clamp the value of the offset to the number of columns
size_t offset = (n >= 0
? n % c
: c - -n % c) * sizeof(short);
// transform each row
for (short *row = &mat[0][0], *row_end = row + r * c;
row != row_end;
row += c)
{
rotate_(c * sizeof(short), row, buf, offset);
}
}
void print_matrix_short(size_t r, size_t c, short mat[r][c])
{
for (size_t i = 0; i < r; ++i)
{
for (size_t j = 0; j < c; ++j)
{
printf(" %hd", mat[i][j]);
}
puts("");
}
}
#define ROWS 3
#define COLS 3
int main(void)
{
short matrix[ROWS][COLS] = {{1, 2, 3},
{3, 1, 2},
{2, 3, 1}};
short buf[COLS];
print_matrix_short(ROWS, COLS, matrix);
puts("");
rotate_columns_short(ROWS, COLS, matrix, buf, 5);
print_matrix_short(ROWS, COLS, matrix);
}
The output beeing:
1 2 3
3 1 2
2 3 1
2 3 1
1 2 3
3 1 2
My problem is that when I create a local array in the function and return it, all the values in the array become assigned to the array's first value. So for an example, an array of size 4 with the values 3, 5, 11, 13 is returned. The array now only has the values 3, 3, 3, 3. I'm fairly new to coding, so any help would be appreciated.
uint8_t* half( const uint8_t array[],
unsigned int cols,
unsigned int rows )
{
int size = (cols / 2) * (rows / 2);
uint8_t *newarray = malloc( size * sizeof(int) );
float average;
for (int i = 0; i < (rows / 2); i++) {
for (int k = 0; k < (cols / 2); k++) {
average = (array[ (2*k) + (2*i*cols) ] + array[ ((2*k) + 1) + (2*i*cols) ] + array[ ((2*k) + 1) + ((2*i*cols) + cols) ] + array[ (2*k) + ((2*i*cols) + cols) ]) / 4.0;
newarray[k + (i * (cols / 2))] = (int)( round(average) );
}
}
return newarray;
}
int main () {
uint8_t *halfarray;
halfarray = half(testarray, test_width, test_height);
for (int i = 0; i < 4; i++) {
printf("values in array %d\n", *halfarray);
}
return 0;
}
Try changing this line:
printf("values in array %d\n", *halfarray);
to this:
printf("values in array %d\n", *halfarray);
halfarray++
Use pointer arithmetic at each iteration to increment the position of the non-constant pointer, thusly:
for (int i = 0; i < 4; i++, halfarray++) {
printf("values in array %d\n", *halfarray);
}