二叉树的三种遍历方式的循环和递归的实现方式



///////////////////头文件:BST.h////////////////////////

#ifndef BST_H
#define BST_H
#include "StdAfx.h"
#include<iostream>
#include<stack>
template<typename DataType>
class BST
{
public:
    class Node
    {
    public:
        Node(int data=0):m_data(data),m_left(NULL),m_right(NULL)
        {}
    public:
        int m_data;
        Node* m_left;
        Node* m_right;
    };
    typedef Node* NodePointer;
public:
    BST();

    bool empty() const;
    void insert(const DataType& item);

    void preordertrav(NodePointer root);//前序遍历(循环)
    void preordertravRec(NodePointer root);//前序遍历(递归)

    void midordertrav(NodePointer root);//中序遍历(循环)
    void midordertravRec(NodePointer root);//中序遍历(递归)

    void postordertrav(NodePointer root);//后序遍历(循环)
    void postordertravRec(NodePointer root);//后序遍历(递归)

    void static visit(Node* p);//输出相应的节点
public:
    Node* myroot;//根节点
};

template<typename DataType>
inline BST<DataType>::BST():myroot(NULL)
{}

template<typename DataType>
inline bool BST<DataType>::empty() const
{
    return myroot==NULL;
}

#endif

 1 #include "StdAfx.h"
  2 #include"BST.h"
  3 #include<iostream>
  4 #include<stack>
  5 using namespace std;
  6 //通过insert建树
  7 template<typename DataType>
  8 void BST<DataType>::insert(const DataType& item)
  9 {
 10     BST<DataType>::NodePointer locptr=myroot,//记录可以插入的位置,从根节点开始
 11         parent=NULL;//记录可以插入的位置的根节点
 12     bool found=false;//表明item是否已经在BST中
 13     while(!found&&locptr!=NULL)//查找可以插入的位置
 14     {//在这里找到可以插入的位置是可插入的父节点,在这个父节点上插入
 15         parent=locptr;
 16         if(item<locptr->m_data)//比根节点小
 17             locptr=locptr->m_left;//往左边继续找
 18         else if(locptr->m_data<item)//比根节点大
 19             locptr=locptr->m_right;//往右边继续找
 20         else
 21             found=true;
 22     }
 23     if(!found)//执行插入操作
 24     {
 25         locptr=new BST<DataType>::Node(item);//创建新节点
 26         if(parent==NULL)//如果该开始是空树,则第一个插入的就是根节点
 27             myroot=locptr;
 28         else if(item<parent->m_data)
 29             parent->m_left=locptr;
 30         else
 31             parent->m_right=locptr;
 32     }
 33     else
 34         cout<<"Item already in the tree";
 35 }
 36 //前序遍历,循环实现(中左右)
 37 template<typename DataType>
 38 void BST<DataType>::preordertrav(NodePointer root)
 39 {
 40     if(root==NULL)
 41         return ;
 42     stack<BST<DataType>::NodePointer>ss;//用来存放遍历的节点,注意这里的节点的类型
 43     Node* curr=root;
 44     while(!ss.empty()||curr!=NULL)
 45     {
 46         while(curr!=NULL)
 47         {
 48             visit(curr);//第一个访问根节点
 49             ss.push(curr);//保存根节点
 50             curr=curr->m_left;//然后是左节点
 51         }
 52         Node* p=ss.top();//最左边的左节点
 53         ss.pop();//删除,因为它已经遍历了
 54         curr=p->m_right;//但是删除之后还必须考察它的右节点是否存在
 55     }
 56 }
 57 //前序遍历,递归实现
 58 template<typename DataType>
 59 void BST<DataType>::preordertravRec(NodePointer root)
 60 {
 61     if(root==NULL)
 62     {
 63         //cout<<"错误的输入!"<<endl;
 64         return ;
 65     }
 66     visit(root);//访问根节点
 67     preordertravRec(root->m_left);
 68     preordertravRec(root->m_right);
 69 }
 70
 71 //中序遍历,循环方式实现
 72 template<typename DataType>
 73 void BST<DataType>::midordertrav(NodePointer root)
 74 {
 75     if(NULL==root)
 76         return;
 77     stack<BST<DataType>::NodePointer>ss;//定义一个栈来存储遍历的路径
 78     BST<DataType>::NodePointer curr=root;//定义一个当前的节点来作为临时变量
 79     while(!ss.empty()||curr!=NULL)
 80     {
 81         while(curr!=NULL)//先遍历左子树
 82         {
 83             ss.push(curr);//压栈
 84             curr=curr->m_left;
 85         }
 86         //此时最左边的路径已经遍历完了,现在开始返回,记住:也要把最左边的叶子节点当作根节点来看待
 87         BST<DataType>::NodePointer p=ss.top();//取出最左边的节点
 88         visit(p);//如果该节点没有左节点就输出该节点
 89         ss.pop();//删除该节点,因为他已经遍历了。
 90         curr=p->m_right;//由于该节点没有左节点,但是不知道右节点是否存在,因此需要仅需判断右节点
 91     }
 92 }
 93 //中序遍历,递归实现
 94 template<typename DataType>
 95 void BST<DataType>::midordertravRec(NodePointer root)
 96 {
 97     if(root==NULL)
 98     {
 99         //cout<<"错误的输入!"<<endl;
100         return ;
101     }
102     midordertravRec(root->m_left);
103     visit(root);
104     midordertravRec(root->m_right);
105
106 }
107
108 //后序遍历,循环实现
109 template<typename DataType>
110 void BST<DataType>::postordertrav(NodePointer root)
111 {
112     if(root==NULL)
113         return ;
114     stack<NodePointer>ss;
115     BST<DataType>::NodePointer curr=root;//定义一个当前的节点来作为临时变量
116     BST<DataType>::NodePointer last=NULL;//定义一个节点来表示之前访问的节点
117     while(curr!=NULL||!ss.empty())
118     {
119
120         while(curr!=NULL)
121         {
122             ss.push(curr);//压栈
123             curr=curr->m_left;
124         }
125         curr=ss.top();//最左边的节点
126
127         //其访问方式是:左节点——>根节点(这时并不访问)——>右节点——>根节点(这时才访问)
128         //这个访问节点的状态转换都是通过判断当前节点的右节点是否存在来实现转换。
129
130         //如果当前节点的右节点已经访问过或者没有右节点
131         if(curr->m_right==NULL||last==curr->m_right)
132         {
133             visit(curr);//访问当前节点
134             last=curr;//记录上次访问过的节点
135             ss.pop();//删除左节点
136             curr=NULL;//下次访问根节点
137
138         }
139         else
140         {
141             //否则将右节点压栈
142             curr=curr->m_right;
143         }
144     }
145 }
146 //后序遍历,递归实现
147 template<typename DataType>
148 void BST<DataType>::postordertravRec(NodePointer root)
149 {
150     if(root==NULL)
151         return ;
152     postordertravRec(root->m_left);
153     postordertravRec(root->m_right);
154     visit(root);
155 }
156
157 template<typename DataType>
158 void BST<DataType>::visit(Node* p)
159 {
160     if(p==NULL)
161         return ;
162     cout<<p->m_data<<" ";
163 }

