使用动态和非唯一键存储大量数据的最佳数据结构?

时间:2010-06-18 22:37:17

标签: data-structures

基本上,我有大量的C结构要跟踪,基本上是:

struct Data {
    int key;
    ...        // More data
};

我需要定期访问其中的大量(数百个),并且必须从最低key值到最高值{{1}}进行排序。键不是唯一的,它们将在程序过程中更改。为了使问题更加有趣,大多数结构将在排序之前从池中剔除(基于与键值完全无关的标准),但我仍然需要保留对它们的引用。

我已经研究过使用二叉搜索树来存储它们,但是不保证密钥是唯一的,并且我不完全确定一旦更改密钥或如何剔除特定结构,如何重组树。

回顾以上不清楚的情况,我需要:

  1. 使用非唯一且动态的密钥存储大量结构。
  2. 剔除大部分结构(但不完全释放它们,因为每次都会剔除不同的结构)。
  3. 将剩余结构从最高到最低键值排序。
  4. 您将使用哪些数据结构/算法来解决此问题?该方法需要尽可能快和/或内存效率,因为这是一个实时应用程序。

    编辑:剔除是通过迭代所有对象并为每个对象做出决定来完成的。密钥在剔除/分拣运行之间改变。我应该声明它们不会发生很大的变化,但它们会发生变化,并且它们可以在剔除/分拣运行之间进行多次更改。 (如果有帮助,每个结构的键实际上是Sprite的z顺序。它们需要在每个绘制循环之前进行排序,以便首先绘制具有较低z顺序的Sprite。)

2 个答案:

答案 0 :(得分:2)

这类问题的一般解决方案是使用平衡搜索树(例如AVL树,红黑树,B树),它保证O(log n)时间(几乎恒定,但不完全)插入,删除和查找,其中n是当前存储在树中的项目数。保证没有密钥存储在树中两次是非常简单的,并且由许多实现自动完成。

如果您使用的是C ++,则可以尝试使用std::map<int, yourtype>。如果在C中,找到或实现一些简单的二叉搜索树代码,看看它是否足够快。

但是,如果您使用这样的树并发现它太慢,您可以查看一些更精细的方法。一种可能是将结构放在一个大数组中,radix sort用整数键,剔除它,然后每次传递重新排序。另一种方法可能是使用Patricia树。

答案 1 :(得分:2)

将它们全部放在一个大阵列中。

当需要进行剔除和排序时,首先要进行排序。进行插入排序。这是对的 - 没什么聪明的,只是插入排序。

排序后,浏览已排序的数组,并对每个对象进行剔除决策,如果没有剔除,则立即输出该对象。

这与内存效率大致相同。它还应该只需要很少的计算:没有关于剔除/排序过程之间的更新的记录,并且排序将是便宜的 - 因为插入排序是自适应的,并且对于像这样的几乎排序的数组,它几乎是O(n) 。它没有做的一件事是缓存局部性:在数组上有两个单独的传递,用于排序和剔除/输出。

如果您需要更多的聪明,那么您可以使用另一种更快的就地排序,而不是插入排序。 Timsort和smoothsort是很好的候选人;实施起来都是非常可恶的。

对此的一个重要替代方法是仅使用您排序(或保留在二叉树或其他任何内容中)的此类对象的辅助临时列表来排序未被清除的对象。但问题是,如果键没有那么大的改变,那么你在几乎排序的数组上使用自适应排序所获得的胜利(我认为!)将超过你从排序较小数据集中获得的胜利。它是O(n)vs O(n log n)。