二叉树的非递归遍历——前序、中序、后序、层序、层序按行输出
一、自己总结归纳的
二叉树的非递归遍历——前序、中序、后序、层序、层序按行输出
层序和前序的程序代码特别像,只有两点差别:
1、只是层序用到queue,前序用的stack
2、前序先push了右孩子,再push左孩子
层序先push了左孩子,再push右孩子
//层序遍历
void LevelOrder(BinaryTreeNode *T)
{
if (T == NULL) return;
queue<BinaryTreeNode *> Q;
Q.push(T);//入队根指针
while (!Q.empty()){
BinaryTreeNode *cur = Q.front();
Q.pop();
cout << cur->data << " ";
if (cur->lchild) Q.push(cur->lchild);
if (cur->rchild) Q.push(cur->rchild);
}
cout << endl;
}
//前序遍历函数
void PreOrder(BinaryTreeNode *root)
{
if (!root)return;
stack<BinaryTreeNode *> S;
S.push(root);
while (!S.empty()){
BinaryTreeNode* p = S.top();
S.pop();
cout << p->data << " ";
if (p->rchild)S.push(p->rchild);
if (p->lchild)S.push(p->lchild);
}
cout << endl;
}
//中序遍历
void inOrder(BinaryTreeNode *root){
if (!root)return;
stack<BinaryTreeNode *> S;
while (!S.empty() || root){
if (root){
S.push(root);
root = root->lchild;
}
else{
root = S.top();
S.pop();
cout << root->data << " ";
root = root->rchild;
}
}
cout << endl;
}
//后序遍历
void postOrder(BinaryTreeNode *root){
if (!root)return;
stack<BinaryTreeNode *>S;
BinaryTreeNode *pre = NULL, *cur = NULL;
S.push(root);
while (!S.empty()){
cur = S.top();
if ((!cur->lchild && !cur->rchild) || (pre && (pre == cur->lchild || pre == cur->rchild))){
S.pop();
cout << cur->data << " ";
pre = cur;
}
else{
if (cur->rchild)S.push(cur->rchild);
if (cur->lchild)S.push(cur->lchild);
}
}
cout << endl;
}
//层序遍历--按行输出
void LevelOrderByRow(BinaryTreeNode *root)
{
if (!root) return;
queue<BinaryTreeNode *> Q;
Q.push(root);//入队根指针
while (!Q.empty()){
int count_row = Q.size();
for (int i = 0; i < count_row; ++i){
BinaryTreeNode *cur = Q.front();
Q.pop();
cout << cur->data << " ";
if (cur->lchild) Q.push(cur->lchild);
if (cur->rchild) Q.push(cur->rchild);
}
cout << endl;
}
cout << endl;
}
二、来自于昨夜的秋天**的二叉树的非递归遍历——前序、中序、后序
三种遍历的代码总体结构都是完全一样的,只是cout的时机有所不同。
都需要用一个stack来模拟递归时的函数调用。
对于三种遍历,我们都使用push当前节点->push左子树->pop左子树->push右子树->pop右子树的方式。
对于前序遍历来说,每次访问到一个节点就cout;
对于中序遍历来说,每次将右子节点进栈时,把当前节点cout;
对于后序遍历来说,每次pop的时候cout。
另外我们还需要一个last_pop指针来存放上一个pop出去的节点。
如果当前节点的左右节点都不是上一个pop的节点,那么我们将左子节点入栈;
如果当前节点的左节点是上一个pop的节点,但右节点不是,那么就把右子节点入栈;
否则的话,就需要让当前节点出栈。
void preorder_traversal_iteratively(BinaryTreeNode* root){
if (root == 0) return;
stack<BinaryTreeNode*> s;
s.push(root);
cout << root->data << ' '; // visit root
BinaryTreeNode* last_pop = root;
while (!s.empty()){
BinaryTreeNode* top = s.top();
if (top->lchild != NULL && top->lchild != last_pop && top->rchild != last_pop){ // push_lchild
s.push(top->lchild);
cout << top->lchild->data << ' '; // visit top->lchild
}
else if (top->rchild != NULL && top->rchild != last_pop && (top->lchild == 0 || top->lchild == last_pop)){ // push_rchild
s.push(top->rchild);
cout << top->rchild->data << ' '; // visit top->rchild
}
else{ // pop
s.pop();
last_pop = top;
}
}
cout << endl;
}
void inorder_traversal_iteratively(BinaryTreeNode* root){
if (root == 0) return;
stack<BinaryTreeNode*> s;
s.push(root);
BinaryTreeNode* last_pop = root;
while (!s.empty()){
BinaryTreeNode* top = s.top();
if (top->lchild != 0 && top->lchild != last_pop && top->rchild != last_pop){ // push_lchild
s.push(top->lchild);
}
else if (top->rchild != 0 && top->rchild != last_pop && (top->lchild == 0 || top->lchild == last_pop)){ // push_rchild
s.push(top->rchild);
cout << top->data << ' '; // visit top
}
else{ // pop
s.pop();
last_pop = top;
if (top->rchild == 0)
cout << top->data << ' '; // visit top
}
}
cout << endl;
}
void postorder_traversal_iteratively(BinaryTreeNode* root){
if (root == 0)return;
stack<BinaryTreeNode*> s;
s.push(root);
BinaryTreeNode* last_pop = root;
while (!s.empty()){
BinaryTreeNode* top = s.top();
if (top->lchild != 0 && top->lchild != last_pop && top->rchild != last_pop){ // push_lchild
s.push(top->lchild);
}
else if (top->rchild != 0 && top->rchild != last_pop && (top->lchild == 0 || top->lchild == last_pop)){ // push_rchild
s.push(top->rchild);
}
else{ // pop
s.pop();
last_pop = top;
cout << top->data << ' '; // visit top
}
}
cout << endl;
}
实验的二叉树:
1
/ \
2 3
/ \ \
4 5 6
/ \
7 8
实验代码:
其中的 ConstructBinaryTree()函数来自于我的另一篇博客C++ 使用数组建立二叉树 层序数组(方法二)
void test2(){
cout << "by me" << endl;
BinaryTreeNode *t;
int data[] = { 1, 2, 3, 4, 5, '#', 6, '#', '#', 7, 8 };
//前序遍历:1 2 4 5 7 8 3 6
t = ConstructBinaryTree(data, sizeof(data) / sizeof(data[0]), 0);
cout << "前序: ";
PreOrder(t);
cout << "中序: ";
inOrder(t);
cout << "后序: ";
postOrder(t);
cout << "层序: ";
LevelOrder(t);
cout << "层序--按行输出:" << endl;
LevelOrderByRow(t);
}
void test3(){
cout << "by 昨夜的秋天" << endl;
BinaryTreeNode *t;
int data[] = { 1, 2, 3, 4, 5, '#', 6, '#', '#', 7, 8 };
//前序遍历:1 2 4 5 7 8 3 6
t = ConstructBinaryTree(data, sizeof(data) / sizeof(data[0]), 0);
cout << "前序: ";
preorder_traversal_iteratively(t);
cout << "中序: ";
inorder_traversal_iteratively(t);
cout << "后序: ";
postorder_traversal_iteratively(t);
}
int main()
{
test2();
test3();
cout << endl;
return 0;
}