我有一个结构:

  typedef struct book{
  double rating;
  double price;
  double relevance;
  int ID;
}B;

的阵列

list* B;

和的这些所以文件中的文件中读取与此

int read_file(char* infile, int N)
{
  int c;
  if((fp=fopen(infile, "rb")))
    {
      fscanf(fp, "%*s\t%*s\t%*s\t%*s\n");
      c=0;
      while((!feof(fp))&&(c<N))
    {
      fscanf(fp, "%lf\t%lf\t%lf\t%d\n", &list[c].rating,  &list[c].price, &list[c].relevance, &list[c].ID);   
      c++;
    }

 fclose(fp);      
    }
  else
    {
      fprintf(stderr,"%s did not open. Exiting.\n",infile);
      exit(-1);
    }
  return(c);
}

和一个比较方法

int comp_on_price(const void *a, const void *b)
{

  if ((*(B *)a).price < (*(B *)b).price)
    return 1;
  else if ((*(B *)a).price > (*(B *)b).price)
    return -1;
  else
    return 0;  

}

我想一个稳定的排序与n日志(n)的时间 也许在最低PRIE的顺序排序合并到最高

我只需要20种最低的价格。

如何将我实现这个用我的比较方法?

感谢

有帮助吗?

解决方案 7

我终于做到这一点使用计数排序花的代码在100行中℃。

i,那么这样做是在一行中的壳脚本

排序-NK 2,2- -s Wodehouse.txt |排序-rnk 3,3 -s |排序-rnk 1,1- -s |头-20

其他提示

  

我想的排序与n日志(n)的一稳定时间也许在最低PRIE的顺序排序合并到最高

     

我只需要20种最低的价格。

然后,可以在O(n)的时间这样做。你可以把这些O(1)排序查找O(N)时间的前20个值。

看到这里为STL C ++库版本

注释的Python实现此处

快速排序是你的朋友:)。 (虽然它并不NLOG(N)在最坏的情况下,很难做做任何事情更快)

既然你提到C和不是C ++,我会说你考虑实现自己的类似的的qsort()

看看如何对的qsort比较被定义。您需要定义自己相似的地方?对于实际的排序,你会需要从头开始实现自己的StableSort()的版本。

您要使用的功能是 qsort 。 C提供该做一个完全可以接受的排序的究竟的你似乎需要。

qsort本身不是一个稳定的排序(当然,它的可以的是对于给定的实现方式中,但该标准并不能保证它),但它可以被制成一个与一些诡计。我已经做了之前通过添加一个指向其最初填充与元件自身的地址数组元素(或递增的整数值作为你读取文件可能会做这里)。

然后就可以使用,作为一个次要键,这确保具有相同的主要关键元素被保存在顺序。

如果您的的想去改变结构的麻烦,Algorithmist是一个好地方,的获取代码。自己,我更愿意少量修改的重新实现。

要真正使之稳定,改变你的结构:

typedef struct book {
  double rating;
  double price;
  double relevance;
  int ID;
  int seq;                                 // Added to store sequence number.
} B;

和您的文件读取的代码更改为:

fscanf(fp, "%lf\t%lf\t%lf\t%d\n", ... 
list[c].seq = c;                           // Yes, just add this line.
c++;

那么你的比较函数变成这样的:

int comp_on_price(const void *a, const void *b) {
    B *aa = (B*)a;
    B *bb = (B*)b;

    if (aa->price < bb->price)
        return 1;
    if (aa->price > bb->price)
        return -1;
    return (aa->seq < bb->seq) ? 1 : -1;   // Cannot compare equal.
}

您不需要快速排序的一切。只需创建一个空的B *阵列的20个最低纪录,在那里复制的第一个<= 20次的记录和快速排序他们,如果有超过20然后根据你迭代的元素比较他们在第20最高:如果更多的则还有继续比较下一个最高等回来到最低,然后转向其他指针,使空间在低-20的下一个条目。你需要一个确定的比较 - 听paxdiablo在这一方面:加一个输入记录编号或东西来区分记录

这只是你的comparizon功能的细微变化做出快速排序库稳定。见链接此处

像下面应达到目的的东西(未测试的,谨慎):

int comp_on_price(const void *a, const void *b)
{
    if ((*(B *)a).price < (*(B *)b).price)
        return 1;
    else if ((*(B *)a).price > (*(B *)b).price)
        return -1;
    else
        // if zero order by addresses
        return a-b;
}

这会工作,如果你能保证a和b是在相同的地址空间(在同一阵列中两个指针),并且每一个比较,给出数组的一个更大的整体排序,下层结构的地址将趋于更慢。这是泡沫排序或类似的事实。这也将努力为小事实施QucikSort(这快速排序是不是)。然而,对于其他算法,或使用临时存储(也许对于优化目的)附加地址空间中的任何算法,这个属性不会是真的。

如果你排序包含在比较项目的任何唯一标识符(在当前的例子,可能是现场ID真),另一种方法来使排序稳定将比较这些项目。你也可以在实现这一目的的新字段添加这样一个独特的密钥,但因为它使用更多的内存,你应该考虑的第三个选项在这之前如下所述。

我的优选的方法仍然是第三个,不直接排序的结构的阵列,但排序指针数组实际结构的项目。这样做有几个不错的性能。首先,你可以比较结构的阵列指向的,因为它不会改变,它将使排序稳定。

在比较功能将成为类似:

int comp_on_price(const void *a, const void *b)
{
    if ((*(B **)a)->price < (*(B **)b)->price)
        return 1;
    else if ((*(B **)a)->price > (*(B **)b)->price)
        return -1;
    else
        // if zero, order by addresses
        return *(B **)a-*(B **)b;
}

其他良好的特性是,它避免周围移动结构,而分选,它只需要移动的指针,并且,可以是时间节省。也可以保持几个这样的指针数组,并允许几个有序访问数组项在同一时间。

缺点是,它需要一些存储器和访问的项目被稍慢(更间接的一个电平)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top