对具有重复条目的列表进行计数排序奇数结果

标签 c sorting

我正在使用计数排序来对从文件中读取的数字选择进行排序。这对于没有重复条目的文件似乎工作得很好,但是一旦有重复,就会开始出现大量的零。

您知道为什么会发生这种情况以及如何解决它吗?

示例:

输入(不重复):

1612 1894 3018 4212 6046 12894 13379 14408 14615 16394 17982 23004 27588 31393 33195 39526 54326 54566 67926 72479 90466 157832 703908

输出:

0: 1612 1: 1894 2: 3018 3: 4212 4: 6046 5: 12894 6: 13379 7: 14408 8: 14615 9: 16394 10: 17982 11: 23004 12: 27588 13: 31393 14: 33195 15: 39526 16: 54326 17: 54566 18: 67926 19: 72479 20: 90466 21: 157832 22: 703908

输入(有重复项):

1612 1894 3018 4212 6046 12894 13379 14408 14615 16394 17982 23004 27588 31393 33195 39526 54326 54566 60000 60000 60000 60000 703908

输出(参见 18++):

0: 1612 1: 1894 2: 3018 3: 4212 4: 6046 5: 12894 6: 13379 7: 14408 8: 14615 9: 16394 10: 17982 11: 23004 12: 27588 13: 31393 14: 33195 15: 39526 16: 54326 17: 54566 18: 0 19: 0 20: 0 21: 60000 22: 60000

输入:

2 2 2 2 2 3 3 3 3 3

输出:

0: 119 1: 110 2: 2025792 3: 3249376 4: 56 5: 2 6: 2 7: 2 8: 2 9: 2

用于生成此输出的代码片段:

int *numbers = (int *) calloc(rows, sizeof(int));

int i = 0;
int max = -1; //min
int min = 500000000; //max
while(fscanf(inputPtr, "%d", &numbers[i]) != EOF) {
  //printf("%d\n", numbers[i]);
  if(numbers[i]>max) max = (int) numbers[i];
  if(numbers[i]<min) min = (int) numbers[i];
  i++;
}

countingSort(numbers, rows, max, min);

void countingSort(int array[], const int end, const int max, const int min) {
  int i;
  const int range = max-min+1;
  int count[range+1],
      scratch[end];

  for(i=0; i<range+1; i++)
    count[i] = 0;

  /* Set the value of count[i] to the number of
   * elements in array with value i+min-1. */
  for(i=0; i<end; i++) {
    int c = array[i]-1-min;
    count[c]++;
  }

  /* Update count[i] to be the number of
   * elements with value less than i+min. */
  for(i=1; i<range; i++)
    count[i] += count[i-1];

  /* Copy the elements of array into scratch in
   * stable sorted order. */
  for(i=(end-1); i>=0; i--) {
    int c = array[i]-min;
    int s = count[c];
    scratch[s] = array[i];
    /* Increment count so that the next element
     * with the same value as the current element
     * is placed into its own position in scratch. */
    count[c]++;
  }

  for(i=0; i<end; i++)
    array[i] = scratch[i];
}
<小时/>

完整代码:

#include <stdio.h>  // FILE stderr fopen fclose fprintf printf fgets
#include <stdlib.h> // Standard Lib :-)
#include <math.h> // Every body was kung fu math

/**
 * Given any number of program parameters (command-line parameters)
 * calculates the length of each one, and writes the longest to standard output
 * this time using counting sort!
 */

/*
 * Output the usage
 */ 
void usage () {
  printf("Usage:\n"
         "Usage: part2 rows fileToRead\n");
}

/**
 * counting sort
 * http://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Counting_sort
 */
