如果在C ++ STL 中已经可以使用它们自己定义和实现数据结构(例如stack
),该怎么做?
两个实现之间有什么区别?
答案 0 :(得分:2)
首先,自己实现一个现有的数据结构是一个有用的练习。您可以更好地了解它的作用(因此您可以更好地了解标准containers的作用)。特别是,您会更好地理解time complexity为何如此重要。
然后,存在实施质量问题。标准实现可能不适合您。
让我举个例子。实际上,std::stack
正在实现堆栈。这是一个通用的实现。您测量过sizeof(std::stack<char>)
吗?您是否对它进行了基准测试(在平均一百万个3.2个元素的堆栈中带有Poisson distribution)?
也许在您的 情况下,您碰巧知道自己有数百万个char
-s堆栈(从不 NUL ),而其中的99%它们的元素少于4个。有了这些额外的知识,您可能应该能够实现比标准C ++堆栈所提供的“更好”的东西。因此std::stack<char>
可以工作,但是只要有了额外的知识,您就可以以不同的方式实现它。您(出于可读性和维护性考虑)仍将使用与std::stack<char>
中相同的方法-因此您的WeirdSmallStackOfChar
将具有push
方法,依此类推。在项目进行期间),您意识到或者更大的堆栈可能有用(例如,在1%的情况下),您将以不同的方式重新实现堆栈(例如,如果您的代码库增长到一百万行C ++,并且您意识到自己通常会更大堆栈,您可以“删除”您的WeirdSmallStackOfChar
类并添加typedef std::stack<char> WeirdSmallStackOfChar;
....)
如果您偶然发现 all 个堆栈少于4个char
-s并且\0
在其中无效,则表示这样的“堆栈” -s作为char w[4]
字段可能是最明智的方法。这是快速简便的代码。
因此,如果性能和内存空间很重要,那么您可能会编写类似于
的怪异代码class MyWeirdStackOfChars {
bool small;
union {
std::stack<char>* bigstack;
char smallstack[4];
}
当然,这是非常不完整的。当small
为真时,您的实现将使用smallstack
。对于错误率为1%的情况,您的实现使用bigstack
。 MyWeirdStackOfChars
的其余部分留给读者作为练习(不是那么容易)。不要忘记遵循rule of five。
好吧,也许上面的例子令人信服。但是std::map<int,double>
呢?您可能有数百万个,并且您可能知道其中的99.5%小于5。您显然可以针对这种情况进行优化。在内存和CPU时间方面,用int
和double
对的阵列表示小地图很有可能更有效。
有时候,您甚至知道所有您的地图上的条目少于16个(并且std::map<int,double>
不知道),并且键为从不 0。那么您可能会不同地表示它们。在这种情况下,我想我可以实现比std::map<int,double>
提供的功能更有效的功能(可能是由于cache的影响,一个由16个条目组成的数组,其中包含一个int
和一个double
是最快的)。
这就是为什么任何开发人员都应该了解经典算法(并且已经阅读过Introduction to Algorithms)的原因,即使在许多情况下,他将使用现有的容器也是如此。另请注意as-if rule。
答案 1 :(得分:1)
对于每个可能的用例,数据结构的STL实现并不完美。
我喜欢哈希表的示例。我已经使用STL实现了一段时间,但是我主要将其用于竞争性编程竞赛。
想象一下您是Google,您有数十亿美元用于存储和访问哈希表的资源。通常,您可能希望为公司用例提供可能的最佳实施方式,因为它通常会节省资源并加快搜索速度。 哦,我忘了提及您,您也有一些地球上最好的工程师为您工作(:
(该视频由Kulukundis制作,谈论了他的Google团队制作的新哈希表) https://www.youtube.com/watch?v=ncHmEUmJZf4
其他一些理由可以实现您的数据结构的自己的版本:
测试您对特定结构的了解。
自定义结构的一部分 以适应某些特殊的用例。
在特定数据结构上寻求比STL更好的性能。
讨厌STL错误。
基准测试 STL以实现一些简单的实现。