二叉树的递归与非递归

对一个树的访问,分别可以以前序访问,中序访问,后序访问,层序访问的访问的方法进行访问。
二叉树的表示方法有两种,一种是数组表示法,一种是链式存储法。用数组表示完全二叉树特别有效,但是若用数组表示一般的二叉树就会特别浪费时间,所以一般都会采用链式结构来表示.根据二叉树的定义,可以设计出二叉树的构造,一个二叉树里面应该存有树的根节点(_root),左子树(_lift),右子树(_right)这里写图片描述
二叉链表的存储表示
这里写图片描述

在这里,前序,中序,后序遍历的思想都比较简单,控制好循环条件,用递归方法直接调用就可以,层序遍历的思想是以队列先进先出的思想实现的
![这里写图片描述]
层序遍历思想图(https://img-blog.csdn.net/20170925091220618?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3luMTI2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
非递归借助栈辅助完成

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<assert.h>
#include<queue>
#include<stack>
using namespace std;
template <class T>
struct NodeBinaryTree
{
    NodeBinaryTree(const T& data=T())//定义结构体  并初始化
    :_data(data)
    , _left(NULL)
    , _right(NULL)
    {}
    NodeBinaryTree* _left;
    NodeBinaryTree* _right;
    T _data;
};
template <class T>
class BinaryTree
{
    typedef NodeBinaryTree<T> Node;
public:
    BinaryTree()//无参构造函数
        :_root(NULL)
    {}
    BinaryTree(const T* arr, int sz, const T invalid)//带有参数的构造函数
    {
        assert(arr);
        int index = 0;//代表数组的初始位置
        _root = CreatTree(arr, sz, invalid, index);
    }
    BinaryTree(const BinaryTree<int> & bt)
    {
        _root = Copy(bt._root);
    }
    BinaryTree<T> operator=(const BinaryTree<T> &bt) //赋值运算符重载
    {
        if (this != &bt)
        {
            Node* tmp = bt._root;
            delete[] bt;
            _root = tmp;
        }
        return *this;
    }
    //BinaryTree<T> operator=(const BinaryTree<T> &bt)//现代写法
    //{
    //  std::swap(_root, bt._root)
    //      return *this;
    //}
    ~BinaryTree()
    {
        if (_root)
        {
            delete[]_root;
            _root = NULL;
        }
    }
    //递归思想实现二叉树
     void PreOrder()
    {
         cout << "前序遍历";
             _PreOrder(_root);
    }
     void InOrder()
     {
         cout << "中序遍历";
             _InOrder(_root);
     }
     void EndOrder()
     {
         cout << "后序遍历";
             _EndOrder(_root);
     }
     void SeqOrder()
     {
         cout << "层序遍历";
             _SeqOrder(_root);
     }
     size_t Size()
     {
         return _Size(_root);
     }

     size_t Depth()
     {
         return _Depth(_root);
     }
     size_t LeafSize()
     {
         return _LeafSize(_root);
     }
     size_t GetKLevel_NodeSzie(int k)
     {

        return  _GetKLevel_NodeSzie(_root, k);
     }
     void Destory()
     {
         _Destory();
     }

protected:
    Node* CreatTree(const T*arr,int  sz, const T& invalid,int&  index)//前序遍历建立二叉树
    {
        assert(arr);
        if ((index <sz) && arr[index] != invalid)
        {
            Node* _root = new Node(arr[index]);
            _root->_left = CreatTree(arr, sz, invalid, ++index);
            _root->_right = CreatTree(arr, sz, invalid, ++index); 
            return _root;
        }
        return NULL;
    }
    Node* Copy(Node* _root)
    {
        Node* tmp = NULL;
        if (_root)
        {
            tmp = new Node(_root->_data);
            tmp->_left = Copy(_root->_left);
            tmp->_right = Copy(_root->_right );
            return tmp;
        }
    }
    void _PreOrder(Node* _root)
    {
        if (_root)
        {
            cout << _root->_data<<"->";
            _PreOrder(_root->_left);
            _PreOrder(_root->_right);
        }
    }
    void _InOrder(Node* _root)
    {
        if (_root)
        {
            _InOrder(_root->_left);
            cout << _root->_data << "->";
            _InOrder(_root->_right);
        }
    }
    void _EndOrder(Node* _root)
    {
        if (_root)
        {

            _EndOrder(_root->_left);
            _EndOrder(_root->_right);
            cout << _root->_data << "->";
        }
    }
    void _SeqOrder(Node* _root)//层序遍历  层序遍历是以队列的思想来实现的(画图)
    {
        queue<Node*> q;
        if (_root)
        {
            q.push(_root);
         }
        while (!q.empty())//当队列不为空时,进入循环打印
        {
            Node* tmp = q.front();
            cout << tmp->_data<<"->";
            q.pop();
            if (tmp->_left)
            {
                q.push(tmp->_left);
            }
            if (tmp -> _right)
            {
                q.push(tmp->_right);
            }

        }

    }
    size_t _Size(Node* _root)//不需要定义计数器 浪费空间  直接用递归计算
    {
        if (_root == NULL)
        {
            return 0;
        }
        if (_root)
        {
            return _Size(_root->_left) + _Size(_root->_right) + 1;
        }
    }
    size_t _Depth(Node* _root)//  左右子树高的+1依次递归
    {
        if (_root == NULL)
        {
            return 0;
        }
        if (_root)
        {
            return (_Depth(_root->_left) > _Depth(_root->_right) 
                ? _Depth(_root->_left) : _Depth(_root->_right)) + 1;
        }
    }
    size_t _LeafSize( const Node* _root)//返回二叉树中叶子节点的个数 三种情况都要分别考虑到
    {
        if (_root == NULL)
        {
            return 0;
        }
        if ((_root->_left == NULL) && (_root->_right==NULL))
        {
            return 1;
        }
        if (_root)
        {
            return _LeafSize(_root->_left) + _LeafSize(_root->_right);
        }
    }
    size_t _GetKLevel_NodeSzie( Node* _root,int k)//返回第k层节点的个数
    {
        if (_root == NULL)
        {
            return 0;
        }
        if (k==1)
        {
            return 1;
        }
        return _GetKLevel_NodeSzie(_root->_left, k - 1)
            + _GetKLevel_NodeSzie(_root->_right, k - 1);
    }

public:
    //用栈做辅助非递归实现二叉树
    void PrevOrder_NonR()
    { 
        Node* cur = _root;
        stack<Node*> s;
        while (cur || !s.empty())
        {
            while (cur)
            {
                cout << cur->_data << "->";
                s.push(cur);
                cur = cur->_left; 
            }
            Node*top= s.top();
            s.pop();
            cur = top->_right;

        }

    }
    void InOrder_NonR()//中序遍历
    {
        Node* cur = _root;
        stack<Node*> s;//在这里要定义成一个结构体 若定义成一个整型无法访问下一个节点  以便可以找到下一个节点
        while (cur || !s.empty())
        {
            while (cur)
            {
                s.push(cur);
                cur = cur->_left;
            }
            Node* top = s.top();
            cout << top->_data << "->";
            s.pop();
            cur = top->_right;
         }
    }


    void EndOrder_NonR()//后续遍历,需要定义一个指向前一个节点的指针
    {
        Node* cur = _root;
        stack<Node*> s;
        Node* prev = NULL;
        while (cur || !s.empty())
        {
            while (cur)
            {
                s.push(cur);
                cur = cur->_left;
            }
            Node* top = s.top();
            if (((top->_right) == NULL) ||( top->_right == prev))
            {
                cout << top->_data<<"->";
                s.pop();
                prev=top;
            }
            else
                cur = top->_right;
        }

    }
    void _Destory(Node* &_root)
    {
        if (_root == NULL)
        {
            return 0;
        }
        else
        {
            _Destory(_root->left);
            _Destory(_root->right);
            delete _root;
            _root = NULL;
        }

    }

 protected:
     Node* _root;
//
};
void TestBinaryTree()
{
    //int arr[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
    int arr[15] = {1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8}; 

    int sz = sizeof(arr) / sizeof(arr[0]);
    //BinaryTree<int> bt;
    BinaryTree<int> bt1(arr, sz, '#');
    //BinaryTree<int>bt2(bt1);
    //BinaryTree<int>bt = bt1;

    bt1.PreOrder();
    cout << endl;
    bt1.InOrder();
    cout << endl;
    bt1.EndOrder();
    cout << endl;
    bt1.SeqOrder();
    cout << endl;
    cout << "Size()?  " << bt1.Size() << endl;
    cout << "Depth()?  " << bt1.Depth()<<endl;
    cout << "LeafSize()?  " << bt1.LeafSize()<<endl;
    cout << "GetKLevel_NodeSzie()?  " << bt1.GetKLevel_NodeSzie(3) << endl;


    bt1.PrevOrder_NonR();
    cout << endl;
    bt1.InOrder_NonR();
    cout << endl;
    bt1.EndOrder_NonR();
    cout << endl;

}
int main()
{
    TestBinaryTree();
    system("pause");
    return 0;
}

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值