C - Sort float array while tracking indexes

I have an array of 3 floating point values:

float norms[3]; norms[0] = 0.4; norms[1] = 3.2; norms[2] = 1.7; 

I want to sort this array in descending order, tracking the original indexes of the values โ€‹โ€‹in the array.

In other words, given the array norms[] = {0.4, 3.2, 1.7} with the corresponding indices {0, 1, 2} , I basically want to get an array of the corresponding ints that reflects the initial positions of the float values โ€‹โ€‹in norms[] after the descending Sort. In this case, it will be {1, 2, 0} .

What is the best / cleanest way to achieve this?

+9
c sorting arrays
source share
4 answers

Use a structure to store the value and index, and then sort by value.

 struct str { float value; int index; }; int cmp(const void *a, const void *b) { struct str *a1 = (struct str *)a; struct str *a2 = (struct str *)b; if ((*a1).value > (*a2).value) return -1; else if ((*a1).value < (*a2).value) return 1; else return 0; } int main() { float arr[3] = {0.4, 3.12, 1.7}; struct str objects[3]; for (int i = 0; i < 3; i++) { objects[i].value = arr[i]; objects[i].index = i; } //sort objects array according to value maybe using qsort qsort(objects, 3, sizeof(objects[0]), cmp); for (int i = 0; i < 3; i++) printf("%d ", objects[i].index); //will give 1 2 0 // your code goes here return 0; } 
+9
source share

The cleanest way I can think of is to create a structure containing both a float and an index.

 typedef struct str { float val; int index; } str; 

then create an array of this structure and sort it according to val .

+4
source share

Just use any sorting algorithm to โ€œsmooth outโ€ the original array access. Bubblesort example

 int len = 3; bool switched = false; float myFloatArr[3]; int myFloatIndex[3] = {0, 1, 2}; do { switched = false; for(i = 1; i < len; i++) { if(myFloatArr[myFloatIndex[i - 1]] < myFloatArr[myFloatIndex[i]]) { int temp = myFloatIndex[i]; myFloatIndex[i] = myFloatIndex[i - 1]; myFloatIndex[i - 1] = temp; switched = true; } } } while(switched); 
+2
source share

The following solution will not work in a multi-threaded context, as it uses a global variable. It is also assumed that the arguments to the function have a well-defined distance, which can be expressed as an integer.

 #include <stdio.h> #include <stdlib.h> static int p_distance = 0; /* * Compares not just p1 and p2, but the floats i and j, then p1 and p2 are swapped * by the qsort algorithm internally. */ static int indexed_compare(const void *p1, const void *p2) { float i = *((float *)(p1 - p_distance)); float j = *((float *)(p2 - p_distance)); if (i > j) return (1); if (i < j) return (-1); return (0); } /* * The data can be const, we will only sort the indices through qsort. */ void order(int n, const float *data, int *indices) { p_distance = (void*)indices - (void*)data; qsort((void*)indices, n, sizeof(float), indexed_compare); } /* * Test procedure. Result will be printed as sorted values of test. The array test * itself will be kept in-tact. The array indices will be updated to point to values * in test from small to large. That is, indices[0] becomes 3. */ int main() { float test[5] = {0.3, 0.5, 0.2, 0.1, 0.4}; int indices[5] = {0, 1, 2, 3, 4}; for (int i = 0; i < 5; ++i ) { printf("%f ", test[i]); } printf("\n"); order(5, test, indices); for (int i = 0; i < 5; ++i ) { printf("%i ", indices[i]); } printf("\n"); for (int i = 0; i < 5; ++i ) { printf("%f ", test[indices[i]]); } printf("\n"); return 0; } 

It also has its advantages. No structures are required. No copying around. There are no temporary variables. Just an array of indexes with incremental 1: N values โ€‹โ€‹to start with and

0
source share

All Articles