I need to check between two arrays if they are reversed, e.g. A[3] = {1, 2, 3} and B[3] = {3, 2, 1}
Returning zero if A is not the reverse of B of a given length, and 1 otherwise.
Here is what I managed to do for now
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int* input_array(int);
int areReversed(int*, int*, int);
int main()
{
int n = 0;
int* A, * B;
printf("please enter the size of arrays: \n");
scanf("%d", &n);
printf("please enter elements of the first array: \n");
A = input_array(n);
printf("please enter elements of the second array: \n");
B = input_array(n);
areReversed(A, B, n) ? printf("Arrays are the opposite to one another.\n") : printf("Arrays are not the opposite to one another.\n");
free(A); free(B);
}
int areReversed(int* A, int* B, int n) {
int i = 0, j = n-1;
int reverse = 0;
if (n > 1)
{
for (i = 0, j = 0; i < n && j >= 0; i++, j--)
{
if (A[i] == B[j])
{
return areReversed(A + 1, B + 1, n);
}
if (A[i] != B[j])
return 0;
}
return 1;
}
}
`
but sadly its not working and I have tried so many things...
even if you can give hints its will be awesome
areReversed can be simply:
int areReversed(int *A, int *B, int n)
{
return n == 0 || A[0] == B[n-1] && areReversed(A+1, B, n-1);
}
This works:
If n is zero, the two arrays are trivially reverses of each other, since both are empty. (We expect n is not negative.)
Otherwise, we compare the first element of A to the last element of B. If they are unequal, this == and the && fail (produce zero for “false”), and “false” is returned, since the arrays are not reverses of each other.
If they are equal, we also require the rest of the arrays to be reversed, which is handled by a recursive case: The last n-1 elements of A (starting at A+1) must be the reverse of the first n-1 elements of B (starting at B).
With recursion the key is:
To have a robust terminating condition that will be met, and which has a definitive answer.
The problem is a function of a smaller but identical problem.
In this case, the terminating condition is when the length of the arrays n is zero (return true), or when A[0] != B[n-1] (return false)
For an array length n where the two opposite ends are equal (A[0] == B[n-1]), A may be the reverse of B, so you turn the problem into a smaller one and test that. The smaller problem is "one-in" from each end of each array - i.e.:
areReversed( &A[1], B, n - 1 ) ;
If you were doing this iteratively rather then recursively, the "smaller" test after comparing A[0] with B[n-1] would be to compare A[1] with B[n-2]. In recursion only one pair is tested, but the recursive call modifies the parameters to achieve the same effect. So here the recursive call's A is the parent calls &A[1] (or A + 1 if you like - I don't), and the array length is one shorter so that the recursive call's B[n-1] is the parent calls B[n-2].
So:
#include <stdio.h>
#include <stdbool.h>
bool areReversed( int* A, int* B, int n)
{
int is_reverse = false ;
if( n == 0 )
{
is_reverse = true ;
}
else if( A[0] == B[n-1] )
{
is_reverse = areReversed( &A[1], B, n - 1 ) ;
}
return is_reverse ;
}
int main()
{
int A1[] = {1, 2, 5, 14, 9, 3} ;
int B1[] = {3, 9, 14, 5, 2, 1} ;
int A2[] = {1, 2, 5, 14, 9, 3} ;
int B2[] = {3, 9, 14, 5, 2, 7} ;
bool R1 = areReversed( A1, B1, sizeof(A1) / sizeof(*A1) ) ;
bool R2 = areReversed( A2, B2, sizeof(A2) / sizeof(*A2) ) ;
printf( "A1 %s the reverse and B1\n", R1 ? "is" : "is not" ) ;
printf( "A2 %s the reverse and B2\n", R2 ? "is" : "is not" ) ;
}
Outputs:
A1 is the reverse and B1
A2 is not the reverse and B2
And to demonstrate its function with an odd number of elements:
int A1[] = {1, 2, 5, 99, 14, 9, 3} ;
int B1[] = {3, 9, 14, 101, 5, 2, 1} ;
int A2[] = {1, 2, 5, 100, 14, 9, 3} ;
int B2[] = {3, 9, 14, 100, 5, 2, 1} ;
Output then is:
A1 is not the reverse and B1
A2 is the reverse and B2
I recommend that to understand recursion, you use your debugger to step through the code, stepping into each recursive call to observe the "smaller problem" and the meeting the terminating condition, and stepping-out to observe the "unwinding" of the algorithm and final return. In any event you should learn effective use of a debugger - it is a great learning tool to observe the precise behaviour of code and state of variables as well as a debugging aid.
I would also suggest that while a simple function such as this is a useful way of exploring recursion as a concept, it is also trivially implemented using iteration and should probably be done that way in practice. Some problems are much less amenable to iteration and lend themselves to recursion. I'd reserve recursion for such problems - binary search trees, and flood-fill for example spring to mind, though even then recursion is not required, merely simpler.
The problem with recursion is that it has a non-deterministic call-stack requirement and the call-stack is a finite resource - you can literally get a _stack-overflow. In your test case where the data is provided at runtime and is of unlimited length, a malicious or unwary user could cause a stack-overflow with no means in your code to protect against such an attack or misuse.
Let's at first start with your function declaration.
int areReversed(int*, int*, int);
Within the function the passed arrays are not changed are they?
So the corresponding first two function parameters should be declared with the qualifier const
int areReversed( const int *, const int *, int);
Also sizes of entities in C are values of the type size_t. So the third parameter should have the type size_t
int areReversed( const int *, const int *, size_t );
And at last it is a bad idea to use upper case letters as identifiers.
Further, the function returns logical true if either the third parameter is equal to 0 or when the first element of the first array is equal to the last element of the second array and this condition is valid for other elements of the two arrays in recursive calls of the function. Thus it is enough to write only one return statement with the logical expression as described above.
So the function can be defined the following way
int areReversed( const int *a, const int *b, size_t n )
{
return n == 0 || ( a[0] == b[n - 1] && areReversed( a + 1, b, n - 1 ) );
}
But you can reduce the number of recursive calls of the function if you will compare the first element of the first array with the last element of the second array and vice versa when you will compare the last element of the first array with the first element of the second array.
In this case the function will look the following way.
int areReversed( const int *a, const int *b, size_t n )
{
return ( n == 0 ) ||
( n == 1 && a[0] == b[0] ) ||
( a[0] == b[n - 1] && a[n - 1] == b[0] && areReversed( a + 1, b + 1, n - 2 ) );
}
But what to do if the arrays have a different element type?
In this case you have to write another function when for example the array element type is for example double. And moreover you will have to name the function differently that will only confuse readers of your code.
Unfortunately you may not overload functions in C as you may do in C++.
In this case the approach to solve the problem is the same as the approach used in such C standard functions as bsearch and qsort.
That is in this case you have to deal with pointers of the type const void * and to use an auxiliary function that will convert the pointers of the type const void * to the appropriate pointer types.
In this case a general function can look the following way as it is shown in the demonstration program below..
#include <stdio.h>
int areReversed( const void *a, const void *b,
size_t nmemb, size_t size,
int cmp( const void *, const void * ) )
{
return ( nmemb == 0 ) ||
( nmemb == 1 && cmp( a, b ) ) ||
( cmp( a, ( const char * )b + ( nmemb - 1 ) * size ) &&
cmp( b, ( const char * )a + ( nmemb - 1 ) * size ) &&
areReversed( ( const char * )a + size, ( const char * )b + size, nmemb - 2, size, cmp ) );
}
static inline int cmp( const void *a, const void *b )
{
return *( const int * )a == *( const int * )b;
}
int main( void )
{
enum { N = 7 };
int a[N] = { 1, 4, 6, 7, 5, 3, 2 };
int b[N] = { 2, 3, 5, 7, 6, 4, 1 };
printf( "The arrays are reversed relative to each other is %s.\n",
areReversed( a, b, N, sizeof( int ), cmp ) ? "true" : "false" );
}
Opposite to C in C++ you could just use the standard algorithm std::equal . For example a non-recursive function can look like
#include <iostream>
#include <iterator>
#include <algorithm>
template <typename T1, typename T2>
bool areReversed( const T1 &a, const T2 &b )
{
return std::size( a ) == std::size( b ) &&
std::equal( std::begin( a ), std::end( a ), std::rbegin( b ) );
}
int main()
{
enum { N = 7 };
int a[N] = { 1, 4, 6, 7, 5, 3, 2 };
int b[N] = { 2, 3, 5, 7, 6, 4, 1 };
std::cout << "The arrays are reversed relative to each other is "
<< ( areReversed( a, b ) ? "true" : "false" ) << '\n';
}
Bear in mind that if you say that you know C and you do not know C++ and vice versa that you know C++ and you do not know C then usually it means that you know neither C nor C++.:)
Related
#include <stdio.h>
#include <math.h>
int prod(int arr[], int n) {
if (arr[n-1] < 0) {
return 1;
}
return ((arr[n-1]) * (prod(arr[n-2] , n)));
}
int main( int argc, char* args[] ) {
int arr[] = {2 , 3};
printf("%d" , prod(arr , 2));
}
i keep getting pointer related errors but have no idea what to change, any help? The code is supposed to use the recursive function to get the product of all integers equal or over 0 in the array.
I guess the condition for termination of recursion should be:
if (n-1 < 0) {
return 1;
}
It can be reformulated as:
if (n <= 0) {
return 1;
}
What means that product of entries of empty array is 1.
Moreover, expression that goes deeper should be:
return arr[n-1] * prod(arr , n - 1);
The final code could be:
int prod(int arr[], int n) {
if (n == 0)
return 1;
return arr[n-1] * prod(arr, n - 1);
}
There should be assignment in the prod function with something like this:-
n=n-1
You are not decreasing the value of n anywhere.
This function is incorrect.
int prod(int arr[], int n) {
if (arr[n-1] < 0) {
return 1;
}
return ((arr[n-1]) * (prod(arr[n-2] , n)));
}
For starters this if statement
if (arr[n-1] < 0) {
return 1;
}
does not make a sense.
It seems you mean
if ( n-1 < 0) {
return 1;
}
In this expression
prod(arr[n-2] , n)
the first argument is a scalar object of the type int. That is arr[n-2] is an element of an array. Also the second argument shall be decremented that is you have to use the expression n - 1.
But apart from this there are several other drawbacks.
For starters a product of elements of an array can be too big to fit in an object of the type int, You should use at least the type long long int as the return function type or maybe the float type long double.
Secondly as the array is not being changed within the function then the first parameter should have the qualifier const.
The user can pass as second argument the value 0. In this case it will look strange that the function returns 1.
Thus the function should look at least like
long long int prod( const int arr[], size_t n )
{
return n == 0 ? 0 : ( n == 1 ? arr[n-1] : arr[n-1] * prod( arr, n - 1 ) );
}
Here is a demonstrative program
#include <stdio.h>
long long int prod( const int arr[], size_t n )
{
return n == 0 ? 0 : ( n == 1 ? arr[n-1] : arr[n-1] * prod( arr, n - 1 ) );
}
int main(void)
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf( "%lld\n" , prod( arr , sizeof( arr ) / sizeof( *arr ) ) );
return 0;
}
The program output is
3628800
I tried to solve a C coding problem Two Sum in Online coding platform LeetCode
I am not able to return the integer pointer size.
Question:
Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
int i,j,sum=0,n1=0,n2=0,sz=1;
int *re;
re = (int*)malloc(sizeof(returnSize));
for(i=0;i<numsSize;i++){
if(sum==target){
break;
}
n1 = i;
for(j=i+1;j<numsSize;j++){
sum = nums[i]+nums[j];
if(sum==target){
n2 = j;
re[0] = n1;
re[1] = n2;
break;
}
}
}
return re;
}
“I expect the output of nums = [2, 7, 11, 15], target = 9, to be [0, 1], but the actual output is ]”
The interface of the function is designed to provide a two-part result, the array and its size.
You are not supposed to return the array by overwriting returnSize.
You are supposed to return the size of the returned array by writing it to the int variable referred by the pointer returnSize (and probably check that it is not a NULL pointer).
The array (i.e. the newly malloced pointer) is supposed to be returned via return, which of course you do. But doing that by overwriting return parameter pointer is what indirectly causes a problem here. (A mre would be required to trace the observed problem to this.)
By the way, I spotted this simply by seeing that you ignore and overwrite one of the parameters, the pointer. If that were correct, then the interface of the function would be inefficient. That can be the case, but usually not for challenges.
I can not reproduce the problem for the provided array. But in any case the function is incorrect..
Instead of this statement (where the argument of the malloc call does not make sense)
re = (int*)malloc(sizeof(returnSize));
^^^^^^^^^^^
there should be
re = (int*)malloc(sizeof( sizeof( int ) * *returnSize ));
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Though the parameter returnSize is redundant because the array according to your description has a fixed size equal to 2.
Moreover there is an unused variable sz=1
The function can invoke undefined behavior because in the case when the target is equal to 0 then the dynamically allocated array is not initialized and has indeterminate values because there is exit from the loop.
for(i=0;i<numsSize;i++){
if(sum==target){
break;
}
// ...
There is no need to dynamically allocate an array. You could return a structure of two elements.
The first parameter should be declared with the qualifier const.
The function can be written simpler and more clear and readable.
#include <stdio.h>
struct PairIndices
{
size_t first;
size_t second;
};
struct PairIndices twoSum( const int *a, size_t n, int target )
{
struct PairIndices pair = { n, n };
for ( size_t i = 0; i < n && pair.first == n ; i++ )
{
size_t j = 1;
while ( j < n && a[i] + a[j] != target ) j++;
if ( j != n )
{
pair.first = i;
pair.second = j;
}
}
return pair;
}
int main(void)
{
int a[] = { 2, 7, 11, 15 };
const size_t N = sizeof( a ) / sizeof( *a );
int target = 9;
struct PairIndices pair = twoSum( a, N, target );
if ( pair.first != N )
{
printf( "a[%zu] + a[%zu] == %d\n", pair.first, pair.second, target );
}
else
{
printf( "There are no two elements in the array "
"sum of which is equal to %d\n", target );
}
return 0;
}
The program output is
a[0] + a[1] == 9
I need to swap the values of 2 arrays in a function. The problem is I can change anything in the main, just the function itself. It should recive 2 integer arrays, and swap those. The problem is, that I don't know the size of the arrays, and for my understading they can even be in diffrent sizes. Trying this code:
int main()
{
int size = 4; //Please notice that I'm using this only to print the array
int a[] = {1,2,3,4};
int b[] = {5,6,7,8};
printArr(a,"a",size);
printArr(b,"b",size);
swapArray(a,b);
printf("Swapped:\n");
printArr(a,"a",size);
printArr(b,"b",size);
}
and this function:
void swapArray(int **a,int **b)
{
int *p = *a;
*a = *b;
*b = p;
}
while printArr simply prints the array:
void printArr(int arr[],char name[],int size)
{
printf("%s:\t",name);
for(int i=0;i<size;i++){
printf("%d\t",arr[i]);
}
printf("\n");
}
I got a really weird result:
a: 1 2 3 4
b: 5 6 7 8
Swapped:
a: 5 6 3 4
b: 1 2 7 8
I would like to understand why it happens, and not only a working solution.
Thank you :)
In this call
swapArray(a,b);
the argument expressions have the type int * while the function parameters have the type int **. There is no implicit conversion from the type int * to the type int **. So the compiler shall issue a diagnostic message.
In any case the swap function as it is implemented does not make sense. Your program has undefined behavior at least because it tries to swap pointers instead of the arrays themselves.
Take into account that arrays are not pointers though in expressions with rare exceptions they indeed are implicitly converted to pointers to their first elements.
To swap elements of two arrays you have to swap each pair of elemenets separatly.
And you have to supply the number of elements in the arrays. Otherwise the arrays need to have a sentinel value.
Here is a demonstrative program that shows how the function swap can be defined.
#include <stdio.h>
void printArr( const int a[], size_t n, const char *s )
{
printf( "%s:\t", s );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
void swapArray( int *a, int *b, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
int tmp = a[i];
a[i] = b[i];
b[i] = tmp;
}
}
int main(void)
{
enum { N = 4 };
int a[N] = { 1, 2, 3, 4 };
int b[N] = { 5, 6, 7, 8 };
printArr( a, N, "a" );
printArr( b, N, "b" );
putchar( '\n' );
swapArray( a, b, N );
printArr( a, N, "a" );
printArr( b, N, "b" );
putchar( '\n' );
return 0;
}
Its output is
a: 1 2 3 4
b: 5 6 7 8
a: 5 6 7 8
b: 1 2 3 4
You could swap visual representations of original arrays using pointers. But in this case the arrays themselves will not be swapped.
Consider the following program.
#include <stdio.h>
void printArr( const int a[], size_t n, const char *s )
{
printf( "%s:\t", s );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
void swapArray( int **a, int **b )
{
int *tmp = *a;
*a = *b;
*b = tmp;
}
int main(void)
{
enum { N = 4 };
int a[N] = { 1, 2, 3, 4 };
int b[N] = { 5, 6, 7, 8 };
printArr( a, N, "a" );
printArr( b, N, "b" );
putchar( '\n' );
int *pa = a;
int *pb = b;
swapArray( &pa, &pb );
printArr( pa, N, "pa" );
printArr( pb, N, "pb" );
putchar( '\n' );
printArr( a, N, "a" );
printArr( b, N, "b" );
putchar( '\n' );
return 0;
}
Its output is
a: 1 2 3 4
b: 5 6 7 8
pa: 5 6 7 8
pb: 1 2 3 4
a: 1 2 3 4
b: 5 6 7 8
As you see the arrays were not swapped. However the pointers that point to first elements of the arrays were swapped. Using the pointers you can simulate swapping of arrays.
Opposite to C C++ has a template function std::swap for arrays that can be called indeed simply like
std::swap( a, b );
I guess on your platform the size of the pointer is 64 bit, and the size of an in is 32 bit.
When calling swapArray, the compiler implicitly reinterprets your arrays of int as an array of pointers. (These are pointers to int but this is irrelevant here).
swapArray then just swaps the first element of these pointer arrays.
Luckily your original int arrays are large enough so that no illegal access happens.
Since pointer is 64 bit is corresponds to two int which get swapped.
In C an array is not a single "thing" you can swap. You will need to swap it element-by-element.
The only case in which you can swap these array "things" in one time is if they are pointers to arrays.
int *a = malloc(n*sizeof(int));
int *b = malloc(n*sizeof(int));
int *tmp;
tmp=a; a=b; b=tmp;
The problem is, that I don't know the size of the arrays, and for my
understading they can even be in diffrent sizes.
Then let's do it with different sizes! But I don't want to support a "C&P behaviour" and hence I won't provide a complete program. I just provide some short cuts and explain them.
As already shown in the other answers you need to specify the size of an array x[] if you pass it to a function like e.g. swapArray().
But in your main() you are statically defining your two arrays. Let me do it this way:
int a[] = { 1, 2, 3 };
int b[] = { 5, 6, 7, 8, 9 };
Here we defined two arrays statically with different sizes. But the sizes are known. The compiler knows them at build/compile time. There's a build time operator sizeof() which returns the size of a type or a variable at compile time. Hence we can use sizeof(a) to get the size of array a.
But there's one light issue: The "unit" returned by sizeof() is bytes and not elements. Hence we must divide it by the size of the type (here: int) to get the actual number of elements in the array:
size_t size_a = sizeof(a) / sizeof(int);
(Actually this means that for e.g. size_a it will end up with 12 / 4 which will actually write a 3 as a pre-calculated value in your compiled program. I assume here that int takes up 4 bytes.)
For your swapping function you must pass the lower value of both size_a and size_b. We can simply get the minimum value with this:
size_t size_min = (size_a < size_b) ? size_a : size_b;
In case that size_a is smaller then size_a is taken. Otherwise size_b. This is calculated at run time. (If you want to do this at build time because of static values then you need to use preprocessor directives.)
Calling printArr() is straight forward, just pass the correct size:
printArr(b,"b",size_b);
And for swap we use size_min:
swapArray(a, b, size_min);
That's it for handling arrays with different sizes.
A very simple swapArray() could look like this:
void swapArray(int a[],int b[], size_t size) { // or int *a, int *b...
while (size > 0) {
size--;
int tmp = a[size];
a[size] = b[size];
b[size] = tmp;
}
}
We don't need to define an additional loop variable because we can simply use size and decrease it until it reaches 0.
I want to retrieve the index in the array where the value is stored. I know the value of the item at that point in the array. I'm thinking it's similar to the findIndex function in c#.
For example, array[2] = {4, 7, 8}. I know the value is 7, how do I get the value of the index, 1, if I know it is at array[1]?
For example you can define the corresponding function the following way
size_t FindIndex( const int a[], size_t size, int value )
{
size_t index = 0;
while ( index < size && a[index] != value ) ++index;
return ( index == size ? -1 : index );
}
Also instead of type size_t you can use type int.
But the better way is to use standard algorithm std::find or std::find_if declared in header <algorithm> provided that you use C++
For example
#include <algorithm>
#include <iterator>
int main()
{
int a[] = { 4, 7, 8 };
auto it = std::find( std::begin( a ), std::end( a ), 7 );
if ( it != std::end( a ) )
{
std::cout << "The index of the element with value 7 is "
<< std::distance( std::begin( a ), it )
<< std::endl;
}
}
The output is
The index of the element with value 7 is 1
Otherwise you have to write the function yourself as I showed abve.:)
If the array is sorted you can use standard C function bsearch declared in header <stdlib.h>
For example
#include <stdio.h>
#include <stdlib.h>
int cmp( const void *lhs, const void *rhs )
{
if ( *( const int * )lhs < *( const int * )rhs ) return -1;
else if ( *( const int * )rhs < *( const int * )lhs ) return 1;
else return 0;
}
int main()
{
int a[] = { 4, 7, 8 };
int x = 7;
int *p = ( int * )bsearch( &x, a, 3, sizeof( int ), cmp );
if ( p != NULL ) printf( "%d\n", p - a );
return 0;
}
First its important that the argument list contain size information for the array, i.e. passing a pointer to an array only does not provide enough information to know how many elements the array has. The argument decays into a pointer type with no size information to the function.
So given that, you could do something like this:
int findIndex(int *array, size_t size, int target)
{
int i=0;
while((i<size) && (array[i] != target)) i++;
return (i<size) ? (i) : (-1);
}
For small arrays this approach will be fine. For very large arrays, some sorting and a binary search would improve performance
Here's my version without a additional variable.
// Return index of element starting
// Return -1 if element is not present
int indexOf(const int elm, const int *ar, int ar_cnt)
{
// decreasing array count till it reaches negative
// arr_cnt - 1 to 0
while (ar_cnt--)
{
// Return array index if current element equals provided element
if (ar[ar_cnt] == elm)
return ar_cnt;
}
// Element not present
return -1; // Should never reaches this point
}
Hope the comments are self explanatory!
I'm trying to sort an array A whose elements are indexes. The indexes refer to another array B whose value will determine the order of A. So, I would like to sort A such that B[ A[i] ] is increasing.
For example:
A = [0, 1, 4, 5, 7]
B = [5, 3, 8, 2, 2, 7, 1, 6, 3, 9]
Sorted A would be
A' = [ 7, 4, 1, 0, 5 ]
Is this possible with C's built-in sort, or am I going to have to write my own implementation?
EDIT: These arrays are local function variables.
If you want to use qsort, the best thing to-do would be to re-wrap the indexes in A and the values in B into a struct, and then make a comparator based on a new array that struct. For instance:
typedef struct
{
int index_from_A;
int value_from_B;
} index_value_wrapper;
index_value_wrapper index_wrapper_array[5];
for (int i=0; i < 5; i++)
{
index_wrapper_array[i].index_from_A = A[i];
index_wrapper_array[i].value_from_B = B[A[i]];
}
int comparitor (const void* lhs, const void* rhs)
{
return (lhs.value_from_B - rhs.value_from_B);
}
Now you can run qsort on the struct array and from there you can extract the proper sorted sequence you desired for the original array A without having to use a custom sorting function.
If you have it available, qsort_r provides a way to do this. You can give it context information in an additional parameter. That context is passed to the comparison function. You can access that additional information to extract the desired sorting information.
The Microsoft compiler has a similar one: qsort_s
I think you can use qsort and a custom comparator
int comparator(const void *x, const void *y)
{
return ( b[*(int*)x] - b[*(int*)y] );
}
Create another array C of type struct { int a_value; int b_value}, initialise each element to the values of each index of a and the value looked up from b. Sort that, traverse the sorted C copying the a_values back into A.
Viola. No, that's a large violin. Voila!
Use your rule as the comparison function to qsort (as long as B is longer than A):
#include <stdio.h>
#include <stdlib.h>
int A[] = {0, 1, 4, 5, 7};
int B[]= {5, 3, 8, 2, 2, 7, 1, 6, 3, 9};
int my_cmp(const void *a_, const void *b_,void *arg_)
{
const int *a = a_, *b = b_;
if(B[*a] == B[*b])
return 0;
else if (B[*a] < B[*b])
return -1;
else
return 1;
}
int main(int argc,char *arga[])
{
int i;
qsort(A,sizeof A/sizeof A[0] ,sizeof A[0],my_cmp);
puts("Sorted A");
for(i = 0 ; i < sizeof A/sizeof A[0]; i++) {
printf("A[%d] : %d B[A[%d]] : %d\n",i,A[i],i,B[A[i]]);
}
return 0;
}
This gives:
$ ./a.out
Sorted A
A[0] : 4 B[A[0]] : 2
A[1] : 1 B[A[1]] : 3
A[2] : 0 B[A[2]] : 5
A[3] : 7 B[A[3]] : 6
A[4] : 5 B[A[4]] : 7
Available on many platforms is also qsort_r(on linux you'll have to #define _GNU_SOURCE before including <stdlib.h> to use it. Using that, you'd change the comparison function to e.g.
int my_cmp(const void *a_, const void *b_,void *arg_)
{
const int *a = a_, *b = b_, *arg = arg_;
if(arg[*a] == arg[*b])
return 0;
else if (arg[*a] < arg[*b])
return -1;
else
return 1;
}
And call qsort_r like
qsort_r(A,sizeof A/sizeof A[0] ,sizeof A[0],my_cmp,B);