C++数据结构与算法——第八章:二叉树

注意:

1.成员函数指针的声明/定义及使用(typedef void(BinaryTree::*VISIT)(treenode *node);)
2. destroy时不能进行前序/中序遍历,最好使用非递归的层次遍历进行删除
3.在类外部不能使用含有模板的typedef,但是在类内部可以(为什么?未知!)
4.实现参考的是《C++数据结构与算法分析》第八章,但有所修改(size实现源代码使用的是static int作为计数器)
5.注意层次遍历的实现——借助于queue

#pragma once

#include <queue>
#include <iostream>

using namespace std;

//• 确定其高度。
//• 确定其元素数目。
//• 复制。
//• 在屏幕或纸上显示二叉树。
//• 确定两棵二叉树是否一样。
//• 删除整棵树。
//• 若为数学表达式树,计算该数学表达式。
//• 若为数学表达式树,给出对应的带括号的表达式。
//
//有四种遍历二叉树的方法:
//• 前序遍历。
//• 中序遍历。
//• 后序遍历。
//• 逐层遍历

template<typename T>
class treenode
{
public:
    treenode():m_pleftnode(nullptr),m_prightnode(nullptr){}
    treenode(const T &t) :m_data(t), m_pleftnode(nullptr), m_prightnode(nullptr) {}
    treenode(const T &t, treenode<T> * leftnode, treenode<T> * righttree):m_data(t),m_pleftnode(leftnode),m_prightnode(righttree){}
    treenode(const treenode<T> &t):m_data(t.m_data), m_pleftnode(t.m_pleftnode), m_prightnode(t.m_prightnode) {}

    T m_data;
    treenode<T> *m_pleftnode;
    treenode<T> *m_prightnode;
};



//template<typename T>
//struct visitex
//{
//  typedef void(*visit)(treenode<T> *node);
//};

//template<typename T>
//using VISIT = visitex<T>::visit;

//定义一个辅助class
//template<class T>
//struct bar {
//  typedef void(*pfun)(T t);
//};
//然后用的时候
//bar<int>::pfun ptr;


template<typename T>
class BinaryTree
{
public:
    //template<typename T>
    typedef void(*visit)(treenode<T> *node);

    typedef void(BinaryTree<T>::*VISIT)(treenode<T> *node);
    BinaryTree() :m_proot(nullptr) {
        m_increase = &BinaryTree<T>::increase; m_pOutPutNode = &BinaryTree<T>::OutPutNode;
    }
    BinaryTree(const treenode<T> & t)
    {
        m_proot = new treenode<T>(t);
        m_increase = &BinaryTree<T>::increase;
        m_pOutPutNode = &BinaryTree<T>::OutPutNode;
        m_freeFunc = &BinaryTree<T>::free;
    }

    ~BinaryTree()
    {
        destroy(m_proot);
    }

    void increase(treenode<T> *node)
    {
        m_count++;
    }

    void OutPutNode(treenode<T> *node)
    {
        cout << node->m_data << "  ";
    }

    int size()
    {
        m_count = 0;
        LevelOrder(m_increase);
        return m_count;
    }

    int Height()
    {
        return Height(m_proot);
    }

    void destroy(treenode<T> *node)
    {
        LevelOrder(m_freeFunc,node);
        node = nullptr;
    }

    void MakeTree(const T &t, BinaryTree<T> &lefttree, BinaryTree<T> &righttree)
    {
        destroy(m_proot);
        m_proot = new treenode<T>(t,lefttree.m_proot,righttree.m_proot);
        lefttree.m_proot = righttree.m_proot = nullptr;     
    }

    bool BreakTree(T &t, BinaryTree<T> &lefttree, BinaryTree<T> &righttree)
    {
        if (isEmpty())
        {
            return false;
        }
        t = m_proot->m_data;
        if (!lefttree.isEmpty())
        {
            destroy(lefttree.m_proot);
        }
        if (!righttree.isEmpty())
        {
            destroy(lefttree.m_proot);
        }
        lefttree.m_proot = m_proot->m_pleftnode;
        righttree.m_proot = m_proot->m_prightnode;
        delete m_proot;
        m_proot = nullptr;
        return true;
    }
    treenode<T> *getRoot()
    {
        return m_proot;
    }
    bool getRootData(T &x)
    {
        if (isEmpty())
        {
            return false;
        }
        x = m_proot->m_data;
        return true;
    }
    bool isEmpty() { return (m_proot == nullptr); }
    void PreOrder(VISIT v, treenode<T> *node)
    {
        if (node != nullptr)
        {
            (this->*v)(node);
            PreOrder(v, node->m_pleftnode);
            PreOrder(v, node->m_prightnode);
        }
    }
    void InOrder(VISIT v, treenode<T> *node)
    {
        if (node != nullptr)
        {
            InOrder(v, node->m_pleftnode);
            v(node);
            InOrder(v, node->m_prightnode);
        }
    }
    void PostOrder(VISIT v, treenode<T> *node)
    {
        if (node != nullptr)
        {
            PostOrder(v, node->m_pleftnode);
            PostOrder(v, node->m_prightnode);
            v(node);
        }
    }
    void LevelOrder(VISIT v, treenode<T> * node = nullptr)
    {
        treenode<T> *tmp = m_proot;
        if (node != nullptr)
        {
            tmp = node;
        }
        queue<treenode<T>*> que;        
        if (tmp != nullptr)
        {
            que.push(tmp);
            while (!que.empty())
            {
                tmp = que.front();
                que.pop();
                if (tmp->m_pleftnode != nullptr)
                {
                    que.push(tmp->m_pleftnode);
                }
                if (tmp->m_prightnode != nullptr)
                {
                    que.push(tmp->m_prightnode);
                }
                (this->*v)(tmp);
            }
        }
    }

    VISIT m_pOutPutNode;
private:
    int Height(treenode<T> * node)
    {
        if (nullptr == node)
        {
            return 0;
        }
        int hl = Height(node->m_pleftnode);
        int hr = Height(node->m_prightnode);
        if (hl > hr)
        {
            return ++hl;
        }
        return ++hr;
    }
    void free(treenode<T> * node)
    {
        delete node;
    }
    VISIT m_freeFunc;
    treenode<T> *m_proot;
    VISIT m_increase;
    int m_count ;
};

#include "binarytree.h"
#include <iostream>

using namespace std;

int main()
{
    BinaryTree<int> tree1;

    BinaryTree<int> treeleft_level1_2(8);
    treeleft_level1_2.MakeTree(2, BinaryTree<int>(4), BinaryTree<int>(5));


    BinaryTree<int> treeright_level1_2;
    treeright_level1_2.MakeTree(3, BinaryTree<int>(6), BinaryTree<int>());

    tree1.MakeTree(1, treeleft_level1_2, treeright_level1_2);
    tree1.PreOrder(tree1.m_pOutPutNode,tree1.getRoot());
    cout << endl;
    tree1.LevelOrder(tree1.m_pOutPutNode);
    cout << endl;

    cout << "count of tree1:" << tree1.size() << endl;
    cout << "Height of tree1:" << tree1.Height() << endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值