我不确定如何遍历下面的树形结构,以使节点始终按升序排列。对数组[9 8 7 6 5 4 3 2 1 0]
进行堆操作得到数组[0 1 3 2 5 4 7 9 6 8]
,我认为它对应于此表示:
想要保留数组(因为我希望以后能够高效地插入),如何有效地按升序遍历它呢?(即按[0 1 2 3 4 5 6 7 8 9]
的顺序访问节点)
我不确定如何遍历下面的树形结构,以使节点始终按升序排列。对数组[9 8 7 6 5 4 3 2 1 0]
进行堆操作得到数组[0 1 3 2 5 4 7 9 6 8]
,我认为它对应于此表示:
想要保留数组(因为我希望以后能够高效地插入),如何有效地按升序遍历它呢?(即按[0 1 2 3 4 5 6 7 8 9]
的顺序访问节点)
只需对数组进行排序。排序后仍将保持最小堆性质,没有其他算法在渐近意义下更加高效。
self-balancing binary search tree (BST)
二叉搜索树(BST)是一种基于节点的二叉树数据结构,具有以下特性:
- 一个节点的左子树只包含键值小于该节点的键的节点。
- 一个节点的右子树只包含键值大于该节点的键的节点。
- 左右子树都必须是二叉搜索树。
- 不能有重复的节点。
使用BST以排序的方式遍历(称为中序遍历)比使用堆更简单且更节省空间。
BST将支持O(log n)插入和O(n)遍历。
如果您要在再次进行遍历之前进行大量插入,则将其排序为数组可能更有效 - 相关的运行时间为O(1)插入和O(n log n)获取排序顺序 - 此选项比使用BST更有效的确切点需要进行基准测试。
i
的节点的左右子节点分别在2i
和2i+1
处。我不知道是否有任何库执行此操作,可能是因为调整大小的成本很大。 - Bernhard Barker如果您不需要重复项,可以使用std::set
。 std::set
迭代器将按顺序遍历并根据默认比较器维护排序。对于int类型,默认比较器是<,但如果您使用rbegin()
以相反的顺序遍历,则可以从最高到最低遍历。或者您可以添加自定义比较器。前者如下所示:
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main() {
vector<int> data{ 5, 2, 1, 9, 10, 3, 4, 7, 6, 8 };
set<int> ordered;
for (auto n : data) {
ordered.insert(n);
// print in order
for (auto it = ordered.rbegin(); it != ordered.rend(); it++) {
cout << *it << " ";
}
cout << endl;
}
return 0;
}
Output:
5
5 2
5 2 1
9 5 2 1
10 9 5 2 1
10 9 5 3 2 1
10 9 5 4 3 2 1
10 9 7 5 4 3 2 1
10 9 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1