【数据结构】二叉树的基本操作

求取二叉树的深度解析博客

用非递归实现二叉树的前序,中序,后序遍历解析博客

源码:

bintree.h

#pragma once
#ifndef  __BINTREE_H__

#define __BINTREE_H__
#include<iostream>
#include<stdio.h>
#include<stack>
#include<queue>

using namespace std;

//二叉树节点
template<class T>
struct BinTreeNode
{
    BinTreeNode(const T& data)
        :_data(data)
        , _pLeft(NULL)
        , _pRight(NULL)
    {}
    T _data;
    BinTreeNode<T>* _pLeft;
    BinTreeNode<T>* _pRight;
};

//二叉树
template<class T>
class BinTree
{
    typedef BinTreeNode<T> Node;
    typedef Node* pNode;
public:

    //构造函数
    //空二叉树的构造
    BinTree()
        :_pRoot(NULL)
    {}

    //带参的二叉树构造函数
    BinTree(T* arr,size_t size,T invalid){
        size_t index = 0;
        _pRoot = CreateNewTree(arr, size, index, invalid);
    }

    //拷贝构造函数
    BinTree(const BinTree<T>& bt){
        _pRoot = _CopyBinTree(bt._pRoot);
    }

    //赋值运算符重载
    BinTree<T>& operator=(const BinTree<T>& bt){
        if (this != &bt){
            this->~BinTree();
            _pRoot = _CopyBinTree(bt._pRoot);
        }
        return *this;
    }

    //前序遍历
    void PreOrder(){
        cout << "前序遍历";
        _PreOrder(_pRoot);
        cout << endl;
    }

    //前序非递归遍历
    void PreOrderNR(){
        cout << "前序非递归遍历" << endl;
        _PreOrderNR(_pRoot);
        cout << endl;
    }

    //中序遍历
    void InOrder(){
        cout << "中序遍历";
        _InOrder(_pRoot);
        cout << endl;
    }

    //中序非递归遍历
    void InOrderNR(){
        cout << "中序非递归遍历" << endl;
        _InOrderNR(_pRoot);
        cout << endl;
    }

    //后序遍历
    void PostOrder(){
        cout << "后序遍历";
        _PostOrder(_pRoot);
        cout << endl;
    }

    //后序非递归遍历
    void PostOrderNR(){
        cout << "后序非递归遍历"<<endl;
        _PostOrderNR(_pRoot);
        cout << endl;
    }

    //层序遍历
    void LevelOrder(){
        cout << "层序遍历";
        _LevelOrder(_pRoot);
        cout << endl;
    }

    //二叉树的高度
    void Depth(){
        cout << "树的高度为:" << endl;
        cout << _Depth(_pRoot) << endl;
    }

      //二叉树中的节点个数
    void Size(){
        cout << "二叉树的节点个数:" << endl;
        cout << _Size(_pRoot) << endl;
    }

    //求叶子节点的个数
    void LeafSize(){
        cout << "二叉树的叶子节点个数:" << endl;
        cout << _LeafSize(_pRoot) << endl;
    }

    //二叉树中第k层结点的个数
    void GetKLevelSize(size_t k){
        cout << "二叉树中第k层结点的个数:" << endl;
        cout << _GetKLevelSize(_pRoot) << endl;
    }

    //查找值为k的节点
    void Find(T k){
        cout << "查找值为k的节点" << endl;
        pNode pFin = _Find(_pRoot, k);
        cout <<"找到该节点的值为:"<< pFin->_data << endl;
    }

    //判断一个节点是否在二叉树中
    bool IsNodeInBinTree(pNode pNode){
        return _IsNodeInBinTree(_pRoot, pNode);
    }

    //二叉树的镜像
    void Mirror(){
        return _Mirror(_pRoot);
    }

    //二叉树的镜像,非递归
    void Mirror_Nor(){
        if (NULL == _pRoot)
            return;
        queue<T> q;
        q.push(_pRoot);
        while (!q.empty()){
            pNode pCur = q.front();
            swap(pCur->_pLeft, pCur->_pRight);
            if (pCur->_pLeft)
                q.push(pCur->_pLeft);
            if (pCur->_pRight)
                q.push(pCur->_pRight);

            q.pop();
        }
    }

    //判断一颗二叉树是否是完全二叉树
    bool IsCompleteBinTree(){
        //方法一
        //return _IsCompleteBinTree_1(_pRoot);
        //方法二
        return _IsCompleteBinTree_2(_pRoot);
    }

    //析构函数
    ~BinTree(){
        _Destroy(_pRoot);
    }
protected:

    //创建二叉树
    Node* CreateNewTree(T* arr, size_t size, size_t& index, const T& invalid){
        pNode pRoot = NULL;
        if (index < size && arr[index] != invalid){
            pRoot = new Node(arr[index]);
            pRoot->_pLeft = CreateNewTree(arr, size, ++index, invalid);
            pRoot->_pRight = CreateNewTree(arr, size, ++index, invalid);
        }
        return pRoot;
    }