////////////测试代码////////////////////
 1 // MidOrderTrav.cpp : 定义控制台应用程序的入口点。
  2 //二叉树的中序遍历
  3
  4 #include "stdafx.h"
  5 #include<iostream>
  6
  7 //#include"BST.h"
  8 #include"BST2.cpp"
  9
 10 using namespace std;
 11
 12 //template<typename DataType>
 13 void ad(BST<int>::Node* root)
 14 {
 15     if(root==NULL)
 16         return ;
 17     stack<BST<int>::NodePointer>ss;
 18     BST<int>::NodePointer curr=root;//定义一个当前的节点来作为临时变量
 19     BST<int>::NodePointer last=NULL;//定义一个节点来表示之前访问的节点
 20     while(curr!=NULL||!ss.empty())
 21     {
 22
 23         while(curr!=NULL)
 24         {
 25             ss.push(curr);//压栈
 26             curr=curr->m_left;
 27         }
 28         curr=ss.top();//最左边的节点
 29
 30         //其访问方式是:左节点——>根节点(这时并不访问)——>右节点——>根节点(这时才访问)
 31         //这个访问节点的状态转换都是通过判断当前节点的右节点是否存在来实现转换。
 32
 33         //如果当前节点的右节点已经访问过或者没有右节点
 34         if(curr->m_right==NULL||last==curr->m_right)
 35         {
 36             BST<int>::visit(curr);//访问当前节点
 37             last=curr;//记录上次访问过的节点
 38             ss.pop();//删除左节点
 39             curr=NULL;//下次访问根节点,并判断右节点
 40         }
 41         else
 42         {
 43             //否则将右节点压栈
 44             curr=curr->m_right;
 45         }
 46     }
 47 }
 48
 49 //2、题目:求二叉树的深度,利用遍历的方式,每一次遍历一个节点之后,等于它左右子树较大的深度加1
 50 int TreeDepth(BST<int>::Node* pRoot)
 51 {
 52     if(pRoot==NULL)
 53         return 0;
 54     int left=TreeDepth(pRoot->m_left);
 55     int right=TreeDepth(pRoot->m_right);
 56
 57     return left>right?left+1:right+1;
 58 }
 59 //3、判断是否是平衡二叉树
 60 bool IsBalance(BST<int>::Node* pRoot)
 61 {
 62     //如果一个二叉树的每一个节点的左右子树的深度差小于等于1就是平衡树
 63     //因此,我们可以求出根节点的左右子树的深度
 64     if(pRoot==NULL)
 65         return false;
 66     int left=TreeDepth(pRoot->m_left);//求出左子树的深度
 67     int right=TreeDepth(pRoot->m_right);//求出右子树的深度
 68     if(left-right<=1&&left-right>=-1)//左右子树的深度差
 69         return true;
 70     return false;
 71 }
 72
 73
 74
 75 int main()
 76 {
 77     cout<<"请输入一组数:"<<endl;
 78     int a;
 79     BST<int>bst;
 80     while(cin>>a)
 81     {
 82         bst.insert(a);
 83     }
 84
 85     cout<<"前序遍历(循环):"<<endl;
 86     bst.preordertrav(bst.myroot);//前序遍历(循环)
 87     cout<<endl;
 88     cout<<"前序遍历(递归):"<<endl;
 89     bst.preordertravRec(bst.myroot);//前序遍历(递归)
 90     cout<<endl;
 91     cout<<"中序遍历(循环):"<<endl;
 92     bst.midordertrav(bst.myroot);//中序遍历(循环)
 93     cout<<endl;
 94     cout<<"中序遍历(递归):"<<endl;
 95     bst.midordertravRec(bst.myroot);//中序遍历(递归)
 96     cout<<endl;
 97     cout<<"后序遍历(循环):"<<endl;
 98     //ad(bst.myroot);
 99     bst.postordertrav(bst.myroot);//后序遍历(循环)
100     cout<<endl;
101     cout<<"后序遍历(递归):"<<endl;
102     bst.postordertravRec(bst.myroot);
103     cout<<endl;
104
105
106     cout<<"求二叉树的深度h:"<<endl;
107     cout<<TreeDepth(bst.myroot)<<endl;
108
109
110     cout<<"判断一颗二叉树是否是平衡树:"<<endl;
111     if(IsBalance(bst.myroot))
112         cout<<"这棵树是平衡二叉树"<<endl;
113     else
114         cout<<"这棵树不是平衡二叉树"<<endl;
115
116
117     return 0;
118 }

