3个向量的高效排序算法
Posted
技术标签:
【中文标题】3个向量的高效排序算法【英文标题】:Efficient sorting algorithm for 3 vectors 【发布时间】:2015-04-20 16:25:52 【问题描述】:我有 3 个向量,category
description
和 price
我已经编写了这段代码,将由 category
组织的向量放入一个名为 menuFile
的文件中:
for(int x = 0; x < _category.size(); x++)
if(_category[x].compare("Starter") == 0)
menuFile << _category[x] << ":" << _description[x] << ":" << _price[x] << endl;
for(int x = 0; x < _category.size(); x++)
if(_category[x].compare("Main") == 0)
menuFile << _category[x] << ":" << _description[x] << ":" << _price[x] << endl;
for(int x = 0; x < _category.size(); x++)
if(_category[x].compare("Pudding") == 0)
menuFile << _category[x] << ":" << _description[x] << ":" << _price[x] << endl;
for(int x = 0; x < _category.size(); x++)
if(_category[x].compare("Drink") == 0)
menuFile << _category[x] << ":" << _description[x] << ":" << _price[x] << endl;
但这似乎不是一个非常有效的方法。有更好的方法吗?
【问题讨论】:
这就是 struct 和 class 存在的目的。category
、description
、price
分别是什么类型?它们只是字符串吗?似乎您希望 struct
将此数据作为一个组包含,然后您可以编写自定义比较运算符并在输出之前在您的向量上调用 std::sort
。
您几乎肯定希望从具有三个成员的结构(或类)开始,而不是三个向量,然后创建这些结构的向量。这样可以很容易地按照您选择的顺序对项目进行排序。
考虑在 codereview.stackexchange 上发布这个,那里似乎更合适。
是 'category' 唯一的排序方案(否则,您可能会看看 boost.org/doc/libs/1_58_0/libs/multi_index/doc/index.html - 虽然有点复杂)
【参考方案1】:
我相信你应该创建一个结构来处理这三种类型的数据,然后为它制作一个向量。
例如:
struct Menu
string category;
string description;
int price;
;
那么我建议您实施比较器来决定如何对数据进行排序。比方说按价格排序(你当然可以决定如何实现重载运算符)。
struct Menu
string category;
string description;
int price;
bool operator < (const Menu& rhs) const
return (this->price < rhs.price);
;
然后为这个结构创建一个向量并对其进行排序。
vector<Menu> menu;
// do something, insert data
sort(menu.begin(),menu.end());
然后相应地输出。
for(int x = 0; x < menu.size(); x++)
menuFile << menu[x].category << ":" << menu[x].description << ":" << menu[x].price << endl;
【讨论】:
我什至会说类别也应该是enum
Nicer 是按谓词(类别、描述或价格)排序
bool operator<(const Menu&rhs)const if(this.category!=rhs.category) return this.category<rhs.category; if(this.price!=rhs.price) return this.price<rhs.price; return this.description<rhs.description;
【参考方案2】:
我不知道你的容器类型是什么,所以我假设std::string
。最简单的方法可能是单独制作一个 vector
和 tuple
s:
using StrTuple = std::tuple<std::string*, std::string*, std::string*>;
std::vector<StrTuple> combined;
for (size_t i = 0; i < _category.size(); ++i)
combined.emplace_back(&_category[i], &_description[i], &_price[i]);
然后按类别排序:
std::sort(std::begin(combined), std::end(combined),
[](const StrTuple& lhs, const StruTuple& rhs)
return *std::get<0>(lhs) < *std::get<0>(rhs);
);
然后按顺序流式传输:
for (auto& t : combined)
menuFile << *std::get<0>(t) << ":" << *std::get<1>(t) << ":" << *std::get<2>(t) << std::endl;
同样可以使用单独的类型来实现,例如:
struct CombinedValues
std::string *category, *description, *price;
;
【讨论】:
【参考方案3】:我认为没有更有效的算法可以做到这一点。你可能会这么认为,因为你用同样的东西做了 4 次循环。但是你仍然在做 O(n) 效率。添加类似上述命题的排序操作会增加一个以 O(n*log(n)) 效率运行的步骤,这会更糟。
你仍然需要 4 个循环,所以我们唯一可以尝试优化的是测试,即用更快的方法替换每个循环中的字符串 compare() 操作。可能的方法是将字符串测试替换为整数测试,这意味着在新向量中预先计算类别编号(即,如果 category=="Starter",则值为 0,如果为“Main”,则值为 1,等等,并且值不同于0..3 如果不是任何有趣的类别(如果可能的话)
这意味着计算这个类别的初始循环可以提高效率(使用平均 2 个字符串比较)。甚至更少使用类别字符串的哈希映射。
所以在循环中,我们只对每个元素进行整数比较而不是字符串比较。但是,我们在第一个循环中添加了计算类别编号的时间。乍一看哪个更快并不明显:4 个循环和 4*n 字符串比较或 4 个循环、2*n 字符串比较和 4*n 整数比较。如果比较字符串比比较整数的成本要高得多,那可能会更快。
对于这类东西,唯一知道的方法是测量实际执行时间。显然,所有这些都非常耗时,因此只有在确实需要时才这样做(即您的分析器告诉您这部分需要优化)
【讨论】:
以上是关于3个向量的高效排序算法的主要内容,如果未能解决你的问题,请参考以下文章