C 使用qsort同时对两个数组进行排序?

C 使用qsort同时对两个数组进行排序?,c,arrays,qsort,C,Arrays,Qsort,我可以对指向单词的指针数组进行排序,以便它们按字母顺序排列,问题是我还需要对整数数组(使用特定单词的次数)进行排序,以便整数与它们各自的单词位于同一位置: 我的代码: for (i = 0; i < numWords; i++) { // prints out the words and their frequency respectively printf("%s - %d\n", dictionary[i], frequency[i]); } //sorts the

我可以对指向单词的指针数组进行排序,以便它们按字母顺序排列,问题是我还需要对整数数组(使用特定单词的次数)进行排序,以便整数与它们各自的单词位于同一位置:

我的代码:

for (i = 0; i < numWords; i++) {
    // prints out the words and their frequency respectively
    printf("%s - %d\n", dictionary[i], frequency[i]); 
}

//sorts the dictionary so that the words are 'alphabetical'
qsort(dictionary, numWords, sizeof(char *), rstrcmp);  
printf("\nafter qsort\n");  //checkmark

for (i = 0; i < numWords; i++) {
    // prints the word list alphabetically, but the frequencies are no longer matched
    printf("%s - %d\n", dictionary[i], frequency[i]); 
}
标准的
qsort()。
除此之外,它如何知道(或如何告诉它)哪两个数组要并行排序

您要么必须更改数据结构(使用结构类型的数组),要么必须编写自己的排序函数。其中,更改数据结构可能更容易

还有另一种选择——但有点扭曲。您可以创建一个
int
数组,其中包含以下条目:

for (int i = 0; i < N; i++)
    index[i] = i;

“thunk”是作为第一个参数传递给比较器的指针。您可以将其与索引数组方案一起使用,将指向两个数组的指针传递到比较器中,这样就根本不需要文件范围变量。但是,您仍然无法进行两次独立的交换,因此必须使用索引数组方案。

您可能会发现一种对并行数组排序有用的方法:创建一个整数数组(
size\t
s严格正确),并用值0到
numWords-1
对其进行初始化。然后
qsort
使用一个比较函数对该数组进行排序,该比较函数执行strcmp(dictionary[*(int*)p1),dictionary[*(int*)p2]
,然后使用排序后的索引数组同时排列
dictionary
frequency
(通过复制很容易做到这一点,或者通过互换稍微不那么容易做到:这是后者的一个例子)


Turix可能有更好的解决方案——使用结构数组而不是两个数组可以避免整个问题。

一个简单的方法是使用结构来存储单词/频率对,然后对这些结构数组进行排序

例如:

struct WordFrequency
{
    const char * word;
    int frequency;
} wordFreqs[numWords];        // Assumes numWords is static/global and constant...
然后:


理想情况下,您可以使用一个哈希表/映射,其中单词是键,频率是值,然后根据键进行排序。一个简单的方法是使用一个结构来存储单词/频率对,然后对这些结构的数组进行排序。@Turix我可能有点麻烦,我不擅长指针以及何时使用它们;我几乎不知道顺便,想展示一个如何初始化结构数组的例子吗?@nobodyImportant好的,我在下面添加了一些示例代码作为答案。+1用于就地交换算法的外部参照。@hobbs你能展示qsort中使用的函数定义,它将访问本地字符串数组吗?对于GNU系统,还有
void qsort\r(void*,size\u t,size\u t,int(*)(const void*,const void*,void*),void*arg);
有一个不同的原型。@mafso:有趣。一致性-谁需要一致性?仅供参考(我不得不看):GNU版本的设计似乎只需要实现一个功能(参见glibc),而且因为…,嗯,(?).哦,为了完整起见,微软的CRT和C11附录K规定了
qsort_s
,其中有一个迷人的想法,即将上下文指针作为前者中比较函数的第一个参数,而后者中的最后一个参数。你说得对,没有人需要一致性!@mafso:研究得好。我已经开始对它不感兴趣了过去和现在是附录K。你是对的。的Microsoft规范遵循BSD变量
qsort\u r()
。“标准”版本遵循GNU变量
qsort\u r()
。这是另一个对C的扩展中用意良好但定义不一致的函数持怀疑态度的原因。感谢这些指针!请记住:MS和BSD版本采用相同类型的比较函数,但在其他方面不兼容(与您的示例相比,
thunk
compar
需要为MS切换),GNU和附录K似乎是兼容的。
 void qsort_r(void *base, size_t nel, size_t width, void *thunk,
              int (*compar)(void *, const void *, const void *));
struct WordFrequency
{
    const char * word;
    int frequency;
} wordFreqs[numWords];        // Assumes numWords is static/global and constant...
for (i = 0; i < numWords; i++) {
    printf("%s - %d\n", dictionary[i], frequency[i]);
    wordFreqs[i].word = dictionary[i];
    wordFreqs[i].frequency = frequency[i];
}

//sorts the dictionary so that the words are 'alphabetical'
qsort(wordFreqs, numWords, sizeof(struct WordFrequency), wfcmp);  

for (i = 0; i < numWords; i++) {
    printf("%s - %d\n", wordFreqs[i].word, wordFreqs[i].frequency); 
}
int wfcmp(const void *p1, const void *p2) {
     return strcmp(((const struct WordFrequency *)p1)->word, ((const struct WordFrequency *)p2)->word);
}