二叉树的三种遍历方式的循环和递归的实现方式

时间: 2024-12-26 17:32:48

二叉树的三种遍历方式的循环和递归的实现方式的相关文章

公交车站捡垃圾之二叉树的三种遍历方法

# 二叉树的遍历 今天下午看了二叉树的三种遍历方式,虽然能写出代码,但是理解可能不太到位,感觉很容易忘,所以想到一个形象的方法,把每个节点当作公交车站,而访问节点则是在这个公交车站捡垃圾,右子树和左子树则表示岔路.然后这个捡垃圾的人钟爱左边这个方向,所以一直以左优先.甲乙丙三个人,都爱捡垃圾,但是思考方式不同,所以捡垃圾的方法有点不同. 先序遍历 先序遍历最简单,秉承的原则是,甲很小心谨慎,每次经过公交车站,怕别人捡了,都把垃圾先捡到手,直到左边的路走完了,再往回走,但是回来的过程中,在公交车站

二叉树的三种遍历简单版

同学突然向我问二叉树的三种遍历代码.数据结构刚刚学了,自己很吃力的敲了出来. 和老师演示的代码有很大差距. #include <stdio.h>#include <string.h>#include <stdlib.h> #define Error -1#define Right 1 struct BiTnode{    char data;    struct BiTnode *LChild;    struct BiTnode *RChild; }; BiTnode

