【问题标题】:c++ sort with structsc++ 使用结构排序
【发布时间】:2010-10-26 19:12:34
【问题描述】:

我很难解决这个问题,它需要一种客户姓名、客户 ID 以及最后的应付金额。我已经计算了整个程序,但无法确定进行排序所需的最后一个原型。我有一个名为 Customers 的结构,我还将提供 int main() 部分。我只需要任何帮助来启动原型 SortData()。

struct Customers {
    string Name;
    string Id;
    float OrderAmount;
    float Tax;
    float AmountDue;
};

const int MAX_CUSTOMERS = 1000;
bool MoreCustomers(int);
Customers GetCustomerData();
void OutputResults(Customers [], int);
void SortData(const int, const int, Customers []);

int main() {
    Customers c[MAX_CUSTOMERS]; 
    int Count = 0;      
    do {
      c[Count++] = GetCustomerData();   
    } while (MoreCustomers(Count));     


    for (int i = 0; i < Count; i++) {
        c[i].Tax = 0.05f * c[i].OrderAmount;        
        c[i].AmountDue = c[i].OrderAmount + c[i].Tax;   
    }

    SortData(0, Count, c);     //0:Sorts by customer name       
    OutputResults(c, Count);            
    GeneralSort(1, Count, c);   //1:Sorts by ID     
    OutputResults(c, Count);        
    GeneralSort(2, Count, c);   //2: Sorts by amount due        
    OutputResults(c, Count);        

    return 0;                       
}


void SortData(const int SortItem, const int count, CustomerProfile c[]) {
     //0: Sort by name
    //1: Sort by ID
    //3: Sort by amount due
}

【问题讨论】:

    标签: c++ arrays sorting struct bubble-sort


    【解决方案1】:

    我假设您是编程或 C++ 新手,因此您可能正在寻找以下内容:

    #include <search.h> // for the qsort()
    
    int
    CompareByName( const void *elem1, const void *elem2 )
    {
      return ((Customers*)elem1)->Name > ((Customers*)elem2)->Name? 1 : -1;
    }
    
    int
    CompareByOrderAmount( const void *elem1, const void *elem2 )
    {
      return ((Customers*)elem1)->OrderAmount > ((Customers*)elem2)->OrderAmount? 1 : -1;
    }
    
    void SortData( int SortItem, int count, Customers customers[] )
    {
      switch (SortItem) {
      case 0:
        qsort(customers, count, sizeof(Customers), CompareByName);
        break;
      case 1:
        qsort(customers, count, sizeof(Customers), CompareByOrderAmount);
        break;
      // ...
      }
    }
    
    void test()
    {
      Customers cust[10];
    
      cust[0].Name = "ten";
      cust[1].Name = "six";
      cust[2].Name = "five";
      SortData( 0, 3, cust );
      cout << cust[0].Name << endl;
      cout << cust[1].Name << endl;
      cout << cust[2].Name << endl;
    }
    

    【讨论】:

    • 您的答案显然是 C 风格的答案,没有 C++ 品质(除了对字符串使用重载的 > 运算符)。如果这是一个 C 问题(并且您将字符串比较更改为 strcmp),那么您的答案会很有用,但事实上,它对这个问题根本没有用。对于初学者,在 C++ 风格中,排序应该使用 std::sort,而不是 qsort。 (顺便说一句,即使在使用 qsort 时,您的比较函数也必须处理两个元素相等的情况,并返回 0。)
    • 是的,你是对的。但是使用普通结构也是 C 风格的。对于初学者来说,使用 STL 可能有点神秘。无论如何,我可以删除我的答案。
    • 我的比较函数应该处理元素相等的情况,真的。但是,这种情况很少见,实际问题是当我们对数组进行排序时,最好使用指针数组而不是结构数组。所以任何好的答案都是主观的。
    • 同意不使用整个结构的容器,以降低排序成本。我不能谈论 C++ 中数组的惯用用法,但不鼓励在 STL 容器中使用(裸)指针,因为这样很难跟踪对象生存期。 (当需要指针时,建议使用 shared_ptr,例如,避免切片,或防止大量对象复制(如本例),或与不可复制类型一起使用时。)
    • 实际上,在这点上,AFAIK qsort 仅可用于 POD 类型(该标准似乎对此主题保持沉默,但谷歌搜索“qsort 是否可用于非 pod 类型”是有启发性的)。 OP 的示例在结构中使用了一些非 POD 类型(特别是 std::string),因此这是另一个支持保存指针而不是整个对象的论点。 (不过,像 shared_ptr 这样的智能指针也不是 POD 类型,所以一般不建议使用 qsort。)
    【解决方案2】:

    经常被忽视的是,您实际上可以将 STL 范围函数与基于 C 的数组一起使用,就像在您的示例中一样。因此,您实际上不必转而使用基于 STL 的容器(我不会在这里讨论这样做的优点 :-))。

    因此,根据 Chris 的回答,您可以按如下方式调用 sort:

    std::sort( customers, customers+Count, &customer_sorter);
    

    【讨论】:

      【解决方案3】:

      您只需要编写一个比较两个 CustomerProfile 类型的比较函数。拥有此功能后,您可以使用 STL 排序(参见 http://www.sgi.com/tech/stl/sort.htmlhttp://msdn.microsoft.com/en-us/library/ecdecxh1(VS.80).aspx)或旧的 C qsort:http://en.wikipedia.org/wiki/Qsort_(C_Standard_Library)。我建议不要编写自己的排序算法,除非这是家庭作业。 您的比较取决于您喜欢使用的技术,它可能看起来像这样:

      int CompareCustomerProfile(
         const CustomerProfile* pC1,
         const CustomerProfile* pC2)
      {
       int result = strcmp(pC1->name, pC2->name);
       if (0 != result) return result; 
      
        result = strcmp(pC1->ID, pC2->ID);
        if (0 != result) return result;
      
        if (pC1->amountDue < pC2->amountDue) return -1;
       if (pC1->amountDue > pC2->amountDue) return 1;
      
        return 0
      }
      

      这假定您示例中的“字符串”类型是 char*。如果您使用 Unicode 或多字节类型,那么显然必须使用适当的 Unicode 或多字节比较。 然后,您只需使用比较函数调用该算法。例如。使用 qsort:

      qsort(c, Count, sizeof(CustomerProfile), CompareCustomerProfiler).
      

      现在如果这个家庭作业,你不应该在这里问怎么做......

      【讨论】:

        【解决方案4】:

        您应该使用在 &lt;algorithm&gt; 标头中声明的 C++ 标准排序函数 std::sort

        当您使用自定义排序函数进行排序时,您必须提供一个 谓词函数 来说明左侧值是否小于右侧值。因此,如果您想先按名称排序,然后按 ID 排序,然后按到期金额排序,所有这些都按升序排列,您可以这样做:

        bool customer_sorter(Customer const& lhs, Customer const& rhs) {
            if (lhs.Name != rhs.Name)
                return lhs.Name < rhs.Name;
            if (lhs.Id != rhs.Id)
                return lhs.Id < rhs.Id;
            return lhs.AmountDue < rhs.AmountDue;
        }
        

        现在,将该函数传递给您的 sort 调用:

        std::sort(customers.begin(), customers.end(), &customer_sorter);
        

        这假设您有一个名为 customers 的包含客户的 STL 容器(而不是数组,就像您在示例代码中那样)。

        【讨论】:

          【解决方案5】:

          您可以通过创造性的谷歌搜索在 C++ 中找到很多排序实现。 唯一的区别是,不是对数字进行排序,而是对结构进行排序。

          因此,无论您将使用的算法中是否存在 if(a[i]&lt;a[j]) 之类的内容,请拨打类似 `if(isFirstCustomerLowerThanOther(a[i]

          现在,创建一个具有以下结构的函数:

          bool isFirstCustuomerLowerThanOther(const Customer& firstCustomer, const Customer& secondCustomer)
          {
           // Implement based on your key preferences
          }
          

          更好的是,如果你使用 C++,你可以使用 STL 的排序算法(同样,谷歌了解信息以及如何将排序传递给它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-09-01
            相关资源
            最近更新 更多