C语言 对数组进行虚拟排序,只存储顺序



我已经得到了这段代码,但它不应该工作。我需要按降序对'val'数组进行虚拟排序,并将顺序存储在'order'数组中。

#include <stdio.h>
#define NUM_J_DIRS 4
#define FRAC_LEFT 0
#define FRAC_RIGHT 1
#define FRAC_FORWARD 2
#define FRAC_BACK 3
#define FIRST 0
#define SECOND 1
#define THIRD 2
#define FOURTH 3
struct iv
{
int index;
float value;
};
struct Fractions
{
int order[NUM_J_DIRS];    //this is where we store order of 'val'
float val[NUM_J_DIRS];    //once declared, this don't change
int enabled[NUM_J_DIRS];  //once declared, this don't change
};
int main ()
{
struct Fractions fractions;   
struct iv iv[NUM_J_DIRS];
fractions.val[FRAC_LEFT] = 0.1;
fractions.val[FRAC_RIGHT] = 1.0;
fractions.val[FRAC_FORWARD] = 1.0;
fractions.val[FRAC_BACK] = 0.5;
// populate iv from val 
for (int i = 0; i < NUM_J_DIRS; i++)
{
iv[i].index = i;
iv[i].value = fractions.val[i];
}
// sort kv by value 
for (int i = 0; i < NUM_J_DIRS; i++)
{
for (int j = i + 1; j < NUM_J_DIRS; j++)
{
if (iv[i].value < iv[j].value)
{
struct iv temp = iv[i];
iv[i] = iv[j];
iv[j] = temp;
}
}
}
// set order 
for (int i = 0; i < NUM_J_DIRS; i++)
{
fractions.order[iv[i].index] = i;
}
printf("order = %i, dir: %i, the value was: %fn",
FIRST, fractions.order[FIRST], fractions.val[fractions.order[FIRST]]);
printf("order = %i, dir: %i, the value was: %fn", 
SECOND, fractions.order[SECOND], fractions.val[fractions.order[SECOND]]);
printf("order = %i, dir: %i, the value was: %fn", 
THIRD, fractions.order[THIRD], fractions.val[fractions.order[THIRD]]);
printf("order = %i, dir: %i, the value was: %fn", 
FOURTH, fractions.order[FOURTH], fractions.val[fractions.order[FOURTH]]);
return 0;
}

输出:

order = 0, dir: 3, the value was: 0.500000
order = 1, dir: 0, the value was: 0.100000
order = 2, dir: 1, the value was: 1.000000
order = 3, dir: 2, the value was: 1.000000

但是应该输出:

order = 0, dir: 1, the value was: 1.000000
order = 1, dir: 2, the value was: 1.000000
order = 2, dir: 3, the value was: 0.500000
order = 3, dir: 0, the value was: 0.100000

dir 1和dir 2的顺序是可以互换的,因为它们具有相同的值。相同值的方向顺序不重要。

上面的代码应该可以工作,但是没有。我花了无数的时间想知道为什么不可以。

iv进行排序后,元素按值降序排列,每个元素在fractions.val数组中都有对应的索引。iv[0].index给出最大元素的索引,iv[1].index给出次大元素的索引,等等。因此,当您读取它时,您希望order的第一个元素从iv的第一个元素中取出index,从第二个元素中取出第二个元素,以此类推。但这不是它的意思:

// set order 
for (int i = 0; i < NUM_J_DIRS; i++)
{
fractions.order[iv[i].index] = i;
}

你已经颠倒了iiv[i].index的意义。你真正需要的是

for (int i = 0; i < NUM_J_DIRS; i++) 
{
fractions.order[i] = iv[i].index;
}

在我做了这个更改之后,你的程序的输出将为我按降序打印这些值。

声明这是你的比较函数:

int compareFunction(const void *p1, const void *p2, void *arg) {
struct Fractions* f = (struct Fractions*)arg;
int index1 = *(int*)p1;
int index2 = *(int*)p2;
if (f->val[index1] < f->val[index2]) {
return 1;
}
if (f->val[index1] > f->val[index2]) {
return -1;
}
return 0;
}

然后对"顺序"进行排序。基于"值"的现有顺序的数组。数组:

for (int i = 0; i < NUM_J_DIRS; i++) {
fractions.order[i] = i;    
}
qsort_r(fractions.order, NUM_J_DIRS, sizeof(int), &fractions);

通过在源文件的顶部添加#include <stdlib.h>来获得qsort_r

最新更新