PTA 二叉树的三种遍历(先序、中序和后序)

6-5 二叉树的三种遍历(先序.中序和后序) (6 分) 本题要求实现给定的二叉树的三种遍历. 函数接口定义: void Preorder(BiTree T); void Inorder(BiTree T); void Postorder(BiTree T); T是二叉树树根指针,Preorder.Inorder和Postorder分别输出给定二叉树的先序.中序和后序遍历序列,格式为一个空格跟着一个字符. 其中BinTree结构定义如下: typedef char ElemType; typed

POJ2255 TreeRecovery(二叉树的三种遍历)

Description Little Valentine liked playing with binary trees very much. Her favorite game was constructing randomly looking binary trees with capital letters in the nodes. This is an example of one of her creations: D / \ B E / \ \ A C G / F To recor

二叉树的三种遍历的应用(表达式,求深度,叶子数,结点数,二叉树的建立,复制)

表达式的表示 如图所示的二叉树表达式: a+b*(c-d)-e/f 若先序遍历此二叉树,按访问结点的先后次序将结点排列起来,其先序序列为: (波兰式,前缀表达式)  -+a*b-cd/ef 按中序遍历,其中序序列为:a+b*c-d-e/f (中缀表达式) 按后序遍历,其后序序列为:abcd-*+ef/- (逆波兰式,后缀表达式) 注:人喜欢中缀形式的算术表达式,对于计算机,使用后缀易于求值 查询二叉树中某个结点 使用先序遍历算法进行查询遍历 // 若二叉树中存在和 x 相同的元素,则 p 指向该

二叉树的三种遍历(非递归)

先定义二叉树: /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ 二叉树的先序遍历(以LeetCode 144.为例): class Solution { public: vector<int> preo

二叉树的三种遍历(前序,中序,后序)

参考<大话数据结构>P178~184——二叉树的遍历. 用书上的这个二叉树: 代码和解释如下(VS2012测试通过): 1 #include <iostream> 2 using namespace std; 3 4 //二叉树的二叉链表结点结构定义 5 typedef struct BiTNode 6 { 7 char data; 8 struct BiTNode *lchild,*rchild; 9 }BiTNode; 10 11 //输入前序遍历,创建二叉树 12 //这里输

折半查找/二分查找 以及二叉树的 三种遍历方式

二分查找   线性查找 1.二分查找 public class BinarySearch { /** * 二分查找 * @param data * @return */ public int binarySearch(long[] data,long n) { //左右 端点 int left =0; int right =data.length-1; //中间元素 int mid=-1; while(left<right){ // 有两种情况 1.left = right 2. left>r

二叉树的三种遍历方式

PS: 此算法参考资料<数据结构与算法JavaScript描述> 1 //------------------------------------------------------------------ 2 //-----------------performance binary tree--------------------- 3 //------------------------------------------------------------------ 4 functi