二叉树的,前/中/后序的遍历( 递归,非递归),层序遍历,以及各种应用功能

1.实现二叉树的前/中/后序的递归和非递归的的遍历,以及层序遍历。

2.实现二叉树的各种应用

① 二叉树中的所有结点 ② 二叉树中所有叶子节点个数 ③ 二叉树的深度(高度) ④ 二叉树中第K层的结点个数

以下是代码的具体实现

#include<iostream>
#include<stack>
#include<queue>
using namespace std;

template <class T>
struct Tree_Node
{
    T _data;
    Tree_Node* _left;
    Tree_Node* _right;
    Tree_Node(const T& val)
        :_data(val)
        , _left(NULL)
        , _right(NULL)
    {}
};

template<class T>
class Binary_Tree
{
public:

    typedef Tree_Node<T>  Node;
    Binary_Tree(const int Tree[] ,int& Index ,const int Invalid_value = '*')  //
    {
        //这块要自己定义一个初始化函数,因为构造函数没有返回值,
        //使用递归的话要使用返回值


        //下边有两种初始化方法,都行,但是二叉树的数组要初始化好,不然就蹦了

        //这个是递归 有返回值接收的
        //_root = Init(_root, Tree, Index, Invalid_value);

        //这个事不需要返回值接收的,传值是【引用】
        Init(_root, Tree, Index, Invalid_value);

    }

    //二叉树的初始化,用递归就可以初始化
    //如果不是传返回值的,就要使用【引用】,不然传参过来的只是零时变量,不会改变root的值
    void Init(Node*& root, const int Tree[], int& Index, const int& Invalid_value)
    {
        if(Tree[Index] == Invalid_value)
        {
            Index++;
        }                           // 1, 2,'*', 3,'*',8 ,'*','*'
        else
        {
            root = new Node(Tree[Index]);
            Index++;
            Init(root->_left, Tree, Index, Invalid_value);
            Init(root->_right, Tree, Index, Invalid_value);
        }
    }

    //Node* Init(Node* root, const int Tree[], int& Index, const int& Invalid_value)
    //{
    //  if (Tree[Index] == Invalid_value)
    //  {
    //      Index++;
    //  }                           // 1, 2,'*', 3,'*',8 ,'*','*'
    //  else
    //  {
    //      root = new Node(Tree[Index]);
    //      Index++;
    //      root->_left = Init(root->_left, Tree, Index, Invalid_value);
    //      root->_right = Init(root->_right, Tree, Index, Invalid_value);
    //  }
    //  return root;
    //}




    //拷贝构造
    //BinaryTree(const BinaryTree& t)
    //{}
    //BinaryTree& operator=(const BinaryTree& t);
    //~BinaryTree();


    //前序-------递归
    void PrevOrder()
    {
        //  头  左    右
        _PrevOrder(_root);
    }

    //中序------递归
    void InOrder()
    {
        _InOrder(_root);
    }

    //后序------递归
    void PostOrder()
    {
        _PostOrder(_root);
    }

    //层序访问二叉树(从上到下,从左到右)
    //使用队列实现
    void LevelOrder()
    {
        queue<Node*> q;
        _LevelOrder(_root,q);
    }

    //前序----非递归----使用栈
    void PrevOrder_NonR()
    {
        //创建一个栈,用来存储左子树的头结点
        stack<Node*> s;
        _PrevOrder_NonR(_root,s);
    }

    //中序----非递归
    void InOrder_NonR()
    {
        stack<Node*> s;
        _InOrder_NonR(_root,s);
    }

    //后序----非递归
    void PostOrder_NonR()
    {
        stack<Node*> s;
        _PostOrder_NonR(_root, s);
    }

    //二叉树中所有结点个数
    size_t Size()
    {
        return _Size(_root);
    }

    //二叉树的深度
    size_t Depth()
    {
        return _Depth(_root);
    }

