【问题标题】:Quick sort function works only if last value is the largest仅当最后一个值最大时,快速排序功能才有效
【发布时间】:2016-07-07 23:43:46
【问题描述】:

我正在尝试在 C 中练习使用快速排序。我的程序是一个简单的结构数组,它接受命令行参数(name1 age 1 name2 age2...等)并按降序输出所述年龄。

只有在最后输入的年龄最大时才能正常工作。除此之外,我要么没有输出,要么没有 Seg Fault 11。有人有什么想法吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NameLen 80
void print_struct();

struct people
{
char name [NameLen + 1];
int age;
}; //defining a structure//

typedef struct people PERSON;
void quicksort(struct people list[],int,int);
int main(int argc, const char * argv[])

{
int i,j;
j = 0;
int l = ((argc/2)-1);


struct people list[l]; //maximum size of array of structs


   if (argc %2 == 0) //if the number of arguments is an even number
{

printf("Invalid Arguments!\n");
printf("Usage : ./hw5 name1 age1 name2 age2 ... "); //print error message and correct program usage
    exit(0);
}

printf("You have entered %d persons(s) into the program \n",(argc/2));

for (i=1; i < argc; i+=2)

{
    strcpy(list[j].name, argv[i]);
    list[j].age = atoi(argv[i+1]);
    if(list[j].age == 0)
    {
        printf("...Invalid age <=0. Try again.\n");

        exit(0);
    }
    j++;

}
   printf("Unsorted Names: \n");
    print_struct(&list,argc);

printf ("Sorted by Age: \n");
quicksort(list,0 ,j);
for(i=0;i<j;i++){
  printf("Name : %s| Age : %d\n", list[i].name, list[i].age);}//possible error here?

//Quicksort Function

【问题讨论】:

  • 保持一致的代码风格肯定会提高可读性。
  • 谢谢@Kupiakos!这是我第二次发帖,所以我会继续努力!
  • 为了便于阅读和理解 1) 一致地缩进代码 2) 使用一致的垂直间距 3) 遵循公理:每行只有一个语句和(最多)每个语句一个变量声明.
  • 发布的代码无法编译。它缺少函数的结尾main()
  • 计算list[]数组大小的这一行:int l = ((argc/2)-1);不正确。这是一个整数除法。如果argc 为7,则l 的结果值应为3,但计算结果为2。建议从表达式中删除-1 否则代码访问超出list[] 数组的末尾,这会导致未定义的行为,并可能导致段错误事件。

标签: c arrays sorting struct


【解决方案1】:

也许问题在于 j 的值。 j 是列表的长度吗?还是列表的长度 - 1?

这似乎是你想要的: j = 列表长度

printf ("Sorted by Age: \n");
quicksort(list,0 ,j-1);
for(i=0;i<j;i++){
  printf("Name : %s| Age : %d\n", list[i].name, list[i].age);}

【讨论】:

  • 我之前也试过!没运气。仍然出现 Seg Fault!
  • 在这种情况下,你能分享更多你的代码吗?我无法重现错误。
  • 没问题!我会把它全部发布在下面!提前感谢@MAS
  • 已在上面编辑...对不起,如果它有很多代码!我只是处于亏损状态! @MAS
  • 你为什么要 l = ((argc/2)-1) ?你不想 l = argc/2 吗? @问题代码
【解决方案2】:

快速排序功能很好。问题是你说错了:

quicksort(list,0 ,j);

您为firstlast 传递的值表示第一个和最后一个元素的索引。从您如何使用j 循环遍历元素可以看出,j 是元素的数量。这意味着最后一个元素的索引为j-1

因此,您为last 传递了一个值,该值是数组末尾之后的一个元素。然后,当您尝试读取/写入此虚假元素时,您会调用 undefined behavior,这在您的情况下(幸运的是)会导致段错误。

传入最后一个元素的实际索引(即比大小小一),它运行成功。

quicksort(list,0 ,j - 1);