    //销毁二叉树
    void _Destroy(pNode pRoot){
        if(pRoot)
        {
            _Destroy(pRoot->_pLeft);
            _Destroy(pRoot->_pRight);
            delete pRoot;
            pRoot = NULL;
        }
    }

    //拷贝二叉树
    pNode _CopyBinTree(pNode pRoot){
        if (NULL == pRoot)
            return NULL;
        pNode newRoot = new Node(pRoot->_data);
        newRoot->_pLeft = _CopyBinTree(pRoot->_pLeft);
        newRoot->_pRight = _CopyBinTree(pRoot->_pRight);
        return newRoot;
    }

    //前序
    void _PreOrder(pNode pRoot){
        if (pRoot){
            cout << pRoot->_data << " ";
            _PreOrder(pRoot->_pLeft);
            _PreOrder(pRoot->_pRight);
        }
    }

    //前序非递归
    void _PreOrderNR(pNode _pRoot){
        pNode pCur = _pRoot;
        stack<pNode> s;
        while (pCur || !s.empty()){
            //将左侧节点依次压栈
            while (pCur){
                cout << pCur->_data << "  ";
                s.push(pCur);
                pCur = pCur->_pLeft;
            }
            //开始依次访问栈顶节点的右子树,通过循环将该右子树的左侧节点依次压栈
            pNode pTop = s.top();
            s.pop();
            pCur = pTop->_pRight;//循环的子问题
        }
    }

    //中序
    void _InOrder(pNode pRoot){
        if (pRoot){
            _InOrder(pRoot->_pLeft);
            cout << pRoot->_data << " ";
            _InOrder(pRoot->_pRight);
        }
    }

    //中序非递归
    void _InOrderNR(pNode _pRoot){
        pNode pCur = _pRoot;
        stack<pNode> s;
        while (pCur || !s.empty()){
            //将左侧节点依次压栈
            while (pCur){
                s.push(pCur);
                pCur = pCur->_pLeft;
            }
            //栈中节点的左子树已经遍历完
            //栈中节点自身和右子树还没有遍历
            //开始依次访问栈顶节点的右子树,通过循环将该右子树的左侧节点依次压栈
            pNode pTop = s.top();
            cout << pTop->_data << "  ";
            s.pop();
            pCur = pTop->_pRight;//循环的子问题
        }
    }

    //后序
    void _PostOrder(pNode pRoot){
        if (pRoot){
            _PostOrder(pRoot->_pLeft);
            _PostOrder(pRoot->_pRight);
            cout << pRoot->_data << " ";
        }
    }

    //后序非递归
    void _PostOrderNR(pNode _pRoot){
        pNode pCur = _pRoot;
        stack<pNode> s;
        while (pCur || !s.empty()){
            //将左侧节点依次压栈
            while (pCur){
                s.push(pCur);
                pCur = pCur->_pLeft;
            }
            pNode prev = NULL;
            pNode pTop = s.top();
            if (NULL == pTop->_pRight || prev == pTop->_pRight){
                cout << pTop->_data << "  ";
                s.pop();
                prev = pTop;
            }
            else{
                //进入下一层子循环
                pCur = pTop->_pRight;
            }
        }
    }

    //层序
    void _LevelOrder(pNode pRoot){
        queue<pNode> q;
        if (pRoot){
            q.push(pRoot);
        }
        while (!q.empty()){
            pNode front = q.front();
            cout << front->_data << "  ";
            if (front->_pLeft)
                q.push(front->_pLeft);
            if (front->_pRight)
                q.push(front->_pRight);
            q.pop();
        }
    }

    //二叉树的高度
    size_t _Depth(pNode pRoot){
        if (NULL == pRoot)
            return 0;
        if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
            return 1;
        size_t LeftDepth = _Depth(pRoot->_pLeft);
        size_t RightDepth = _Depth(pRoot->_pRight);
        return LeftDepth > RightDepth ? LeftDepth + 1 : RightDepth + 1;
    }

    //二叉树的节点个数
    size_t _Size(pNode pRoot){
        if (NULL == pRoot)
            return 0;
        //返回当前节点的左子树和右子树以及当前节点个数
        return _Size(pRoot->_pLeft) + _Size(pRoot->_pRight) + 1;
    }

    //二叉树中叶子节点的个数
    size_t _LeafSize(pNode pRoot){
        if (NULL == pRoot)
            return 0;
        if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
            return 1;
        return _LeafSize(pRoot->_pLeft) + _LeafSize(pRoot->_pRight);
    }

    //二叉树中第k层结点的个数
    size_t _GetKLevelSize(pNode pRoot,size_t k){
        if (NULL == pRoot)
            return 0;
        if (1 == k)
            return 1;
        return _GetKLevelSize(pRoot->_pLeft, k - 1) + _GetKLevelSize(pRoot->_pRight, k - 1);
    }

    //查找值为k的节点
    pNode _Find(pNode pRoot,const T& k){
        if (NULL == pRoot)
            return NULL;
        if (k == pRoot->_data)
            return pRoot;
        pNode pFin = _Find(pRoot->_pLeft, k);
        if (pFin)
            return pFin;
        return _Find(pRoot->_pRight, k);
    }

