使用qsort()对一个整数数组进行排序并交换字符串

时间:2019-01-24 14:59:27

标签: c sorting qsort

我想按降序对int *arr进行排序,同时如果char **words的第二个元素大于第一个元素,则交换int *arr数组的相应元素。我如何使用qsort()cmpfunc()来做到这一点?对ints进行排序很容易,但是由于我没有索引当前正在对int数组的哪两个元素进行排序,我该如何在另一个数组中交换字符串?

qsort(arr,N,sizeof(int),cmpfunc);

``

int cmpfunc(const void * a, const void * b) {
    int val1 = *(int *)a;
    int val2 = *(int *)b;

    if(val2 > val1) {
        /* swap string positions */
        return 1;
    } else if(val2 < val1) {
        return -1;
    } else {
        return 0;
    }
}

3 个答案:

答案 0 :(得分:2)

有几种方法可以解决此问题。首先,直接回答您的问题:

  1. 制作一个size_t的新数组,其中包含值0 .. N
  2. 在该数组上运行qsort,而不是
int val1 = *(int *)a;
int val2 = *(int *)b;

你做

int val1 = arr[*(int *)a];
int val2 = arr[*(int *)b];

然后照常进行比较。

  1. 现在您有了arr(排列)的索引数组,排列顺序为arr。现在我们可以应用到arrwords中。一种选择是,只要您想按排序的顺序访问两个数组,就简单地遍历索引数组。另一个方法是复制两个数组,然后根据排列复制元素。

第二个:您还可以对struct { int * ; char ** }数组(每个指向arr的一个成员和words的对应成员)执行相同的操作,对这个数组进行排序它的int成员,同时保留原始数组,并从那里开始使用它。

第三:您可以退出具有并行数组。如果数据是如此紧密地关联,那么为什么要用两个不相关的变量呢?如果将两种数据一起放在一个结构中,那么您可以对结构数组进行排序,并对这些结构进行任何其他操作,而不必担心相关性会不同步。

答案 1 :(得分:1)

您可以使用qsort_s()(如果可用,它是GNU扩展。在Microsoft环境中,它称为int *arr,但具有相同的语义)将另一个参数传递给compare函数,用于示例结构中的基本数组指针char **wordsstruct cmpargs { int *arr; char **words; } args; ... args.arr = arr; args.words = words; qsort_r(arr,N,sizeof(int),cmpfunc, &args);

int cmpfunc(const void * a, const void * b, void *_args) {
    struct cmpargs args = _args;

    int *a1 = a;
    int *a2 = b;

    int idx1 = a - args->arr;
    int idx2 = b - args->arr;

现在,在您的compare函数中,您可以访问它们,并可以使用它们进行交换:

args->word

现在,如果比较函数返回1,则可以在其比较函数中交换相应数组//uisng taglib to achieve the result. TagLib.File file = TagLib.File.Create(FilePath); string title=file.Tag.Title.ToString(); // its fine and find the related data of the title attribute. string Tags= file.Tag.Tags.ToString(); // does not return any data and raise error.'does not contain a definition for Tags'. // using WindowsAPICodePack shell string infos = null; foreach (var prop in new ShellPropertyCollection(open.FileName)) { infos += prop.CanonicalName + "=" + prop.ValueAsObject + "\n"; } 中的元素。

答案 2 :(得分:0)

  

我想同时对int *arr进行降序排序   如果第二个交换一个char **words数组的相应元素   *arr的元素大于第一个元素。我能怎么做   使用qsort()cmpfunc()吗?

没有一种干净的方法来完成此工作,因为它需要qsort()无法传达给比较功能的上下文信息:arrwords的基地址数组。实际上,后者甚至根本没有传达给qsort()本身。

在支持C11线程的实现中,可行的替代方法是将这些指针存储在thread-specific storage中,然后让比较函数从那里检索它们。然后,可以将要比较的元素的索引计算为它们与基本指针之间的指针差,然后可以使用其基本指针和所获得的索引对words进行常规交换。

但这可能不是您真正想要的!我推断您正在尝试对words的元素进行与{{ 1}}。您所描述的内容并不确定一定会产生这种情况,因为您完全不确定每次比较结果以某种方式发生时,arr都会执行交换。

如果确实两个数组必须分开,那么正确的方法是准备并排序某种辅助数组。在该区域中有多种选择,然后您可以对一个或两个主阵列进行重新排序,或者就像完成操作一样对其进行访问。例如,您可能准备一个qsort(),每个元素(一个int (*perm)[2])都包含int[2]的相应元素和该元素的初始索引。然后,您可以根据需要对该数组进行排序,而直接获得排列。然后,您可以将arrarr重新排序以匹配,或者通过排列(words)间接访问它们。

但是您也可以考虑编写自己的有目的的排序功能,而不是使用words[perm[k][1]]。这样的函数可以将指向两个数组的基本指针(甚至正确键入)作为参数,然后直接执行所需的共同排序。