假设我有一个二叉树,其节点具有以下定义。
struct node
{
int key1 ;
int key2 ;
}
二进制搜索树是在key1的基础上创建的。现在可以在O(1)空间中基于key2重新排列二叉搜索树。虽然我可以使用指向节点的指针数组在变量空间中执行此操作。
我要求的实际问题是“计算文件中唯一字的出现次数,并按频率的降序显示结果。” 这里,BST节点是
{
char *word;
int freq ;
}
BST首先是根据字母的字母顺序创建的,最后我希望它基于频率。
我在选择数据结构时是错误的,即BST?
答案 0 :(得分:1)
在您选择的语言中使用HashTable(Java)或Dictionary(.NET)或等效数据结构(STL中的hash_set或hash_map)将在计数阶段为您提供O(1)插入,这与二进制搜索树不同取决于它是否平衡自身,将在插入时从O(log n)到O(n)的某处。如果性能非常重要,请确保您尝试将HashTable初始化为足够大的大小,以免动态调整大小,这可能会很昂贵。
至于按频率列出,我不能立即想到一个棘手的方法来做到这一点而不涉及排序,这将是O(n log n)。
答案 1 :(得分:1)
Map,BST很好,如果你需要为你的词典排序输出。
如果您需要混合添加,删除和查找操作,那就太好了。 我不认为这是你的需要。你加载字典,排序,然后只查看它,这是正确的? 在这种情况下,排序数组可能是更好的容器。 (参见Scott Meyer Effective STL的第23项) (更新:简单地认为地图可以比排序数组产生更多内存缓存未命中,因为数组在内存中获取其数据连续,并且地图中的每个节点都包含指向地图中其他节点的2个指针。你的对象很简单,在内存中占用的空间不大,有序的矢量可能是更好的选择。我热烈建议你从Meyer的书中读取这个项目)
关于你所说的那种,你需要从stl获得该算法: stable_sort。 这个想法是对字典进行排序,然后在频率键上使用stable_sort()进行排序。
它会给出类似的东西(没有经过实际测试,但你明白了):
struct Node
{
char * word;
int key;
};
bool operator < (const Node& l, const Node& r)
{
return std::string(l.word) < std::string(r.word));
}
bool freq_comp(const Node& l, const Node& r)
{
return l.key < r.key;
}
std::vector<node> my_vector;
... // loading elements
sort(vector.begin(), vector.end());
stable_sort(vector.begin(), vector.end(), freq_comp);
答案 2 :(得分:1)
以下是我根据新密钥重新平衡树的建议(好吧,我有2个建议)。
第一个也是更直接的是以某种方式调整Heapsort的“冒泡”功能(使用Sedgewick的名字)。这是wikipedia的链接,他们称之为“筛选”。它不是为完全不平衡的树(这是你需要的)设计的,但我相信它展示了树的就地重新排序的基本流程。它可能有点难以理解,因为树实际上存储在数组中而不是树中(尽管逻辑在某种意义上将其视为树) - 但是,你可能会发现这样一个基于数组的树表示最好!谁知道呢。
我的更疯狂的建议是使用一棵树。我认为他们很漂亮,而这里是wiki link。基本上,您访问的任何元素都“冒泡”到顶部,但它保持BST不变量。所以你保留了用于构建初始树的原始Key1,但希望大多数“更高频率”值也接近顶部。这可能还不够(因为它意味着更高频率的词将“靠近”树的顶部,不一定以任何方式排序),但如果您碰巧拥有或找到或制作树 - 平衡算法,它可以在这样的splay树上运行得更快。
希望这有帮助!谢谢你有一个有趣的谜语,这对我来说听起来像是一个很好的Haskell项目...... :)
答案 3 :(得分:1)
您可以在O(1)空间中轻松完成此操作,但不能在O(1)时间内执行此操作; - )
即使重新排列整个树直到它再次排序似乎是可能的,它可能不是很快 - 最多可能是O(n),在实践中可能更糟。因此,一旦完成树并且只使用频率上的快速排序(平均为O(log n))对数组进行排序,就可以通过将所有节点添加到数组中来获得更好的结果。至少那就是我要做的。即使是艰难的它需要额外的空间,这对我来说比重新安排树木更有希望。
答案 4 :(得分:1)
我认为您可以创建一个按freq
排序的新树,并将所有元素从旧树中弹出。
可能 O(1)虽然可能更像O(log N)
,但不管怎么说都不大。
另外,我不知道你如何在C#中调用它,但在Python中你可以使用list但是可以用两个不同的键对它进行排序。
答案 5 :(得分:0)
您可以考虑的一种方法是构建两个树。一个由word
编制索引的索引,其中一个索引为freq
。
只要树节点包含数据节点的指针,您就可以通过基于word
的树来访问以更新信息,但稍后可以通过{基于{1}}的树输出。
虽然,如果速度真的那么重要,我会寻找摆脱字符串作为关键。字符串比较非常慢。
如果速度不重要,我认为您最好的选择是根据freq
收集数据,并根据yves建议的word
进行重新排序。