文章目录
- 前言
- 一、前序
- 二、中序
- 三、后序
前言
本文实现二叉树的前中后的非递归遍历,使用栈来模拟递归。
文字有点简略,需要看图和代码理解
树节点:
typedef char DATA;
//树节点
typedef struct Node
{DATA data; //数据struct Node* left; //左子树struct Node* right; //右子树bool ok; //判断完成左子树遍历 ,用于后序遍历Node(DATA d){ data = d;left = right = NULL;ok = true;}
}Node;
手搓树:
/构建树
void Tree::Achievements()
{Node* p1 = new Node('a');Node* p2 = new Node('b');Node* p3 = new Node('c');Node* p4 = new Node('d');Node* p5 = new Node('e');p1->left = p2;p1->right = p3;p2->right = p4;p3->left = p5;this->root = p1;
}
一、前序
前序遍历:先根后左右子树
我们通过栈来模拟递归过程:
根据栈的特点:先进先出,所以我们先然右子树进栈再让左子树进栈,这样就符合前序遍历了
代码实现:
//前序遍历 : 根 -> 左子树 -> 右子树
void Tree::Preamble()
{//利用栈实现stack<Node*> sta;//判断是否为空if (this->root == NULL){return;}//根先入栈sta.push(this->root);//当栈空时说明已经遍历完了while (!sta.empty()){//取栈顶元素并出栈Node* tmp = sta.top();sta.pop();cout << tmp->data << "->";//因为栈的特点:先进先出,所以先压右子树,在压左子树,这样就可以做到先左子树了if (tmp->right != NULL){sta.push(tmp->right);}if (tmp->left != NULL){sta.push(tmp->left);}}
}
运行结果:
图解:
二、中序
中序遍历:先左子树再根最后右子树
依旧用模拟栈来实现:先让左子树先出完再出根再右子树
代码实现:
//中序遍历 :先左子树,再根,最后右子树
void Tree::MediumOrder()
{//判断是否为空if (this->root == NULL){return;}//栈stack<Node*> sta;//先进根sta.push(this->root);Node* tmp = this->root;//出循环条件while (!sta.empty()&&tmp!=NULL){//左不为空就进左if (tmp->left != NULL){sta.push(tmp->left);tmp = tmp->left;}//直到左为空了,开始出栈else if (tmp->left == NULL){//取栈顶并出栈tmp = sta.top(); sta.pop();cout << tmp->data << "->";//右子树为空就说明这个子树遍历完了,可以回到上一级根了(栈顶元素),再判断其右子树是否为空while (!sta.empty()&&tmp->right == NULL){tmp = sta.top();cout << tmp->data << "->";sta.pop();}//右子树不为空进栈,并作为新的根,再往下走sta.push(tmp->right);tmp = tmp->right;}}
}
运行结果:
图解:
三、后序
后序:先左子树再右子树最后根
还是用栈来模拟,但是在树节点加了一个bool
变量来判断是否走完左子树了,判断为假的话就该走右子树了。
代码实现:
后序遍历:左子树再右子树最后根
void Tree::Postscript()
{//判断是否为空if (this->root == NULL){return;}//栈stack<Node*> sta;//先让根入栈Node* tmp = this->root;sta.push(tmp);//从根的左节点开始tmp = tmp->left;while (!sta.empty() || tmp != NULL){//不为空就继续进栈,直到为空while (tmp != NULL){sta.push(tmp);tmp = tmp->left;}//左子树为空,取栈顶元素并出栈tmp = sta.top();sta.pop();//判断为真改变为假再入栈if (tmp->ok){tmp->ok = false;sta.push(tmp);//栈顶元素为ok假了,该走右了tmp = tmp->right;}//假,将栈顶往下为假的元素都出,直到为真的再重新走else{ cout << tmp->data << "->";//遍历到根节点了if (tmp == this->root){return;}elsetmp = NULL;}}}
运行结果:
图解: