65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 std::sort() 方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.52/5 (10投票s)

2000年4月28日

viewsIcon

223154

downloadIcon

767

STL 排序入门。

去年,我正在开发一个数据库程序,需要执行三个查询,每个查询都有一些公共字段和几个不同的字段。公共数据是开始和结束日期,自然地,数据行需要交错排列。

Purchase      Jan 1,  1990
Installation  Feb 2, 1990
Repair        Sept 23, 1991
Installation  Dec 10, 1993
Repair        Jun 4, 1996

由于有三个不同的但相似的项目,我需要一个基类,我可以从中派生。基类包含我将用于排序的日期戳,并且为了这个例子,我添加了一个将文本输出到输出流的方法。

// Base class we're using to provide a function with a
sortable value
class CHistoryItem
{
public:
     CHistoryItem(DATE& rTimestamp)
     {
          m_Timestamp = rTimestamp;
     }

     DATE& GetTimestamp()
     {
          return m_Timestamp;
     }

     // Indicate the item type as a string
     virtual   char* ItemName() = 0;

     // Output the item to a stream
     void OutputToStream(std::ostream& os)
     {
          os << ItemName() << "\t" << m_Timestamp << "\n";
     }

protected:
     DATE m_Timestamp;
};

定义了基类后,我从中派生了三个历史项目。

// Repair history entry
class CRepairItem : public CHistoryItem
{
public:
     CRepairItem(DATE rTimestamp)
          : CHistoryItem(rTimestamp)  { }

     // Indicate that this is a repair
     char* ItemName()    {    return "Repair: ";  }
};

// Installtion history entry
class CInstallItem : public CHistoryItem
{
public:
     CInstallItem(DATE& rTimestamp)
          : CHistoryItem(rTimestamp)  { }

     // Indicate that this is a installation
     char* ItemName()    {    return "Install: "; }
};

// Purchase history entry
class CPurchaseItem : public CHistoryItem
{
public:
     CPurchaseItem(DATE& rTimestamp)
          : CHistoryItem(rTimestamp)  { }

     // Indicate that this is a installation
     char* ItemName()    {    return "Purchase: ";     }
};

好的...所以我们有了类定义,现在是时候创建一个包含我们对象的向量了。由于我不知道在执行查询之前会期望什么,我们必须动态分配对象。由于我有点懒而且健忘,我倾向于在向量析构函数中释放我分配的向量中的对象。

// A vector based class to contain our history items
class CHistoryVector : public std::vector<CHistoryItem*>
{
public:
     // Make sure that the history items are de-allocated so we don't leak
     ~CHistoryVector()
     {
          for (iterator pItem=begin(); pItem != end(); ++pItem)
               delete *pItem;
     }
};

现在我们已经设置好了一切,我们需要提供一种指定如何排序数据的方法。通常我只需要以一种方式排序我的数据,但是为了展示排序的工作原理,我创建了两种排序方法。同样,我本可以在 CHistoryItem 类中做更多的工作,并为其提供一个 operator < 方法,但那样我所做的事情可能就不那么明显了。基本上,排序类必须有一个 operator () 方法,该方法返回一个布尔值,并由 sort() 算法传递两个向量元素。你的任务是在第一个项目应该放在排序输出中第二个项目之前返回 true,否则返回 false。

// Ascending date sorting function
struct SAscendingDateSort
{
     bool operator()(CHistoryItem*& rpStart, CHistoryItem*& rpEnd)
     {
          return rpStart->GetTimestamp() < rpEnd->GetTimestamp();
     }
};

// Descending date sorting function
struct SDescendingDateSort
{
     bool operator()(CHistoryItem*& rpStart, CHistoryItem*& rpEnd)
     {
          return rpStart->GetTimestamp() > rpEnd->GetTimestamp();
     }
};

现在我们只需要一些东西来创建我们的向量,对其进行排序,然后做一些可以指示我们输出内容的事情。这是一个简单的控制台应用程序,可以用来测试我们的示例。

// Stuff a vector with data & then sort
int main(int argc, char* argv[])
{
     CHistoryVector HistoryVector;

     // Put two repair items in the vector
     HistoryVector.push_back(new CRepairItem(2*365.0));
     HistoryVector.push_back(new CRepairItem(5*365.0));

     // Now stick three installations items in the vector
     HistoryVector.push_back(new CInstallItem(3*365.0));
     HistoryVector.push_back(new CInstallItem (6*365.0));
     HistoryVector.push_back(new CInstallItem (4*365.0));

     // Finally we need to add a purchase item to the vector
     HistoryVector.push_back(new CPurchaseItem (1*365.0));

     //==================================
     // Sort the items in ascending order
     std::sort(HistoryVector.begin(), HistoryVector.end(), 
               SAscendingDateSort());

     // Now show the results!
     std::cout << "Ascending Sort\n";
     for (long lEle=0; lEle < HistoryVector.size(); ++lEle)
          HistoryVector[lEle]->OutputToStream(std::cout);

     //==================================
     // Sort the items in descending order
     std::sort(HistoryVector.begin(), HistoryVector.end(), 
               SDescendingDateSort());

     // Now show the new results!
     std::cout << "\nDescending Sort\n";
     for (lEle=0; lEle < HistoryVector.size(); ++lEle)
          HistoryVector[lEle]->OutputToStream(std::cout);


     getchar();     // Pause for a response
     return 0;
}

那么运行后它看起来怎么样?这里是输出:

Ascending Sort
Purchase:       365
Repair:         730
Install:        1095
Install:        1460
Repair:         1825
Install:        2190

Descending Sort
Install:        2190
Repair:         1825
Install:        1460
Install:        1095
Repair:         730
Purchase:       365

显然,日期没有转换为漂亮的字符串,但如果需要,我们可以添加这个...主要一点是注意第一组数据按升序排序,而第二组数据按降序排序。

Paul 的公司是 ADOPro.com

© . All rights reserved.