二叉树:迭代顺序打印
Binary Tree: iterative inorder print
我已经编写了一个红黑树实现,带有内置的按顺序遍历(使用嵌套的class Iterator
)。
我正在寻找一种(如果可能的话,是迭代的)算法,该算法使用有序遍历以图形方式打印二进制树
打印方向不相关,即命令行输出中的树可以像这样定向(格式化):
2
/
1 4
/
3 5
或者像这样:
|1
|
|
2
| |3
| |
|4
|
|5
或者甚至颠倒,但是应该使用顺序内遍历打印树,使用下面提供的方法:
void Iteraor::first(); // Traverses to the first node.
void Iterator::next(); // Traverses to the next node.
void Iterator::last(); // Traverses to the last node.
所以有可能做这样的东西:
RBTree tree;
/* Tree init. */
Iterator from(&tree), until(&tree);
from.first();
until.last();
for (Iterator i = from; i != until; i.next()) {
// PRINTING.
}
这是原始代码:
/** A program for Red-Black Tree manipulation: insertion and value retrieval.
* All position relations (first, last, previous, next) are in-order.
*/
class RBTree {
struct Node {
enum class Colour : bool { RED, BLACK };
int value;
Node *left, *right, *parent;
Colour colour;
public:
/* ... */
};
class Iterator {
class Stack {
/* ... */
};
Stack stack;
const RBTree* const tree; // Once set, neither the reference nor the referenced object's attributes can be modified.
Node* pointer;
public:
Iterator(const RBTree*);
void first();
void next();
void last();
/* ... */
Node* getNode() const;
bool operator != (const Iterator&) const;
};
Node *root;
Iterator iterator;
public:
RBTree() : root(nullptr), iterator(this) {}
/* ... */
bool printTree() const;
~RBTree() { deleteTree(); }
};
// TREE // public: //
/* ... */
bool RBTree::printTree() const {
if (root != nullptr) {
// print ??
return true;
}
else
return false;
}
// NODE: Ensures the proper connection. //
void RBTree::Node::setLeft(Node *p_left) {
left = p_left;
if (p_left != nullptr)
p_left->parent = this;
}
void RBTree::Node::setRight(Node *p_right) {
right = p_right;
if (p_right != nullptr)
p_right->parent = this;
}
// ITERATOR //
RBTree::Iterator::Iterator(const RBTree* p_tree) : tree(p_tree), pointer(p_tree->root) {}
// Traverses to the first node (leftmost).
void RBTree::Iterator::first() {
if (pointer != nullptr) {
while (true) {
if (pointer != nullptr) {
stack.push(pointer);
pointer = pointer->left;
}
else {
pointer = stack.peek();
break;
}
}
}
}
// Traverses to next node in-order.
void RBTree::Iterator::next() {
if (pointer != nullptr) {
if (!stack.isEmpty()) {
pointer = stack.pop();
if (pointer->right != nullptr) {
pointer = pointer->right;
first();
}
}
}
}
// Traverses to the last node (rightmost).
void RBTree::Iterator::last() {
pointer = tree->root;
if (pointer != nullptr)
while (pointer->right != nullptr)
pointer = pointer->right;
stack.clear();
}
/* ... */
RBTree::Node* RBTree::Iterator::getNode() const {
return pointer;
}
bool RBTree::Iterator::operator != (const Iterator& p_iterator) const {
return pointer != p_iterator.pointer ? true : false;
}
我曾研究过一个类似问题的答案,但没有一种算法使用按顺序遍历(而且大多数是递归的)。
编辑:
根据@nonsensickle的建议,代码被压缩到最低限度。
使用迭代算法进行有序遍历的规范方法是维护需要打印的节点的堆栈(或LIFO队列)。每个循环迭代做两件事中的一件:
-
如果您不在叶上,请将当前节点推到堆栈上,然后移动到其最左边的子节点。
-
如果你在一个叶子上,打印它,将顶部节点从堆栈中弹出,打印出来,然后移到它最右边的子节点。
你继续,直到你的堆栈是空的,你在一片树叶。
节间分支的格式和图形表示的生成显然取决于您。请记住,这将需要一些额外的状态变量。
编辑
我所说的"一些额外的状态变量"是这样的。
为了提供漂亮的打印,你需要跟踪三件事:
-
要打印的当前节点位于树的哪个级别(从底部开始计数)。这告诉您(的一部分)将其缩进多远(或者如果使用二维图形库,则将其从画布边缘偏移)。
-
当前要打印的节点是左子节点还是右子节点。这将(再次)告诉您它与同级分支的缩进距离,以及连接它与其父分支的分支的方向。
-
节点离"中心"有多少个节点。这也有助于与(非同级)邻居保持适当的间距。
也许可以减少迭代到迭代状态的次数,但这对我来说很有效。
相关文章:
- 如何在C++中递归地按相反顺序打印集合
- 首先按给定顺序打印所有数字,然后使用 Array 打印所有字符和其他符号
- 按字母顺序打印存储在字符数组中的信息
- 视觉C++未按所需顺序打印
- C++使用相反的顺序打印带有逗号的列表
- C/C++ - 用于按顺序打印数字的 sem_t 类型的单个信号量
- 对象指针打印结果以相反的顺序进行
- 链表缺少节点并在打印时颠倒顺序
- 如何以相反顺序C 打印整数的单个数字
- 我不知道如何创建一个以数字/字母顺序打印出我的整数或字符串的程序
- 在 C Linux 中使用三个线程使用信号量同步按顺序打印 3 4 5 50 次
- 以相反的顺序打印链表的后半部分
- 我如何附加双链接以指向正确的节点,以相反的顺序打印
- 为什么在打印东西时没有保留顺序,先用cerr,然后用cout
- 按字母顺序打印结构输入C
- 按顺序打印时遇到问题,二叉树的后顺序等
- 打印所有可能的组合,包括重复,顺序也很重要
- 按特定顺序打印队列
- C++ 中的打印顺序
- 为什么这段代码的打印顺序不像我预期的那样工作?