标签:roo last bre oid vat root 结束 head cout
如果是使用递归来实现二叉树的先,中,后序遍历只需要更改三行代码的位置,但若是使用栈来写那便会有趣得多
遍历方式 | 输出优先级 |
---|---|
先序 | 根结点>左子树>右子树 |
中序 | 左子树>根结点>右子树 |
后序 | 左子树>右子树>根节点 |
栈内元素是指向结点的指针
无论是根节点还是左右子树在栈中的表示方式是一样的都是指针,所以我们可以将左右子树各当作是"一个结点",这样问题就简化为具有3个结点的完全二叉树的输出了
在简化的基础上再考虑上特殊情况规则就可以实现了
通用逻辑栈中初始化只有一个指向根节点的指针,当栈为空时遍历结束
void preorder_travel() {
if (root == NULL)
return;
std::stack<Node*> s;
s.push(root);//根指针入栈
while (!s.empty())
{
std::cout << s.top()->data << " ";//输出栈顶指针指向的结点
Node* temp = s.top();//备份栈顶指针
s.pop();//栈顶指针出栈
if (temp->R != NULL) s.push(temp->R);//备份指向结点右子树不为空则将其压入栈
if (temp->L != NULL) s.push(temp->L);//备份指向结点左子树不为空则将其压入栈
}
}
void inorder_travel() {
if (root == NULL)
return;
std::stack<Node*> s;
s.push(root);//根指针入栈
while (!s.empty())
{
while (s.top()->L != NULL)//重复将栈顶指针指向结点的左子树压栈,直到栈顶指针指向结点的左子树为空
{
s.push(s.top()->L);
}
while (!s.empty())//重复检查
{
std::cout << s.top->data << " ";//输出栈顶指针指向的结点
Node* temp = s.top();//备份栈顶指针
s.pop();//栈顶指针出栈
if (temp->R != NULL) {//如果栈顶指针指向的结点右子树不为空,则将其右子树入栈,退出检查
s.push(temp->R);
break;
}
}
}
}
void postorder_travel() {
if (root == NULL)
return;
std::stack<Node*> s;
s.push(root);//根指针入栈
while (!s.empty())
{
while (s.top()->L != NULL)//重复将栈顶指针指向结点的左子树压栈,直到栈顶指针指向结点的左子树为空
{
s.push(s.top()->L);
}
Node* last = NULL;//上一次遍历过的指针
while (!s.empty())//重复检查
{
if (s.top()->R==NULL||last==s.top()->R) {//如果栈顶指针指向结点的右子树为空或者遍历过
std::cout << s.top()->data << " ";//输出栈顶指向的结点
last = s.top();//更新指针last
s.pop();//栈顶指针出栈
}
else if(s.top()->R!=NULL)//如果栈顶指针指向的结点的右子树不为空
{
s.push(s.top()->R);//将右子树入栈
break;//退出检查
}
}
}
}
#include <iostream>
#include <stack>
template <typename T>
class BST {
public:
BST() :root(NULL) {};
~BST() {};
void insert(T data) {
Node* temp = new Node();
temp->L = NULL;
temp->R = NULL;
temp->data = data;
if (root == NULL) {
root = temp;
}
else {
Node* tracer = root;
while (true)
{
if (tracer->data >= data)
if (tracer->L == NULL) {
tracer->L = temp;
break;
}
else
tracer = tracer->L;
else
if (tracer->R == NULL) {
tracer->R = temp;
break;
}
else
tracer = tracer->R;
}
}
}
void preorder_travel() {
if (root == NULL)
return;
std::stack<Node*> s;
s.push(root);//根指针入栈
while (!s.empty())
{
std::cout << s.top()->data << " ";//输出栈顶指针指向的结点
Node* temp = s.top();//备份栈顶指针
s.pop();//栈顶指针出栈
if (temp->R != NULL) s.push(temp->R);//备份指向结点右子树不为空则将其压入栈
if (temp->L != NULL) s.push(temp->L);//备份指向结点左子树不为空则将其压入栈
}
}
void inorder_travel() {
if (root == NULL)
return;
std::stack<Node*> s;
s.push(root);//根指针入栈
while (!s.empty())
{
while (s.top()->L != NULL)//重复将栈顶指针指向结点的左子树压栈,直到栈顶指针指向结点的左子树为空
{
s.push(s.top()->L);
}
while (!s.empty())//重复检查
{
std::cout << s.top->data << " ";//输出栈顶指针指向的结点
Node* temp = s.top();//备份栈顶指针
s.pop();//栈顶指针出栈
if (temp->R != NULL) {//如果栈顶指针指向的结点右子树不为空,则将其右子树入栈,退出检查
s.push(temp->R);
break;
}
}
}
}
void postorder_travel() {
if (root == NULL)
return;
std::stack<Node*> s;
s.push(root);//根指针入栈
while (!s.empty())
{
while (s.top()->L != NULL)//重复将栈顶指针指向结点的左子树压栈,直到栈顶指针指向结点的左子树为空
{
s.push(s.top()->L);
}
Node* last = NULL;//上一次遍历过的指针
while (!s.empty())//重复检查
{
if (s.top()->R==NULL||last==s.top()->R) {//如果栈顶指针指向结点的右子树为空或者遍历过
std::cout << s.top()->data << " ";//输出栈顶指向的结点
last = s.top();//更新指针last
s.pop();//栈顶指针出栈
}
else if(s.top()->R!=NULL)//如果栈顶指针指向的结点的右子树不为空
{
s.push(s.top()->R);//将右子树入栈
break;//退出检查
}
}
}
}
private:
struct Node
{
Node* L;
Node* R;
T data;
};
Node* root;
};
int main(){
BST<int> b;
b.insert(2);
b.insert(4);
b.insert(1);
b.insert(5);
b.insert(3);
b.insert(0);
b.preorder_travel();
std::cout << std::endl;
b.inorder_travel();
std::cout << std::endl;
b.postorder_travel();
}
标签:roo last bre oid vat root 结束 head cout
原文地址:https://www.cnblogs.com/redo19990701/p/11302448.html