    //叶子(最底层)结点个数--递归
    size_t Leaf_Size()
    {
        return _Leaf_Size(_root);
    }

    //第K层的结点个数
    size_t GetKLevel(size_t K)
    {
        return _GetKLevel(_root,K);
    }
protected:

    //上面的前序输出只是对外的一个接口,这里是实现函数,不对外开放,因此要protected

    //前序---递归
    void _PrevOrder(Node* root)
    {
        if (root)
        {
            cout << root->_data << " ";
            _PrevOrder(root->_left);
            _PrevOrder(root->_right);
        }
    }

    //中序---递归
    void _InOrder(Node* root)
    {
        if (root)
        {
            _InOrder(root->_left);
            cout << root->_data << " ";
            _InOrder(root->_right);
        }
    }

    //后序---递归
    void _PostOrder(Node* root)
    {
        if (root)
        {
            _PostOrder(root->_left);
            _PostOrder(root->_right);
            cout << root->_data << " ";
        }
    }

    //前序非递归
    void _PrevOrder_NonR(Node* root,stack<Node*> s)
    {
        Node* tmp = root;
        while (!s.empty() || tmp)
        {
            while (tmp != NULL)
            {
                s.push(tmp);
                cout << tmp->_data << " ";
                tmp = tmp->_left;
            }

            tmp = s.top();
            s.pop();

            //子问题
            tmp = tmp->_right;
        }

    }

    //中序----非递归
    void _InOrder_NonR(Node* _root,stack<Node*> s)
    {
        Node* root = _root;
        while (!s.empty() || root)
        {
            //遍历左子树
            while (root != NULL)
            {
                s.push(root);
                root = root->_left;
            }

            //每次先输出左结点
            cout << s.top()->_data << " ";
            root = s.top();
            s.pop();

            //子问题
            root = root->_right;
        }
    }

    //后序---非递归
    void _PostOrder_NonR(Node* _root,stack<Node*> s)
    {
        Node* prev = NULL;   //用 prev  来存储上一个结点的位置,如果prev == 当前结点的右子树,那就说明已经遍历过右子树
        Node* root = _root;
        while (!s.empty() || root)
        {
            while (root)
            {
                s.push(root);
                root = root->_left;
            }

            root = s.top();

            //这里用一个标志 prev 来判断是否已经走过右子树,如果当前结点的右子树的地址等于 prev,那就说明
            //已经走过右子树,不能再遍历右子树;
            if (root->_right == NULL || root->_right== prev)
            {
                prev = root;
                cout << root->_data << " ";
                s.pop();
                root = NULL;   //输出后,置为空,这个结点的子树就已经结束,以便访问上一个结点的右结点
            }
            else
            {
                root = root->_right;
            }

        }
    }


    //叶子(最底层)结点个数--递归
    size_t _Leaf_Size(Node* root)
    {
        if (root == NULL)
        {
            return 0;
        }
        else if (root->_left == NULL && root->_right == NULL)
        {
            return 1;
        }
        else
        {
            return _Leaf_Size(root->_left) + _Leaf_Size(root->_right);
        }
    }

    //结点个数(所有结点个数)
    size_t _Size(Node* root)
    {
        if (root == NULL)
        {
            return 0;
        }
        else
        {    //当前结点个数(1) + 子树的结点个数
            return 1 + _Size(root->_left) + _Size(root->_right);
        }
    }

    // 二叉树的深度(高度)
    size_t _Depth(Node* root)
    {
        int left_hight = 0;
        int right_hight = 0;
        if (root == 0)
        {
            return 0;
        }

        left_hight = _Depth(root->_left);
        right_hight = _Depth(root->_right);

        return left_hight > right_hight ? left_hight + 1 : right_hight + 1;
    }

