用C语言对数据进行排序

时间:2010-04-30 12:11:30

标签: c sorting

我对下面的要求几乎没有帮助,因为我对C语法知之甚少。

我有像这样的文件中的数据

73 54 57 [52]
75 73 65 [23]
65 54 57 [22]
22 59 71 [12]
22 28 54 [2]
65 22 54 73 [12]
65 28 54 73 [52]
22 28 65 73 [42]
65 54 57 73 [22]
22 28 54 73 [4]

括号中的值表示该系列的出现。我需要根据顶部最大元素下降的数据的出现对这些数据进行排序,如下所示。

65 28 54 73 [52]
22 28 65 73 [42]
65 54 57 73 [22]
65 22 54 73 [12]
22 28 54 73 [4]
28 59 71 [122]
73 54 57 [52]
22 28 65 [26]
..
.
.
.

等等......

这是什么快速代码?

我正在尝试这个

#include<string.h>
#include <stdio.h>
int main() {

    FILE *infile;
    char fname[40]="resultFile1.txt";
    char line[100];
    int lcount=0;
    if((infile = fopen(fname, "r")) == NULL) {
        printf("Error Opening File.\n");
    }
    char *Arr[23];// need to be dynamic
    while( fgets(line, sizeof(line), infile) != NULL ) {
        stringArray[lcount]=line;
        lcount++;
        Arr[lcount]=line;
    } fclose(infile);
    int i;
    for (i = 0; i < lcount; i++) {
        printf(Arr[i]);// not able to get Arr
    }
}

6 个答案:

答案 0 :(得分:10)

我会:

  1. 将文本作为一大块文本加载到内存中。
  2. 找到每一行的开头,创建一个字符串指针数组到数据块中。
  3. 通过查找“[number]”模式,编写一个比较两行的比较函数。
  4. 使用比较功能在我的线指针数组上调用qsort()
  5. 完成。 :)

答案 1 :(得分:2)

您可能对qsort功能感兴趣。基本上,你需要首先解析你的文件,使它在一个结构数组中,每个结构都有序列和你所谓的“出现”(键)。

然后您可以定义自己的自定义比较器功能,例如:

int compare_file_entries(void* data1, void* data2)
{
    struct file_entry* entry1 = (struct file_entry*) data1;
    struct file_entry* entry2 = (struct file_entry*) data2;
    if ( entry1->occurence < entry2->occurence ){
        return -1;
    } else if ( entry2->occurence > entry2->occurence ){
        return 1;
    } else{
        return 0;
    }
}

然后,如果您有一组file_entry个对象,比如说struct file_entry* entries,并且您有entrycount个这样的条目,那么您可以使用以下方式对该列表进行排序:

qsort(entries,entrycount,sizeof(struct file_entry),&compare_file_entries);

一旦对内存中的表示进行了排序,就可以将其写回文件。

答案 2 :(得分:2)

如果将问题分解为小部分(如上所述),这是最简单的。这是一般工程(无论是软件还是其他)的重要组成部分。

问题大致如下:

  • 阅读文件
  • 输出结果
  • 计算一行中的项目数
  • 提取行尾的数字
  • 存储文件
  • 按行中的项目数排序文件
  • 按文件末尾的编号对文件进行排序

之后很简单!

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define BUFFER_SIZE 100
#define MAX_NODES 1000



int count_spaces( char * s ) {
  int spaces = 0;
  int i;
  for( i = 0; i < strlen( s ) ; i ++ ) {
    if( s[ i ] == ' ' ) {
      spaces++;
    }
    i++;
  }
  return spaces;
}

/* sort by number of spaces */
int sort1( char  *a, char  * b ) {
  int spaces_a = count_spaces( a );
  int spaces_b = count_spaces( b );

  if( spaces_a < spaces_b )
    return -1;
  if( spaces_a > spaces_b )
    return 1;
  return 0;

}

int get_digits( char *s ) {
  char buffer[ 10 ];
  memset( buffer, 0, 10 );
  int state = 0;
  int i = 0, j = 0;
  int number = 0;
  for( i = 0; i < strlen( s ) ; i ++ ) {
    if( state == 0 && s[ i ] == '[' ) {
      state = 1;
    }
    if( state == 1 && s[ i ] != ']' ) {
      buffer[ j ] = s[ i ];
      j++;
    }
    if( state == 1 && s[ i ] == ']' ) {
      break;
    }
  }
  sscanf( buffer, "%d", &number );

}

/* sort by digits in brackets at the end of the line */
int sort2( char  *a, char  * b ) {
  int a_num = get_digits( a );
  int b_num = get_digits( b );

  if( a_num < b_num )
    return -1;
  if( a_num > b_num )
    return 1;
  return 0;


}




int main() {
  FILE *infile;
  char line[ BUFFER_SIZE ];
  int i = 0;
  char *nodes[ MAX_NODES ];

  if( (infile = fopen( "data.txt", "r" )) == NULL ) {
    printf( "Error opening file\n" );
    return -1;
  }

  while( fgets( line, BUFFER_SIZE, infile ) != NULL ) {
    if( (nodes[ i ] = malloc( strlen( line ) + 1 )) == NULL ) {
      printf( "Malloc failed\n" );
      return -1;
    }
    strcpy( nodes[ i ], line );
    i++;
  }
  // sort by # of items in a line
  qsort( nodes, i, sizeof( char *), (void *)(&sort1) );
  // sort by number
  qsort( nodes, i, sizeof( char *), (void *)(&sort2) );
  /* output results */
  i--;
  do {
    printf( "%s", nodes[i] );
    i--;
  } while( i >= 0 );


}

