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


    
    
    ///////////////////头文件: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 }
  • 相关阅读:
    A breakdown pie chart ReportLab Snippets (Beta)
    彩程轶事 | 彩程团队BLOG
    Proxy server
    VIM Quick Reference Card
    Search for visually selected text
    httpstats: HTTP/1.1 Connection header field
    Get File Name from File Path in Python | Code Comments
    vim 控小结
    Django Admin Bootstrap theme
    Mike McCreavy’s Resume: Silicon Valley Software Engineer, Developer, Architect | mccreavy
  • 原文地址:https://www.cnblogs.com/ljy2013/p/3825058.html
Copyright © 2020-2023  润新知