void countingSort(int array[], const int end, const int max, const int min) {
  int i;
  const int range = max-min+1;
  int count[range+1],
      scratch[end];

  for(i=0; i<range+1; i++)
    count[i] = 0;

  /* Set the value of count[i] to the number of
   * elements in array with value i+min-1. */
  for(i=0; i<end; i++) {
    int c = array[i]-1-min;
    count[c]++;
  }

  /* Update count[i] to be the number of
   * elements with value less than i+min. */
  for(i=1; i<range; i++)
    count[i] += count[i-1];

  /* Copy the elements of array into scratch in
   * stable sorted order. */
  for(i=(end-1); i>=0; i--) {
    int c = array[i]-min;
    int s = count[c];
    scratch[s] = array[i];
    /* Increment count so that the next element
     * with the same value as the current element
     * is placed into its own position in scratch. */
    count[c]++;
  }

  for(i=0; i<end; i++)
    array[i] = scratch[i];
}

/**
 * return the appropriate percentile
 */
int getPercentile(double percent, int *array, int array_size) {
  int number = (floor(percent*array_size)+1); //-1 for arrays

  //Make number suitable for arrays
  number -= 1;

  //printf("%d\n", number);

  //Ensure the numbers aren't the same
  while(array[number-1]==array[number]) {
    number++;

    if(number>=array_size)
      return -1;
  }

  //printf("%d\n", number);

  return (int) array[number];
}

/**
 * The main method
 * part2 1000 datafile
 */ 
int main (int argc, char *argv[]) {
  //I need three args
  //1 rows
  //2 file name
  if(argc==3) {
    int rows = 0;     
    if(sscanf(argv[1], "%d", &rows) == 0) {
      printf("The number of rows must be a number.\n");
      usage();   
      exit(-1);       
    }

    FILE *inputPtr; //File pointers
    inputPtr = fopen(argv[2], "r"); //same as PHP ;-)

    // Sensible errors
    if(inputPtr==NULL) {
      printf("I could not open the file for input.\n");
      usage();
      exit(-1);
    }

    // Read all the numbers
    int *numbers = (int *) calloc(rows, sizeof(int));

    int i = 0;
    int max = -1; //min
    int min = 500000000; //max
    while(fscanf(inputPtr, "%d", &numbers[i]) != EOF) {
      //printf("%d\n", numbers[i]);
      if(numbers[i]>max) max = (int) numbers[i];
      if(numbers[i]<min) min = (int) numbers[i];
      i++;
    }

    printf("%d, %d, %d\n\n", min, max, rows);

    //int array[], const int end, const int max, const int min) {
    countingSort(numbers, rows, max, min);

    for(i = 0; i < rows; i++) {
      printf("%i: %d\n", i, numbers[i]);
    }  
    printf("-------\n\n");

    // Close the files
    //fclose(inputPtr);
    //not pointing to file anymore

    int percentile = getPercentile(0.9, numbers, rows);

    printf("%s: %d\n", argv[2], percentile);

  } else {
    printf("Please provide two CLI's!\n");
    usage();
    return 0;
  }


  /* All done */
  return 0;

}

最佳答案

这里有一个错误:

/* Set the value of count[i] to the number of
 * elements in array with value i+min-1. */
for(i=0; i<end; i++) {
    int c = array[i]-1-min;
    count[c]++;
}

如果注释正确,您应该设置c = array[i]+1-min;。没有其他东西跳出来。

关于对具有重复条目的列表进行计数排序奇数结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8169100/

相关文章:

c - swift (Linux) : Extract CMS/PKCS#7 Certs and Validate Container Signature?

mysql - 如何通过 C 连接到 SQL?

c++ - 让 VS 编译器捕捉有符号/无符号的赋值?

c - 并行和顺序点积程序不同的结果

c - 我正在尝试编写一个在 C 中定义为参数的函数

arrays - 对配对数字数组进行排序并删除重复或重叠?

java - 如何使数组处理更快?

Java排序Arraylist并返回排序列表

java - 使用 double 作为比较对 JSONArray 进行排序违反了约定?

arrays - 存储一长串值的最佳方式