二叉树的递归和非递归

二叉树的几种遍历算法

1.二叉树的前序遍历
2.二叉树的中序遍历
3.二叉树的后序遍历
4 .二叉树的后序遍历

一. 二叉树的前序遍历
前序遍历算法是判断节点是否为空,如果不为空,先访问根节点,再访问左子树,最后访问右子树;
前序的递归: 根->左子树(为空)->右子树。对于每一个子树又可以用同样的访问顺序来遍历。

void PrevOrder()
    {
        _PrevOrder(_root);
        cout << endl;
    }

具体实现:

void _PrevOrder(Node *root)
    {
        Node *cur = root;
        if (cur == NULL)
        {
            return ;
        }
        cout << cur->_data << " ";
        _PrevOrder(cur->_left);
        _PrevOrder(cur->_right);
    }

前序的非递归算法
对于任意节点cur:
1:判断根节点是否为空,空则返回
2:根节点不为空,输出节点,将根节点入栈,再看cur的左子树是否为空。
3:若cur的左子树不为空,将cur左子树置为当前节点,重复3操作。
4:若cur的左子树为空,将栈顶节点出栈,但不输出,将右子树的节点置为当前节点,看右子树是否为空。
5:不为空重复3操作
6:为空重复4操作
7:直到当前节点为NULL,且栈为空,则遍历结束。
前序

void PrevOrder_NotR()
    {
        cout << "前序非递归" << endl;
        return _PrevOrder_NotR(_root);
        cout << endl;
    }
