非递归遍历二叉树的实现
来源:互联网 发布:钻石皇朝流量软件 编辑:程序博客网 时间:2024/05/21 05:19
参考:http://blog.csdn.net/kofsky/article/details/2886453/
#pragma once#define NUM_NODE 8#include<iostream>#include<stack>#include<ctime>#include<assert.h>class binnode {public:int key;char value;binnode *left, *right,*parent;bool beVisited; //用于中序遍历的指针回溯版本bool bePushed; //用于中序遍历的binnode(){}binnode(int k, char v) :key(k), value(v) { left = right = parent = nullptr; beVisited = false; bePushed = false; }binnode(const binnode& bn) {key = bn.key;value = bn.value;left = right = parent = nullptr;beVisited = false;bePushed = false;}};class bintree {public:bintree();bool insert(const binnode& bn);void inorder();void postorder();void preorder();void menu();protected:void inorder(binnode * bn); //递归前序遍历void _inorder(); //非递归前序遍历void __inorder(binnode * bn);void postorder(binnode * bn);void _postorder();void preorder(binnode * bn);void _preorder();void __preorder(binnode * bn);private:void visit(binnode *bn);binnode *root;binnode *NIL;};
#include"bintree.h"bintree::bintree() {root = nullptr;NIL = nullptr;}bool bintree::insert(const binnode& bn) {binnode *tmp = root; //指向插入位置的指针binnode *parent_tmp = nullptr; //插入位置的父节点while (tmp != NIL) {parent_tmp = tmp; //先赋值父节点if (bn.key <= tmp->key) {tmp = tmp->left; //指针指向子节点}elsetmp = tmp->right;}tmp = new binnode(bn); //产生插入的节点if (tmp == nullptr) { std::cout << "allocated error!.\n"; return false; }tmp->parent = parent_tmp; //赋值子节点的父指针if (tmp->parent == NIL) { //若父节点为空,则当前插入的节点是根节点root = tmp; //赋值根节点return true;}if (tmp->key <= tmp->parent->key) { //判断插入的位置是父节点的左子女还是右子女tmp->parent->left = tmp;}elsetmp->parent->right = tmp;return true;}void bintree::visit(binnode *bn) {std::cout << bn->value << " ";/*if (bn->parent != nullptr) {std::cout << bn->value << "'s parent is " << bn->parent->value << " ";}*/}void bintree::menu() {int select;std::cout << "1.前序遍历. \t 2.中序遍历. \t 3.后序遍历. \t 4.退出\n";std::cin >> select;while (select != 1 && select != 2 && select != 3 && select != 4) {std::cout << "输入错误,请重新输入!";std::cin >> select;}switch (select){case 1:preorder(); break;case 2:inorder(); break;case 3:postorder(); break;case 4:exit(0); break;default:break;}}int main() {bintree bt;int key[NUM_NODE] = {4,2,3,1,5,6,7};char value[NUM_NODE] = {'A','B','C','D','E','F','G','\0'};binnode bn[NUM_NODE];/*创建二叉查找树*/for (int i = 0; i < NUM_NODE; ++i) {bn[i].key = key[i];bn[i].value = value[i];bn[i].left = bn[i].right = bn[i].parent = nullptr;bn[i].beVisited = false;bn[i].bePushed = false;}for (int i = 0; i < NUM_NODE; ++i) {std::cout << bn[i].value << " ";}std::cout << std::endl;for (int i = 0; i < NUM_NODE; ++i) {bt.insert(bn[i]);}/*测试遍历*/bt.menu();return 0;}
#include"bintree.h"void bintree::inorder() {int select;std::cout << "1.递归中序遍历. \t2.非递归中序遍历.\t 3.非递归中序遍历2 \t 4.返回主菜单\n";std::cin >> select;while (select != 1 && select != 2 && select != 3 && select != 4) {std::cout << "输入错误,请重新输入!" << std::endl;std::cin >> select;}switch (select) {case 1:inorder(root); std::cout << std::endl; inorder(); break;case 2:_inorder(); std::cout << std::endl; inorder(); break;case 3:__inorder(root); std::cout << std::endl; inorder(); break;case 4:menu(); break;}}void bintree::inorder(binnode * bn) { //递归中序遍历if (bn != nullptr) {inorder(bn->left);visit(bn);inorder(bn->right);}}/*// 中序遍历伪代码:非递归版本,用栈实现,版本1void InOrder1(TNode* root){ Stack S; while ( root != NULL || !S.empty() ) { while( root != NULL ) // 左子树入栈 { S.push(root); root = root->left; } if ( !S.empty() ) { root = S.pop(); Visit(root->data); // 访问根结点 root = root->right; // 通过下一次循环实现右子树遍历 } }}*/void bintree::_inorder() { //非递归中序遍历std::stack<binnode*> s;binnode *p = root;while (p != NULL || !s.empty()) //循环结束条件:当节点为空且栈为空结束循环{while (p != NULL) //遍历左子树并进栈,直到左子树为空{s.push(p);p = p->left;}if (!s.empty()) //若栈不为空则出栈,打印并进入节点的右子树{p = s.top();visit(p);s.pop();p = p->right;}}}/*// 中序遍历伪代码:非递归版本,不用栈,增加指向父节点的指针void InOrder3(TNode* root){ while ( root != NULL ) // 回溯到根节点时为NULL,退出 { while ( root->left != NULL && !root->left->bVisited ) { // 沿左子树向下搜索当前子树尚未访问的最左节点 root = root->left; } if ( !root->bVisited ) { // 访问尚未访问的最左节点 Visit(root); root->bVisited=true; } if ( root->right != NULL && !root->right->bVisited ) { // 遍历当前节点的右子树 root = root->right; } else { // 回溯至父节点 root = root->parent; } }}*/void bintree::__inorder(binnode * bn) {binnode * p = bn;while (p != nullptr) {while (p->left != nullptr && !p->left->beVisited) {p = p->left;}if (!p->beVisited) {visit(p);p->beVisited = true;}if (p->right != nullptr && !p->right->beVisited) {p = p->right;}else {p = p->parent;}}}/*// 中序遍历伪代码:非递归版本,用栈实现,版本2void InOrder2(TNode* root){ Stack S; if( root != NULL ) { S.push(root); } while ( !S.empty() ) { TNode* node = S.pop(); if ( node->bPushed ) { // 如果标识位为true,则表示其左右子树都已经入栈,那么现在就需要访问该节点了 Visit(node); } else { // 左右子树尚未入栈,则依次将 右节点,根节点,左节点 入栈 if ( node->right != NULL ) { node->right->bPushed = false; // 左右子树均设置为false S.push(node->right); } node->bPushed = true; // 根节点标志位为true S.push(node); if ( node->left != NULL ) { node->left->bPushed = false; S.push(node->left); } } }}*/
#include"bintree.h"void bintree::preorder() {int select;binnode * p = root;std::cout << "1.递归前序遍历. \t2.非递归前序遍历.\t 3.非递归遍历2. \t 4.返回主菜单\n";std::cin >> select;while (select != 1 && select != 2 && select != 3 && select != 4) {std::cout << "输入错误,请重新输入!" << std::endl;std::cin >> select;}switch (select) {case 1:preorder(p); std::cout << std::endl; preorder(); break;case 2:_preorder(); std::cout << std::endl; preorder(); break;case 3:__preorder(root); break;case 4:menu(); break;}}void bintree::preorder(binnode * bn) {if (bn == nullptr)return;std::cout << bn->value << " ";preorder(bn->left);preorder(bn->right);}void bintree::_preorder() {binnode * p = root;std::stack<binnode*> s;p = root;assert(s.empty());while (p != nullptr || !s.empty()) {if (p != nullptr) {visit(p);s.push(p);p = p->left;}else {p = s.top();s.pop();p = p->right;}}}void bintree::__preorder(binnode * bn) {binnode * p = bn;std::stack<binnode*> s;s.push(p);while (!s.empty()) {p = s.top();s.pop();if (p != nullptr) { //入栈的时候可能有空指针,只有非空指针才能进行操作visit(p);s.push(p->right);s.push(p->left);}}}/*// 先序遍历伪代码:非递归版本,用栈实现,版本1void preOrder1(TNode* root){Stack S;while ((root != NULL) || !S.empty()){if (root != NULL){Visit(root);S.push(root); // 先序就体现在这里了,先访问,再入栈root = root->left; // 依次访问左子树}else{root = S.pop(); // 回溯至父亲节点root = root->right;}}}*//*// 先序遍历伪代码:非递归版本,用栈实现,版本2void preOrder2(TNode* root){if ( root != NULL){Stack S;S.push(root);while (!S.empty()){TNode* node = S.pop();Visit(node); // 先访问根节点,然后根节点就无需入栈了S.push(node->right); // 先push的是右节点,再是左节点S.push(node->left);}}}*/
#include"bintree.h"void bintree::postorder() {int select;std::cout << "1.递归后序遍历. \t2.非递归后序遍历.\t 3.返回主菜单\n";std::cin >> select;while (select != 1 && select != 2 && select != 3) {std::cout << "输入错误,请重新输入!" << std::endl;std::cin >> select;}switch (select) {case 1:postorder(root); postorder(); break;case 2:_postorder(); postorder(); break;case 3:menu(); break;}}void bintree::postorder(binnode * bn) { //递归后序遍历if (bn != nullptr) {postorder(bn->left);postorder(bn->right);std::cout << bn->value << " ";}}/*// 后序遍历伪代码:非递归版本,用栈实现void PostOrder(TNode* root){ Stack S; if( root != NULL ) { S.push(root); } while ( !S.empty() ) { TNode* node = S.pop(); if ( node->bPushed ) { // 如果标识位为true,则表示其左右子树都已经入栈,那么现在就需要访问该节点了 Visit(node); } else { node->bPushed = true; // 根节点标志位为true S.push(node);// 左右子树尚未入栈,则依次将 右节点,左节点,根节点 入栈 if ( node->right != NULL ) { node->right->bPushed = false; // 左右子树均设置为false S.push(node->right); } if ( node->left != NULL ) { node->left->bPushed = false; S.push(node->left); } } }}*/void bintree::_postorder() {std::stack<binnode*> s;binnode *p = root;if (p != nullptr) {s.push(p);}while (!s.empty()) {p = s.top();s.pop();if (p->bePushed) {visit(p);}else {p->bePushed = true;s.push(p);if (p->right != nullptr) {s.push(p->right);p->right->bePushed = false;}if (p->left != nullptr) {s.push(p->left);p->left->bePushed = false;}}}}
总结:1)递归改写成非递归,关键是要仿照递归的遍历顺序,不论是利用栈还是利用指针回溯,最终都是依靠条件来约束非递归时的遍历顺序。
如中序遍历的指针回溯版本,先走到左子树的尽头,若左子树有右子树则进入右子树,若无右子树则回溯父节点,通过判断右子树的有无改变遍历的顺 序,使遍历的顺序跟递归调用的遍历顺序一样。
2)找准算法的出口,明确算法结束的判断条件。
0 0
- 非递归实现二叉树的遍历
- 非递归实现二叉树的遍历
- 二叉树遍历的非递归实现
- 二叉树遍历的非递归实现
- 二叉树遍历的非递归实现
- 二叉树的非递归遍历实现
- 二叉树遍历的非递归实现
- 非递归实现二叉树的遍历
- 二叉树遍历的非递归实现
- 二叉树遍历的非递归实现
- 非递归遍历二叉树的实现
- 二叉树遍历的非递归实现
- 二叉树遍历的非递归实现
- 二叉树的遍历(递归实现+非递归实现)
- 二叉树的各种遍历的递归非递归实现。
- 递归、非递归实现二叉树的前中后序遍历
- Java实现二叉树的递归与非递归遍历
- 二叉树的遍历:递归和非递归实现
- python判断变量类型
- [LeetCode]66. Plus One
- SElinux整理
- 使用html表格布局做一个企业邮箱登录界面
- AngularJS解决第一次加载闪烁问题
- 非递归遍历二叉树的实现
- 【leetcode】258. Add Digits
- Bugs及解决方案
- 。。。
- 二叉树 的模板实现
- 视图渲染、CPU和GPU卡顿原因及其优化方案
- C++的可移植性和跨平台开发
- javaweb-html基础标签01
- android开发--searchView