    //第K层结点个数
    size_t _GetKLevel(Node* root, size_t K)
    {
        //默认二叉树根节点从一层开始,所以0层是0个结点
        if (K == 0 || root == NULL)  //这里不仅要判断k == 0 时返回0,还要判断root == NULL,也是返回0;
        {
            return 0;
        }
        else if (K == 1)
        {
            return 1;
        }
        K--;
        return _GetKLevel(root->_left,K) + _GetKLevel(root->_right,K);

    }

    层序访问二叉树(从上到下,从左到右)
    //使用队列实现
    void _LevelOrder(Node* Root, queue<Node*> q)
    {
        if (Root == NULL)
        {
            return;
        }

        Node* root = Root;
        q.push(root);

        //这里要用q.front()函数来判断二叉树是否已经遍历完成
        while (q.front())
        {
            Node* Front = q.front();
            q.pop();
            cout << Front->_data << " ";
            q.push(Front->_left);
            q.push(Front->_right);
        }
    }
private:
    Node* _root;
};


void test1()
{
    int Tree[] = { 1, 2, 4, '*','*',5 ,'*','*',3 ,6,'*','*',7,'*','*','*'};
    //初始化要初始化完全,不然奔溃
    //int Tree[] = { '*' };
    int Index = 0;
    int Invalid_value = '*';
    Binary_Tree<int> tree(Tree,Index,Invalid_value);
    //tree.PrevOrder();
    //cout << endl;
    //tree.InOrder();
    tree.PostOrder();
    cout << endl;
    //tree.PostOrder();
    //tree.PrevOrder_NonR();
    //tree.InOrder_NonR();
    tree.PostOrder_NonR();
    cout << endl;
    cout << tree.Leaf_Size() << " ";
    cout << endl;
    cout << tree.Size() << " ";
    cout << endl;
    cout << tree.Depth() << " ";
    cout << endl;
    cout << tree.GetKLevel(1) << " ";
    cout << endl;
    tree.LevelOrder();
}
当然,二叉树遍历有三种主要方式:先序遍历(根-左-右)、遍历(左-根-右)和后序遍历(左-右-根)。非递归的层次遍历(也叫广度优先遍历,从上到下、从左到右)通常使用队列来辅助实现。 这里分别给出这些遍历非递归算法代码: 1. 层序遍历(广度优先遍历): ```c #include <stdio.h> #include <stdlib.h> #include <queue> struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; void levelOrder(struct TreeNode* root) { if (root == NULL) return; // 使用队列存储每一层的节点 queue<struct TreeNode*> q; q.push(root); while (!q.empty()) { int size = q.size(); for (int i = 0; i < size; i++) { struct TreeNode* node = q.front(); q.pop(); printf("%d ", node->val); // 打印当节点值 if (node->left != NULL) q.push(node->left); if (node->right != NULL) q.push(node->right); } printf("\n"); // 换行表示新的一层 } } ``` 2. 先序遍历递归非递归两种方式,这里是非递归版本,使用栈): ```c void preorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s; s.push(root); while (!s.empty()) { struct TreeNode* node = s.top(); s.pop(); printf("%d ", node->val); // 打印当节点值 if (node->right != NULL) s.push(node->right); if (node->left != NULL) s.push(node->left); } } ``` 3. 遍历非递归,同样使用栈): ```c void inorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s; struct TreeNode* curr = root; while (curr != NULL || !s.empty()) { while (curr != NULL) { s.push(curr); curr = curr->left; } curr = s.top(); s.pop(); printf("%d ", curr->val); // 打印当节点值 curr = curr->right; } } ``` 4. 后序遍历非递归,使用两个栈): ```c void postorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s1, s2; s1.push(root); while (!s1.empty()) { struct TreeNode* node = s1.top(); s1.pop(); s2.push(node); if (node->left != NULL) s1.push(node->left); if (node->right != NULL) s1.push(node->right); } while (!s2.empty()) { struct TreeNode* node = s2.top(); s2.pop(); printf("%d ", node->val); // 打印当节点值 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值