答案 3 :(得分:1)

如果您没有严格必须在C中进行(可能是这种情况,所以这是无关紧要的),您可以使用标准的UNIX工具:

cat test | sed -r 's/.*\[(.+)\]$/\1 \0/' | sort -n -r | cut -d ' ' -f 2-

“cat test”:不是真的需要,只是把文件扔到管道上 “sed ....”:复制行开头的行李中的最后一个数字 “sort -n -r”:按相反的顺序排序第一个数字 “cut ...”:删除行开头的重复字段

从C,您可以使用system()调用它,它会将结果抛出到stdout,但是如果您需要在程序中读取结果,则需要更多(管道..)

答案 4 :(得分:0)

Bucket按元素编号对它们进行排序(:一旦解析后读取数组长度),然后选择一个适合您对存储桶进行排序的排序,或者更好的是,使得桶的二进制搜索树的关键值是括号中的数字瞧。问题解决了。

答案 5 :(得分:0)

这是我的答案。对不起,大量的代码!

首先,一些struct s

// contains the whole line as well as the series for ease of id
struct _Payload
{
   char *line;      // the line of text
   int series;      // the number in [ ] at the end of that line
   int numElements; // the number of elements in the line
};

// a tree sorted by the series of the Payloads within
struct _PayloadTree
{
   struct _Payload *payload;
   struct _PayloadTree *left;
   struct _PayloadTree *right;
};

// a tree sorted by the number of elements in the PayloadTree subtrees
struct _Tree
{
   int numElements;  // for sorting
   struct _PayloadTree *payloadTree;
   struct _Tree *left;
   struct _Tree *right;
};

typedef struct _Payload Payload;
typedef struct _PayloadTree PayloadTree;
typedef struct _Tree Tree;

接下来,一些辅助函数:

Payload *createPayload(char *line, int series, int numElements)
{
   Payload * payload = (Payload *)malloc(sizeof(Payload));
   payload->line = line;
   payload->series = series;
   payload->numElements = numElements;
   return payload;
}

PayloadTree *createPayloadTree(Payload *p)
{
   PayloadTree * payloadTree = (PayloadTree *)malloc(sizeof(PayloadTree));
   payloadTree->payload = p;
   payloadTree->left = payloadTree->right = NULL;
   return payloadTree;
}

Tree *createTree(int numElements)
{
   Tree * tree = (Tree *)malloc(sizeof(Tree));
   tree->numElements = numElements;
   tree->payloadTree = NULL;
   tree->left = tree->right = NULL;
   return tree;
}

现在向树中添加内容。我们首先找到元素桶的数量,然后在适当的系列桶(PayloadTree

中的那个位置
void addPayloadToPayloadTree(Payload *p, PayloadTree *payloadTree)
{
   // these are sorted according to the value in 'series'
   if(payloadTree == NULL) return;

   PayloadTree *pt = payloadTree;
   while(pt != NULL)
   {
      // should this happen?
      if(p->series == pt->payload->series) break;
      else if(p->series < pt->payload->series)
      {
         if(pt->left == NULL) pt->left = createPayloadTree(p);
         else pt = pt->left;
      }
      else
      {
         if(pt->right == NULL) pt->right = createPayloadTree(p);
         else pt = pt->right;
      }
   }
}

// Main way to add a line to the tree
void addPayload(Payload *p, Tree **tree)
{
   if(*tree == NULL) *tree = createTree(p->numElements);

   Tree *t = *tree;
   while(t != NULL)
   {
      if(t->numElements == p->numElements) break;

      else if(t->numElements > p->numElements)
      {
         // look left
         if(t->left == NULL)
         {
            t->left = createTree(p->numElements);
            break;
         }
         t = t->left;
      }
      else
      {
         // look right
         if(t->right == NULL)
         {
            t->right = createTree(p->numElements);
            break;
         }
         t = t->right;
      }
   }

   // now t points to the right bucket
   if(t->payloadTree == NULL) t->payloadTree = createPayloadTree(p);
   addPayloadToPayloadTree(p, t->payloadTree);
}

最后是打印方法。从右到左打印:

void printPayloadTree(PayloadTree *pt)
{
   if(pt == NULL) return;

   printPayloadTree(pt->right);
   printf("%s\n", pt->payload->line);
   printPayloadTree(pt->left);
}

void printTree(Tree *t)
{
   if(t == NULL) return;

   printTree(t->right);
   printPayloadTree(t->payloadTree);
   printTree(t->left);
}

我省略了clear函数和main实现,因为这取决于您。这是我用来解析一条线的方法。您可以使用先前声明parseLine(theLine, &series, &numElements)series numElements int的{​​{1}}来调用它。

void parseLine(char *line, int *series, int *numElements)
{
   char *tok = strtok(line, " ");
   int n = 0;
   while(tok != NULL)
   {
      if(tok[0] == '[')
      {
         // found the series
         tok[ strlen(tok) - 2 ] = '\0';
         *series = atoi(tok + 1);
      }
      else
      {
         n++;
      }
      tok = strtok(NULL, " ");
   }
   *numElements = n;
}