    //判断节点是否在二叉树中
    bool _IsNodeInBinTree(pNode pRoot, pNode pNode){
        if (NULL == pRoot || NULL == pNode)
            return false;
        if (pRoot == pNode)
            return true;
        bool IsIn = false;
        if (IsIn = _IsNodeInBinTree(pRoot->_pLeft, pNode))
            return true;
        return _IsNodeInBinTree(_pRoot->_pRight, pNode);
    }

    //二叉树的镜像,递归
    void _Mirror(pNode pRoot){
        if (pRoot){
            swap(pRoot->_pLeft, pRoot->_pRight);
            _Mirror(pRoot->_pLeft);
            _Mirror(pRoot->_pRight);
        }
    }

    //判断一颗二叉树是否是完全二叉树
    //方法一
    bool _IsCompleteBinTree_1(pNode pRoot){
        cout << "_IsCompleteBinTree_1" << endl;
        if (NULL == pRoot)
            return false;
        queue<pNode> q;
        q.push(pRoot);
        pNode pCur = q.front();
        //将所有的结点全部押入队列中,空也压入。每次判断队列的头,如果队列头为空了则跳出循环,如果此后队列中还有元素则不是完全二叉树
        while (pCur){
            q.pop();
            q.push(pCur->_pLeft);
            q.push(pCur->_pRight);
            pCur = q.front();
        }
        while (!q.empty()){
            if (NULL != q.front())
                return false;
            q.pop();
        }
        return true;
    }

    bool _IsCompleteBinTree_2(pNode pRoot){
        cout << "_IsCompleteBinTree_2" << endl;
        if (NULL == pRoot)
            return false;
        queue<pNode> q;
        q.push(pRoot);
        bool flag = false;
        while (!q.empty()){
            pNode pCur = q.front();
            q.pop();
            if (flag){
                //再已经存在非满节点的情况下,还存在非满节点,则一定不是满二叉树
                if (NULL != pCur->_pLeft || NULL != pCur->_pRight)
                    return false;
            }
            else{
                //之前不存在非满节点的情况
                if (NULL == pCur->_pLeft && NULL != pCur->_pRight)//一个节点左子树为空,右子树不为空,则一定不是满二叉树
                    return false;
                else if (NULL != pCur->_pLeft && NULL != pCur->_pRight)//两个节点都不为空
                {
                    q.push(pCur->_pLeft);
                    q.push(pCur->_pRight);
                }
                else if (NULL != pCur->_pLeft && NULL == pCur->_pRight){
                    //左子树不为空,右子树为空,出现非满节点,改变标记
                    q.push(pCur->_pLeft);
                    flag = true;
                }
                else{
                    //两个节点都为空
                    flag = true;
                }
            }
        }
    }

private:
    pNode _pRoot;
};

#endif   //__BINTREE_H__

test.cpp

#include"bintree.h"
#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;

void test()
{
    char arr[] = { 'A','B','D','#','#','#','C','E','#','#','F' };
    char arr1[] = {'A','B','D','#','#','E','#','#','C','F'};
    char arr2[] = {'A','B','D','G','#','#','#','E','#','#','C','F'};
    /*char arr2[] = { '1', '2', '#', '#', '3' };
    cout << "bt原始树" << endl;*/
    //场景一
    BinTree<char> bt(arr, sizeof(arr) / sizeof(arr[0]), '#');
    //场景二
    BinTree<char> bt1(arr1, sizeof(arr1) / sizeof(arr1[0]), '#');
    //场景三
    BinTree<char> bt2(arr2, sizeof(arr2) / sizeof(arr2[0]), '#');
    bt.PreOrder();
    if (bt.IsCompleteBinTree())
        cout << "bt is complete BinTree" << endl;
    else
        cout << "bt is not complete BinTree" << endl;
    bt1.PreOrder();
    if (bt1.IsCompleteBinTree())
        cout << "bt1 is complete BinTree" << endl;
    else
        cout << "bt1 is not complete BinTree" << endl;
    bt2.PreOrder();
    if (bt2.IsCompleteBinTree())
        cout << "bt2 is complete BinTree" << endl;
    else
        cout << "bt2 is not complete BinTree" << endl;
    //bt.PreOrder();
    //bt.PreOrderNR();
    //bt.InOrder();
    //bt.InOrderNR();
    //bt.PostOrder();
    //bt.GetKLevelSize(3);
    //bt.Depth();
    //bt.Size();
    //bt.Find('E');
    //bt.LevelOrder();
    /*cout << "bt1原始树" << endl;
    BinTree<char> bt1(arr2, sizeof(arr2) / sizeof(arr2[0]), '#');
    bt1.PreOrder();
    bt1.InOrder();
    bt1.PostOrder();
    bt1.LevelOrder();
    cout << "bt1=bt赋值后,bt1树的遍历" << endl;
    bt1 = bt;
    bt1.PreOrder();
    bt1.InOrder();
    bt1.PostOrder();
    bt1.LevelOrder();*/
}

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

程序测试结果:

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值