在搜索和排序数据时,最基本的数据结构之一是二叉搜索树。然而,二叉搜索树的性能高度依赖于它的形状,在最坏的情况下,它可以退化为时间复杂度为 O(n) 的线性结构。这就是红黑树的用武之地,它们是一种平衡的二叉搜索树,它使用一组特定的规则来确保树始终是平衡的。这种平衡保证了插入、删除和搜索等操作的时间复杂度始终为 O(log n),而不管树的初始形状如何。
红黑树是自平衡的,这意味着树会在每次插入或删除操作后自动调整自身。它使用一种简单但强大的机制来保持平衡,方法是将树中的每个节点着色为红色或黑色。
红黑树是一种二叉搜索树,其中每个节点都用红色或黑色着色。它是一种自平衡二叉搜索树。它具有良好高效的最坏情况运行时间复杂度。
大多数 BST 操作(例如,搜索、最大、最小、插入、删除等)需要 O(h) 时间,其中 h 是 BST 的高度。对于倾斜的二叉树,这些操作的成本可能变为 O(n)。如果我们确保在每次插入和删除之后树的高度保持为 O(log n),那么我们可以保证所有这些操作的上界为 O(log n)。红黑树的高度总是 O(log n),其中 n 是树中的节点数。
import (
rbt "github.com/emirpasic/gods/trees/redblacktree"
)
type TweetCounts struct {
counts map[string]*rbt.Tree
}
func Constructor() TweetCounts {
return TweetCounts{
counts: map[string]*rbt.Tree{},
}
}
func (this *TweetCounts) RecordTweet(tweetName string, time int) {
if _, ok := this.counts[tweetName]; !ok {
this.counts[tweetName] = rbt.NewWithIntComparator()
}
counts, _ := this.counts[tweetName]
if oldCountVal, ok := counts.Get(time); ok {
counts.Put(time, oldCountVal.(int) + 1)
} else {
counts.Put(time, 1)
}
}
func (this *TweetCounts) GetTweetCountsPerFrequency(freq string, tweetName string, startTime int, endTime int) []int {
k := 1
switch freq {
case "minute":
k = 60
case "hour":
k = 3600
case "day":
k = 86400
}
buckets := make([]int, (endTime - startTime) / k + 1)
counts, ok := this.counts[tweetName]
if !ok {
return buckets
}
ceilingNode, ok := counts.Ceiling(startTime)
if !ok {
return buckets
}
for it := counts.IteratorAt(ceilingNode); ; {
t := it.Key().(int)
count := it.Value().(int)
if t > endTime {
break
}
buckets[(t - startTime) / k] += count
if !it.Next() {
break
}
}
return buckets
}