`void _PrevOrder_NotR(Node *root)
{
if (root == NULL)//空树
{
return;
}
Node*cur = root;
stack<Node*> s;
while ( !s.empty()||cur!= NULL)
{
//边遍历边将节点压栈
while(cur)
{
cout << cur->_data << " ";
s.push(cur);//根节点入栈
cur = cur->_left;
}
//说明此时左子树已经遍历完了,要遍历要遍历右子树
if (!s.empty())
{
cur = s.top();//取栈顶元素
s.pop();//出栈
cur = cur->_right;
}
}
cout << endl;
}

二:二叉树的中序遍历****
二叉树的中序遍历算法:先访问左子树,再访问根节点,最后访问右子树。
中序:

void InOrder()
{
_InOrder(_root);
cout << endl;
}

实现:

void _InOrder(Node *root)
    {
        Node *cur = root;
        if (cur == NULL)
        {
            return;
        }
        _InOrder(cur->_left);
        cout << cur->_data << " ";
        _InOrder(cur->_right);
    }

中序的非递归算法:
对于任意节点cur:
1:cur是否为空若为空返回。
2:cur不为空,判断cur的左子树是否为空,若不为空,将cur入栈,将cur的左子树置为当前节点。并对当前节点进行相同操作。
3:cur的左子树为空,输出cur,并将cur的右子树当前节点,看是否为空。
4:不为空重复2和3操作。
5:为空,则执行出栈操作,输出栈顶结点,并将右孩子置为当前节点,看是否为空重复3和4操作。
6:直到当前节点P为NULL并且栈为空,则遍历结束
非递归的实现:

void _InOrder_NotR(Node*root)
    {
        Node*cur = root;
        if (cur == NULL)
        {
            return;
        }
        stack<Node *> s;
        while (cur!= NULL||!s.empty())
        {
            //一直遍历到左子树的最下面
            while (cur)
            {
                s.push(cur);
                cur = cur->_left;
            }
            //说明左子树已经遍历完了;这时需要出栈
            if (!s.empty())
            {
                cur = s.top();
                s.pop();
                cout << cur->_data << " ";
                //遍历右子树
                cur = cur->_right;
            }
        }
        cout << endl;
    }

三:二叉树的后序遍历:
后序遍历算法:根节点->右子树->左子树
后序的递归:

void PosOrder()
    {
        _PosOrder(_root);
        cout << endl;
    }

实现:

void _PosOrder(Node *root)
    {
        Node *cur = root;
        if (cur == NULL)
        {
            return;
        }
        _PosOrder(cur->_right);
        cout << cur->_data << " ";
        _PosOrder(cur->_left);
    }

后序的非递归算法:
对于任意节点cur:
1:cur是否为空若为空返回。
2:cur不为空,判断cur的右子树是否为空,若不为空,将cur入栈,将cur的右子树置为当前节点。并对当前节点进行相同操作。
3:cur的右子树为空,输出cur,并将cur的左子树当前节点,看是否为空。
4:不为空重复2和3操作。
5:为空,则执行出栈操作,输出栈顶结点,并将左孩子置为当前节点,看是否为空重复3和4操作。
6:直到当前节点P为NULL并且栈为空,则遍历结束
非递归的实现:

//后序非递归
    void _PosOrder_NotR(Node*root)
    {
        Node*cur = root;
        if (cur == NULL)//空树
        {
            return;
        }
        stack<Node*>s;
        while (!s.empty() || cur!=NULL)
        {
            //一直遍历右子树的最下面,边遍历边将节点压栈
            while (cur)
            {
                s.push(cur);
                cur=cur->_right;
            }
            if (!s.empty())
            {
                //右子树已经遍历完了,
                cur = s.top();
                s.pop();
                cout << cur->_data << " ";
                //遍历左子树
                cur = cur->_left;
            }
        }
        cout << endl;
    }

四:二叉树的层序遍历:
我们可以利用队的先进先出的性质,具体实现是,先遍历当前层,入队,然后遍历下一层。置到结束:
实现:

void _LevelOeder(Node *root)
    {
        queue<Node *> q;
        if (root == NULL)
        {
            return;
        }
        if (root)
        {
            q.push(root);//把根节点入队
        }
        while (!q.empty())
        {
            Node*front = q.front();
            cout << front->_data << " ";
            q.pop();

            if (front->_left)
                q.push(front->_left);//左子树入队
            if (front->_right)
                q.push(front->_right);//右子树入队
        }
        cout << endl;
    }

五:实现及其测试函数:
.h文件

#pragma once
#include<queue>
#include<stack>
#include<assert.h>
using namespace std;
template<class T>
struct BinaryTreeNode
{
    T _data;//数据
    BinaryTreeNode<T>* _left;//左节点
    BinaryTreeNode<T>* _right;//右节点

    BinaryTreeNode(const T&x =T())
        :_data(x)
        , _left(NULL)
        , _right(NULL)
    {}
};
template<class T>
class BinaryTree
{
    typedef BinaryTreeNode<T>  Node;
public:
    BinaryTree()
        :_root(NULL)
    {}
    BinaryTree(const BinaryTree<T> &t)
    {
        _root = _copy(t._root);
    }
    BinaryTree<T>&operator = (BinaryTree<T> &t)
    {
        //BinaryTree<T> tmp(t._root);
        swap(_root, t._root);
        return *this;
    }
    ~BinaryTree()
    {
        _Destroy(_root);
    }
    BinaryTree(const T*a, size_t n, const T&invalued = T())
    {
        size_t indes = 0;
        _root = _CreatTree(a, n, indes, invalued);//创建一个二叉树
    }
    //数节点的个数
    size_t Size()
    {
        return _Size(_root);
    }
    //深度
    size_t Depth()
    {
        return _Depth(_root);
    }
    //叶子节点的个数
    size_t LeftSize()
    {
        return _LeftSize(_root);
    }
    //获取k的节点
    int GetkLevel(Node *root, int k)
    {
        if (root == NULL||k<1)
        {
            return 0;
        }
        if (k == 1)
        {
            return 1;
        }
        int leftGetkLevel = GetkLevel(root->_left, k - 1);
        int rightGetkLevel = GetkLevel(root->_right, k - 1);
        return (leftGetkLevel + rightGetkLevel);
    }
    //前序
    void PrevOrder()
    {
        _PrevOrder(_root);
        cout << endl;
    }
    //前序非递归
    void PrevOrder_NotR()
    {
        cout << "前序非递归" << endl;
        return _PrevOrder_NotR(_root);
        cout << endl;
    }
    //中序
    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }
    //中序非递归
    void InOrder_NotR()
    {
        cout << "中序非递归" << endl;
        return _InOrder_NotR(_root);
        cout << endl;
    }
    //后序
    void PosOrder()
    {
        _PosOrder(_root);
        cout << endl;
    }
    //后序非递归
    void PosOrder_NotR()
    {
        cout << "后序非递归" << endl;
        return _PosOrder_NotR(_root);
        cout << endl;
    }
    //层序
    void LevelOrder()
    {
        _LevelOeder(_root);
        cout << endl;
    }

protected:
    Node*_CreatTree(const T*a, size_t n, size_t &indes, const T&invalued)
     {
        assert(a);
        Node* root = NULL;

        if (indes<n && a[indes] != invalued)
        {
            root = new Node(a[indes]);//创建根节点
            root->_left = _CreatTree(a, n,++indes,invalued);
            root->_right= _CreatTree(a, n,++indes,invalued);
        }
        return root;
    }
    //拷贝
    Node *_copy(Node *node)
    {
        Node*cur = node;
        Node root = NULL;//
        if (cur)
        {
            root = new Node(cur->_data);//创建新节点
            root->_left = _copy(cur->_left);//递归调用
            root->_right = _copy(cur->_right);//递归调用
        }
        return root;
    }
    //删除
    void _Destroy(Node *node)
    {
        Node* del = node;
        if (del)
        {
            _Destroy(del->_left);
            _Destroy(del->_right);
            delete del;
            del = NULL;
        }
    }
    //树节点的个数
    size_t _Size(Node *root)
    {
        if (root == NULL)
        {
            return 0;
        }
        return _Size(root->_left) + _Size(root->_right) + 1;
    }
    //深度
    size_t _Depth(Node *root)
    {
        Node *cur = root;
        if (cur == NULL)
        {
            return 0;
        }
        //比较左子树和右子树的大小
        return 1 + (_Depth(cur->_left) > _Depth(cur->_right) 
            ? _Depth(cur->_left) : _Depth(cur->_right));
    }
    //叶子节点的个数
    size_t _LeftSize(Node *root)
    {
        Node*cur = root;
        if (NULL == cur)//空树
        {
            return 0;
        }
        if (cur->_left == NULL&&cur->_right == NULL)//只有根节点
        {
            return 1;
        }
        return _LeftSize(cur->_left)+_LeftSize(cur->_right);//左子树与右子树的和
    }
    //前序
    void _PrevOrder(Node *root)
    {
        Node *cur = root;
        if (cur == NULL)
        {
            return ;
        }
        cout << cur->_data << " ";
        _PrevOrder(cur->_left);
        _PrevOrder(cur->_right);
    }
    //前序非递归
    void _PrevOrder_NotR(Node *root)
    {
        if (root == NULL)//空树
        {
            return;
        }
        Node*cur = root;
        stack<Node*> s;
        while ( !s.empty()||cur!= NULL)
        {
            //边遍历边将节点压栈
            while(cur)
            {
                cout << cur->_data << " ";
                s.push(cur);//根节点入栈
                cur = cur->_left;
            }
            //说明此时左子树已经遍历完了,要遍历要遍历右子树
            if (!s.empty())
            {
                cur = s.top();//取栈顶元素
                s.pop();//出栈
                cur = cur->_right;
            }
        }
        cout << endl;
    }
    //中序
    void _InOrder(Node *root)
    {
        Node *cur = root;
        if (cur == NULL)
        {
            return;
        }
        _InOrder(cur->_left);
        cout << cur->_data << " ";
        _InOrder(cur->_right);
    }
    //中序非递归
    void _InOrder_NotR(Node*root)
    {
        Node*cur = root;
        if (cur == NULL)
        {
            return;
        }
        stack<Node *> s;
        while (cur!= NULL||!s.empty())
        {
            //一直遍历到左子树的最下面
            while (cur)
            {
                s.push(cur);
                cur = cur->_left;
            }
            //说明左子树已经遍历完了;这时需要出栈
            if (!s.empty())
            {
                cur = s.top();
                s.pop();
                cout << cur->_data << " ";
                //遍历右子树
                cur = cur->_right;
            }
        }
        cout << endl;
    }
    //后序
    void _PosOrder(Node *root)
    {
        Node *cur = root;
        if (cur == NULL)
        {
            return;
        }
        _PosOrder(cur->_right);
        cout << cur->_data << " ";
        _PosOrder(cur->_left);
    }
    //后序非递归
    void _PosOrder_NotR(Node*root)
    {
        Node*cur = root;
        if (cur == NULL)//空树
        {
            return;
        }
        stack<Node*>s;
        while (!s.empty() || cur!=NULL)
        {
            //一直遍历右子树的最下面,边遍历边将节点压栈
            while (cur)
            {
                s.push(cur);
                cur=cur->_right;
            }
            if (!s.empty())
            {
                //右子树已经遍历完了,
                cur = s.top();
                s.pop();
                cout << cur->_data << " ";
                //遍历左子树
                cur = cur->_left;
            }
        }
        cout << endl;
    }
    //层序
    void _LevelOeder(Node *root)
    {
        queue<Node *> q;
        if (root == NULL)
        {
            return;
        }
        if (root)
        {
            q.push(root);//把根节点入队
        }
        while (!q.empty())
        {
            Node*front = q.front();
            cout << front->_data << " ";
            q.pop();

            if (front->_left)
                q.push(front->_left);//左子树入队
            if (front->_right)
                q.push(front->_right);//右子树入队
        }
        cout << endl;
    }
protected:
    Node  *_root;
};

void TestBinaryTree()
{
    int a1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
    size_t sz = sizeof(a1) / sizeof(a1[0]);
    BinaryTree<int> t(a1, sz, '#');
    BinaryTree<int> t1;
    t1 = t;//调赋值运算符的重载
    cout << t1.Size() << endl;
    cout << t1.Depth() << endl;
    cout << t1.LeftSize() << endl;
    cout << t1.LeftSize() << endl;
    t1.PrevOrder();
    t1.InOrder();
    t1.PosOrder();
    t1.LevelOrder();
    t1.PrevOrder_NotR();
    t1.InOrder_NotR();
    t1.PosOrder_NotR();
}

.cpp文件

#include<iostream>
#include"BinaryTree.h"
using namespace std;

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

测试结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值