为什么这个二叉树搜索比插入花费的时间长得多?
Why does this binary tree search take so much longer than an insertion?
我正在尝试 learn/understand 一些基本算法,今天我决定用 Go 编写一棵二叉树。结构如下所示:
type Node struct {
Value int
Left *Node
Right *Node
}
这是我检查树是否包含 int 的函数:
func (tree *Node) Contains(val int) bool {
if val == tree.Value {
return true
} else if val > tree.Value {
if tree.Right != nil {
return tree.Right.Contains(val)
} else {
return false
}
} else if val < tree.Value {
if tree.Left != nil {
return tree.Left.Contains(val)
} else {
return false
}
} else { // huh
return false
}
}
我写了一个测试函数来测试对树的不同操作需要多长时间。我的 Insert()
函数 34ms 插入 100,000 个随机整数,我的 Contains()
函数 33ms 检查是否这棵树包含 100,000 个随机整数。如果我将随机整数的数量增加到 1,000,000,我的 Insert()
函数需要 34ms 到 运行,但是我的 Contains()
函数突然需要 321ms 到 运行.
为什么 Contains()
运行 时间增加如此之快,而 Insert()
几乎保持不变?
Insert
函数应该定期重新平衡树,因为不平衡的树可能会导致遍历时间非常不平衡。因此,Insert
应该 通常比 Contains
.
慢
如果您的 Insert
函数没有重新平衡树,那么任何给定函数所需的时间将变为 O(n) 最坏情况而不是 O(log n) 并且相当不可预测。
此外,在谈论 O(...) 时间复杂度时,我们通常谈论的是最坏情况 行为。如果您对单个调用进行计时,那么任何给定的调用都可能比最坏的情况花费(少得多)时间——例如,Contains
寻找恰好是根的节点将立即 return 而不管尺寸。
我正在尝试 learn/understand 一些基本算法,今天我决定用 Go 编写一棵二叉树。结构如下所示:
type Node struct {
Value int
Left *Node
Right *Node
}
这是我检查树是否包含 int 的函数:
func (tree *Node) Contains(val int) bool {
if val == tree.Value {
return true
} else if val > tree.Value {
if tree.Right != nil {
return tree.Right.Contains(val)
} else {
return false
}
} else if val < tree.Value {
if tree.Left != nil {
return tree.Left.Contains(val)
} else {
return false
}
} else { // huh
return false
}
}
我写了一个测试函数来测试对树的不同操作需要多长时间。我的 Insert()
函数 34ms 插入 100,000 个随机整数,我的 Contains()
函数 33ms 检查是否这棵树包含 100,000 个随机整数。如果我将随机整数的数量增加到 1,000,000,我的 Insert()
函数需要 34ms 到 运行,但是我的 Contains()
函数突然需要 321ms 到 运行.
为什么 Contains()
运行 时间增加如此之快,而 Insert()
几乎保持不变?
Insert
函数应该定期重新平衡树,因为不平衡的树可能会导致遍历时间非常不平衡。因此,Insert
应该 通常比 Contains
.
如果您的 Insert
函数没有重新平衡树,那么任何给定函数所需的时间将变为 O(n) 最坏情况而不是 O(log n) 并且相当不可预测。
此外,在谈论 O(...) 时间复杂度时,我们通常谈论的是最坏情况 行为。如果您对单个调用进行计时,那么任何给定的调用都可能比最坏的情况花费(少得多)时间——例如,Contains
寻找恰好是根的节点将立即 return 而不管尺寸。