【讨论】:

    【解决方案3】:

    您的循环不正确:

        while(list[i].age<=list[pivot].age&&i<last)
            i++;
    

    此循环可能以i == last 结束,这很糟糕,因为您尝试交换值,这将超出数组的范围。

        while(list[j].age>list[pivot].age)
            j--;
    

    这里,由于jlast 开头,因此您可以从数组外部读取开始。

    一种可能的补救方法是先向后移动j,然后进行测试(do-while 风格)。然后,递增i,针对递减的j 进行测试。

        do --j; while(list[j].age>list[pivot].age);
        do ++i; while(list[i].age<=list[pivot].age&&i<j);
    

    【讨论】:

    • 谢谢@jxh 我暗示了你的策略,它解决了 Seg Fault 问题,但是它仍然拒绝正确排序。 :(
    【解决方案4】:

    我使代码稍微简单了一点(将字符数组更改为仅一个字符以使其尽可能简单)。 我的想法是,当你打电话时:

    quicksort(list,0 ,j);
    

    你应该调用的是:

    quicksort(list,0 ,j-1);
    

    因为最后一个参数必须是数组长度减1,最后一个位置。

    在运行您的代码或我修改的代码时,我没有遇到段错误,如果可能,请仔细检查您用作输入的字符串。

    这是“我的”代码版本。

    希望对你有帮助。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define NameLen 80
    void print_struct();
    
    struct people
    {
        char name;
        int age;
    }; //defining a structure//
    
    typedef struct people PERSON;
    void quicksort(struct people list[],int,int);
    
    int main(int argc, const char * argv[])
    {
        int i,j;
        j = 10;
        struct people list[10]; //maximum size of array of structs
    
        for (i=0; i < 10; i++)
        {
            list[i].name = 'a';
            list[i].age = 10-i;
        }
    
        printf("Unsorted Names: \n");
        for(i=0;i<j;i++){
            printf("Name : %c| Age : %d\n", list[i].name, list[i].age);}//possible error here?
    
        printf ("Sorted by Age: \n");
        quicksort(list,0 ,j-1);
        for(i=0;i<j;i++){
            printf("Name : %c| Age : %d\n", list[i].name, list[i].age);}//possible error here?
    }
    
    void quicksort(struct people list[],int first,int last)
    {
      struct people temp;
      int i,j,pivot;
    
      if(first<last){
            pivot=first;
            i=first;
            j=last;
    
            while(i<j)
            {
                while(list[i].age<=list[pivot].age&&i<last)
                    i++;
                while(list[j].age>list[pivot].age)
                    j--;
                if(i<j){
                    temp=list[i];
                    list[i]=list[j];
                    list[j]=temp;
                }
            }
    
        temp=list[pivot];
        list[pivot]=list[j];
        list[j]=temp;
        quicksort(list,first,j-1);
        quicksort(list,j+1,last);
      }
    }
    

    【讨论】:

      【解决方案5】:

      应用所有 cmets 后,这是生成的代码,它可以干净地编译,但由于缺少两个函数而无法链接:

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      #define NAME_LEN (80)
      
      
      struct people
      {
          char name [NAME_LEN + 1];
          int age;
      }; //defining a structure//
      
      typedef struct people PERSON;
      
      // print_struct( ptrToList, numElements )
      void print_struct( PERSON *, int );
      
      // quicksort( ptrToList, firstOffset, numElements )
      void quicksort(struct people list[],int,int);
      
      
      int main(int argc, const char * argv[])
      {
          //int i,j;
          //j = 0;
          //int l = ((argc/2)-1);
          int l = argc/2;
      
          struct people list[l]; //maximum size of array of structs
      
          if (argc %2 == 0) //if the number of arguments is an even number
          {
              //printf("Invalid Arguments!\n");
              fprintf( stderr, "Invalid Arguments!\n" );
      
              //printf("Usage : ./hw5 name1 age1 name2 age2 ... "); //print error message and correct program usage
              fprintf( stderr, "Usage : %s name1 age1 name2 age2 ... ", argv[0]);
      
              // exit(0);
              exit( EXIT_FAILURE );
          }
      
          //printf("You have entered %d persons(s) into the program \n",(argc/2));
          printf("You have entered %d persons(s) into the program \n", l);
      
          //for (int i=1; i < argc; i+=2)
          for (int i=1, j=0; j < l; i+=2, j++)
          {
              //strcpy(list[j].name, argv[i]);
              memset( list[i].name, '\0', NAME_LEN+1);
              strncpy( list[j].name, argv[i], NAME_LEN );
              list[j].age = atoi(argv[i+1]);
      
              if(list[j].age == 0)
              {
                  fprintf( stderr, "...Invalid age <=0. Try again.\n");
      
                  //exit(0);
                  exit( EXIT_FAILURE );
              }
              //j++;
          }
      
          printf("Unsorted Names: \n");
          //print_struct(&list,argc);
          print_struct( list, l );
      
          //printf ("Sorted by Age: \n");
          //quicksort(list,0 ,j);
          quicksort( list, 0, l ); 
      
          printf ("Sorted by Age: \n");
          // //for(i=0;i<j;i++)
          //for( int i=0; i<l; i++ )
          //{
          //  printf("Name : %s| Age : %d\n", list[i].name, list[i].age);
          //}//possible error here?
          //}
          print_struct( list, l);
      } // end function: main
      
      
      //Quicksort Function
      

      【讨论】:

        猜你喜欢
        • 2019-04-07
        • 1970-01-01
        • 2017-01-21
        • 2017-10-07
        • 1970-01-01
        • 2018-02-14
        • 1970-01-01
        • 2016-04-22
        • 1970-01-01
        相关资源
        最近更新 更多