Java Big-O 性能
我对我的课堂项目的表现有疑问。
我有大约 5000 个通过读取文本文件形成的游戏对象。我有一个 Treemap
(称为超级树),它作为其节点 Treemaps
(我猜是迷你树图)。这些节点/迷你树图是动作、策略、冒险、体育、游戏标题等。基本上是游戏类型,这些迷你树将保存游戏对象。因此,supertree
本身可能会容纳 8 个节点/树图
。
当我插入游戏对象时,它将确定它将转到哪个迷你树并将其放入其中。例如,如果我插入游戏超级马里奥世界,它会检查它是什么类型,并发现它是冒险
,所以超级马里奥世界会被插入到冒险
树中。
所以我的问题是,如果问题列出所有动作游戏,性能会怎样,因为树图获取的时间复杂度为 O(log n)
首先,它将在超级树中查找动作节点/Treemap,这将需要 O(log n)。
然后,一旦进入 Action 树形图
,它将获取所有元素,这将是 o(n log n) 正确的吗?
那么 log n * (n * log n)
的总性能是正确的吗?这比o(n)
更糟糕。
[编辑] 希望这能澄清我的帖子。
I have a question about the performance of my class project.
I have about 5000 game objects formed from reading a text file. I have a Treemap
(called supertree) that holds as its nodes Treemaps
(mini treemaps I guess). These nodes/mini treemaps
are action, strategy, adventure, sports, gametitle, etc. Basically game genres and these mini trees will will hold game objects. So the supertree
itself will hold probably 8 nodes/treemaps
.
When I insert a game object, it will determine which mini tree
it will go to and put it in there. For example if I insert the game Super Mario World, it will check which genre it is and see that it's adventure
,so Super Mario World would be inserted into the adventure
tree.
So my question is what would be the performance if the question lists all the action games
, since a Treemap get is O(log n)
First at the super tree it will look for the Action Node/Treemap
, which will take O(log n).
Then once inside the Action treemap
, it will do get for all elements which would be o(n log n) correct?
So the total performance of log n * (n * log n)
is correct? Which is worst than o(n)
.
[edit]
Hopefully this clarified my post a bit.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
虽然获取超级地图的时间复杂度为 O(n_categories),但遍历另一个地图(使用迭代器)应该为 O(n_games)。如果 n_categories 的上限为 10(因为添加新游戏时类别数量不会改变),则可以假设 supermap 查找为 O(1)。
由于子地图最多可以有 n_games 个条目(当所有条目都属于同一类别时),因此列出所有动作类型的游戏将为您提供 O(n_games)。不要忘记,为了迭代所有条目,您不必每次都调用 get()。这就像阅读一本书,而不是翻页从第 100 页到第 101 页,而是从开头开始计数并数到 101...
编辑:由于上面的段落指出如果类别数量是固定的,人们可以假设类别查找为 O(1) 似乎很难接受,让我说,即使您坚持类别查找为 O(log n_categories),仍然给出 O(n_games),因为类别查找必须是只完成一次。然后,迭代结果,即 O(n_games)。这导致 O(n_games + log n_categories) = O(n_games)。
While the get on the supermap is O(n_categories), and going through the other map (using an iterator) should be O(n_games). If you n_categories has an upper bound of say 10 (because the number of categories doesn't change when adding new games), you can assume the supermap lookup to be O(1).
Since the submaps can have at most n_games entries (when all belong to the same category), listing all games of type action thus gives you O(n_games). Don't forget that in order to iterate over all entries you don't have to call get() each time. That would be like reading through a book and instead of turning the page to get from page 100 to 101, start counting at the beginning and count to 101...
EDIT: Since the above paragraph stating that if the number of categories is fixed , one can assume the category lookup to be O(1) seems to be hard to accept, let me say that even if you insist category lookup is O(log n_categories), that still gives O(n_games) since the category lookup has to be done only once. Then, you iterate over the result, which is O(n_games). This leads to O(n_games + log n_categories) = O(n_games).
好吧,首先,你的大 O 不会根据语言而改变;这就是人们使用大 O(渐近)表示法的原因。
现在,考虑一下你的整个算法。您获取外部树并获取每个元素,这确实是O(n0 lg n0)。对于每个节点,您都有 O(n1 lg n1)。 lg n 仅相差一个常数,因此可以将它们组合起来,得到 O(no×n1 lg n),或 O(n2 lg n)。
Okay, first thing, your big-O isn't going to change depending on language; that's why people use big-O (asymptotic) notation.
Now, think about your whole algorithm. You take your outer tree and get each element, which is indeed O(n0 lg n0). For each of those nodes, you have O(n1 lg n1). The lg n's differ by only a constant, so they can be combined, and you get O(no×n1 lg n), or O(n2 lg n).
关于OP分析的一些评论:
我假设您已经构建了树图/集,并且只是从完成的(预处理的)内存表示中提取元素。
假设 n 是流派的数量。假设 m 是每种类型的最大游戏数量。
获取正确的“流派地图”的复杂度是
O(lg n)
(超级树的单个get
)。迭代该类型游戏的复杂性取决于您的操作方式:此代码会产生
O(m)
复杂度为O(lg m)
的“get”操作,所以这是O(m lg(m))
。如果这样做:
那么复杂性是
O(m)
循环迭代,并且访问该值的时间为常量(O(1))
次。使用第二种地图迭代方法,您的总复杂度为
O(lg(n) + m)
A couple of comments regarding the OP's analysis:
I'm assuming you have already constructed your treemaps/sets and are just extracting elements from the finished (preprocessed) in-memory representation.
Let's say n is the number of genres. Let's say m is the max number of games per genre.
The complexity of getting the right 'genre map' is
O(lg n)
(a singleget
for the supertree). The complexity of iterating over the games in that genre depends on how you do it:This code yields
O(m)
'get' operations ofO(lg m)
complexity each, so that'sO(m lg(m))
.If you do this:
then the complexity is
O(m)
loop iterations with constant(O(1))
time access to the value.Using the second map iteration method, your total complexity is
O(lg(n) + m)
呃,直到最后一段你都是对的。
总复杂度为
O(n logn)
,logn
查找类型,n
列出该类型中的所有值。如果您正在讨论列出所有内容,那么它绝对不是
O(n^2 logn)
,因为获取树中的所有值是线性的。这将是O(n^2)
。使用平面列表执行相同的操作将是
O(n logn)
,因此使用树肯定会损失性能(更不用说内存)。Er, you were right until the last paragraph.
Your total complexity is
O(n logn)
,logn
to look up the type andn
to list all the values in that type.If you're talking about listing everything, it's definitely not
O(n^2 logn)
, since getting all the values in your tree is linear. It would beO(n^2)
.Doing the same thing with a flat list would be
O(n logn)
, so you're definitely losing performance (not to mention memory) by using a tree for this.