承接上篇,本文詳細剖析前序遍歷迭代器的實現。前序遍歷順序:根 → 左子樹 → 右子樹(多叉樹泛化為:根 → 第一個孩子子樹 → 下一個兄弟子樹)。同樣採用順序存儲 + 偏移量 + 模板迭代器架構。
typedef pre_iterator_impl<false, false> pre_iterator;
typedef pre_iterator_impl<false, true> reverse_pre_iterator;
typedef pre_iterator_impl<true, false> const_pre_iterator;
typedef pre_iterator_impl<true, true> const_reverse_pre_iterator;
與後序遍歷類似,但語義不同:
forward_first():正向第一個 = 子樹根forward_last():正向最後個 = 最右最深葉子skip_progeny_:標記是否跳過後代(前/後序特有,兄弟/葉子/深度迭代器無此語義)void forward_first() { off_ = root_; }
void forward_last() {
off_ = root_;
node_pointer_type p = &(*tree_)[off_];
while (p->last_child_) { // 一直向最後一個孩子走
off_ += p->last_child_;
p = &(*tree_)[off_];
}
}
邏輯分支:
end()void forward_next() {
node_pointer_type p = &(*tree_)[off_];
if (!skip_progeny_ && p->first_child_) {
off_ += p->first_child_; // 進入第一個孩子
} else if (off_ != root_ && p->next_sibling_) {
off_ += p->next_sibling_; // 轉右兄弟
} else {
while (off_ != root_ && p->parent_ && !p->next_sibling_) {
off_ -= p->parent_; // 回溯父節點
p = &(*tree_)[off_];
}
if (off_ == root_ || !p->parent_) off_ = tree_->size();
else off_ += p->next_sibling_;
}
}
邏輯分支:
end()void forward_prev() {
node_pointer_type p = &(*tree_)[off_];
if (off_ != root_ && p->prev_sibling_) {
off_ -= p->prev_sibling_;
p = &(*tree_)[off_];
while (p->last_child_) { off_ += p->last_child_; p = &(*tree_)[off_]; }
} else {
if (off_ == root_ || !p->parent_) off_ = tree_->size();
else off_ -= p->parent_;
}
}
| 操作 | 前序 | 後序 |
|---|---|---|
| first | 根節點 | 最左最深葉子 |
| last | 最右最深葉子 | 根節點 |
| next 主邏輯 | 優先進孩子,再右兄弟,最後回溯找右兄弟 | 優先右兄弟子樹最左葉,否則回父節點 |
| prev 主邏輯 | 優先左兄弟子樹最右葉,否則回父節點 | 優先孩子/左兄弟,最後回溯找左兄弟 |
mtree<int, false> mt;
auto root = mt.get_root();
mtree<int, false>::pre_iterator it = root;
auto last = --it.end();
for (it = it.begin(); it != it.end(); ++it) {
cout << *it;
if (it != last) cout << ' ';
}
// 反向遍歷
mtree<int, false>::reverse_pre_iterator rit = root;
auto rlast = --rit.end();
for (rit = rit.begin(); rit != rit.end(); ++rit) {
cout << *rit;
if (rit != rlast) cout << ' ';
}
iterator_base_impl、標簽分發、算術運算實現reverse_trait 將方向決策下沉到模板實例化,零運行期分支off_(當前偏移)、root_(子樹根)、skip_progeny_(跳過後代標記)掌握前序與後序迭代器的對稱邏輯,即掌握了樹遍歷的「陰陽兩面」,為實現層序、深度、葉子等其他迭代器奠定堅實基礎。