【二叉树】C++实现二叉树的多项操作:创建、遍历、求大小、求高度等

本文介绍了使用C++实现的二叉树多项操作,包括流创建、字符串创建、遍历、拷贝、求大小、求高度、查找元素和节点、清空及比较等。代码已经通过部分功能测试,但未进行边界值和特殊输入测试。欢迎讨论和指正。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现功能

本文代码实现了二叉树的以下操作

  • 无返回值的流创建。
  • 带返回值的流创建。
  • 无返回值的字符串创建。
  • 带返回值的字符串创建。
  • 前序、中序、后序递归遍历二叉树。
  • 前序、中序、后序迭代遍历二叉树。
  • 拷贝二叉树。
  • 求二叉树大小。
  • 求二叉树高度。
  • 查找二叉树中的某个元素。
  • 查找二叉树某个节点的父节点。
  • 查找二叉树中某热节点的子节点。
  • 清空二叉树。
  • 比较两棵二叉树。
  • 打印某个二叉树节点。
  • 等等。

测试

  • 功能测试:文中所有代码均通过少量功能测试,并贴出了部分测试代码。代码未进行大量用例测试。
  • 边界值测试:未进行边界值测试。
  • 特殊输入测试:未进行特殊输入测试。

欢迎交流讨论,欢迎批评指正!

核心代码

#ifndef _BINARY_TREE_H
#define _BINARY_TREE_H

#include<iostream>
#include<stack>
#include<queue>
#include<assert.h>

template<typename T>
class BinaryTree;

template<typename T>
class BinaryTreeNode
{
    friend BinaryTree<T>;
public:
    BinaryTreeNode() : data(T()),left(nullptr), right(nullptr) {}
    BinaryTreeNode(T _data, BinaryTreeNode<T> * left = nullptr, BinaryTreeNode<T> * right = nullptr)
        : data(_data), left(nullptr), right(nullptr) {}
private:
    T data;
    BinaryTreeNode<T> * left;
    BinaryTreeNode<T> * right;
};

template<typename T>
class BinaryTree
{
    typedef BinaryTreeNode<T> NodeType;
public:
    BinaryTree() = default;
    BinaryTree(const T& ref) : refval(ref) {}
    BinaryTree(const BinaryTree &);
    ~BinaryTree();
public:
    // create binary by cin/string
    void createBT();
    void createBT(const char *&);
    NodeType * createBT_Ret();
    NodeType * createBT_Ret(const char *&);

    // traverse recur/iter
    void preorderTraverse_Recur() const;
    void inorderTraverse_Recur() const;
    void postorderTraverse_Recur() const;
    void preorderTraverse_Iter() const;
    void inorderTraverse_Iter() const;
    void postorderTraverse_Iter() const;
    void levelTraverse() const;
    void zigzagTraverse() const;

    // get size of tree
    size_t size() const;

    // get height of tree
    size_t height() const;

    // get child node
    NodeType * leftChild(const NodeType *) const;
    NodeType * rightChild(const NodeType *) const;

    // get parent node
    NodeType * parent(const NodeType *) const;

    // find given value node;
    NodeType * find(const T &) const;

    // judge if two trees are same
    bool equal(BinaryTree &) const;

    // print tree node
    void print(const NodeType *) const;

    // clear the tree
    void makeEmpty();
protected:
    NodeType *  _copyTree(NodeType *);
    void _createBT(NodeType *&);
    void _createBT(NodeType *&, const char *&);
    NodeType * _createBT_Ret();
    NodeType * _createBT_Ret(const char *&);

    void _preorderTraverse_Recur(NodeType *) const;
    void _inorderTraverse_Recur(NodeType *) const;
    void _postorderTraverse_Recur(NodeType *) const;
    void _preorderTraverse_Iter(NodeType *) const;
    void _inorderTraverse_Iter(NodeType *) const;
    void _postorderTraverse_Iter(NodeType *) const;
    void _levelTraverse(NodeType *) const;
    void _zigzagTraverse(NodeType *) const;

    size_t _size(NodeType *) const;
    size_t _height(NodeType *) const;
    NodeType * _parent(NodeType *, const NodeType *) const;
    NodeType * _find(NodeType *, const T &) const;
    bool _equal(NodeType *, NodeType *) const;
    void _makeEmpty(NodeType *);
private:
    T refval;
    NodeType * root;
};

//******************** public interface ********************

////////////////////////////////////////////////////////////

template<typename T>
BinaryTree<T>::BinaryTree(const BinaryTree & bt)
{
    root = _copyTree(bt.root);
}

template<typename T>
BinaryTree<T>::~BinaryTree()
{
    makeEmpty();
    root = nullptr;
}

////////////////////////////////////////////////////////////

template<typename T>
void BinaryTree<T>::makeEmpty()
{
    _makeEmpty(root);
}

template<typename T>
void BinaryTree<T>::createBT()
{
    _createBT(root);
}

template<typename T>
void BinaryTree<T>::createBT(const char *& str)
{
    _createBT(root, str);
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::createBT_Ret()
{
    return _createBT_Ret();
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::createBT_Ret(const char *& str)
{
    return _createBT_Ret(str);
}

template<typename T>
void BinaryTree<T>::preorderTraverse_Recur() const
{
    _preorderTraverse_Recur(root);
}

template<typename T>
void BinaryTree<T>::inorderTraverse_Recur() const
{
    _inorderTraverse_Recur(root);
}

template<typename T>
void BinaryTree<T>::postorderTraverse_Recur() const
{
    _postorderTraverse_Recur(root);
}

template<typename T>
void BinaryTree<T>::preorderTraverse_Iter() const
{
    _preorderTraverse_Iter(root);
}

template<typename T>
void BinaryTree<T>::inorderTraverse_Iter() const
{
    _inorderTraverse_Iter(root);
}

template<typename T>
void BinaryTree<T>::postorderTraverse_Iter() const
{
    _postorderTraverse_Iter(root);
}

template<typename T>
void BinaryTree<T>::levelTraverse() const
{
    _levelTraverse(root);
}

template<typename T>
void BinaryTree<T>::zigzagTraverse() const
{
    _zigzagTraverse(root);
}

template<typename T>
size_t BinaryTree<T>::size() const
{
    return _size(root);
}

template<typename T>
size_t BinaryTree<T>::height() const
{
    return _height(root);
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::leftChild(const NodeType * current) const
{
    return current ? current->left : nullptr;
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::rightChild(const NodeType * current) const
{
    return current ? current->right : nullptr;
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::parent(const NodeType * givenNode) const
{
    return _parent(root, givenNode);
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::find(const T & key) const
{
    return _find(root, key);
}

template<typename T>
bool BinaryTree<T>::equal(BinaryTree & bt) const
{
    return _equal(root, bt.root);
}

template<typename T>
void BinaryTree<T>::print(const NodeType * current) const
{
    if(current)
        std::cout << current->data;
}


//******************** protected interface ********************

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_copyTree(NodeType * current)
{
    if(!current) return nullptr;

    NodeType *temp = new NodeType(current->data);
    assert(temp);
    temp->left = _copyTree(current);
    temp->right = _copyTree(current);

    return temp;
}

template<typename T>
void BinaryTree<T>::_makeEmpty(NodeType * current)
{
    if(current)
    {
        _makeEmpty(current->left);
        _makeEmpty(current->right);
        delete current;
    }
}

//////////////////////////////////////////////////////////

template<typename T>
void BinaryTree<T>::_createBT(NodeType *& current)
{
    T element;
    std::cin >> element;

    if(refval == element)
        current = nullptr;
    else
    {
        current = new NodeType(element);
        assert(current);
        _createBT(current->left);
        _createBT(current->right);
    }
}

template<typename T>
void BinaryTree<T>::_createBT(NodeType *& current, const char *& str)
{
    if(refval == *str)
        current = nullptr;
    else
    {
        current = new NodeType(*str);
        assert(current);
        _createBT(current->left, ++str);
        _createBT(current->right, ++str);
    }
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_createBT_Ret()
{
    T element;
    std::cin >> element;
    if(refval == element) return nullptr;

    NodeType *temp = new NodeType(element);
    assert(temp);

    temp->left = _createBT_Ret();
    temp->right = _createBT_Ret();

    return temp;
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_createBT_Ret(const char *& str)
{
    if(refval == str) return nullptr;

    NodeType * temp = new NodeType(*str);
    assert(temp);

    temp->left = _createBT_Ret(++str);
    temp->right = _createBT_Ret(++str);

    return temp;
}

template<typename T>
void BinaryTree<T>::_preorderTraverse_Recur(NodeType * current) const
{
    if(current)
    {
        std::cout << current->data << "  ";
        _preorderTraverse_Recur(current->left);
        _preorderTraverse_Recur(current->right);
    }
}

template<typename T>
void BinaryTree<T>::_inorderTraverse_Recur(NodeType * current) const
{
    if(current)
    {
        _inorderTraverse_Recur(current->left);
        std::cout << current->data << "  ";
        _inorderTraverse_Recur(current->right);
    }
}

template<typename T>
void BinaryTree<T>::_postorderTraverse_Recur(NodeType * current) const
{
    if(current)
    {
        _postorderTraverse_Recur(current->left);
        _postorderTraverse_Recur(current->right);
        std::cout << current->data << "  ";
    }
}

template<typename T>
void BinaryTree<T>::_preorderTraverse_Iter(NodeType *current) const
{
    if(!current) return;

    std::stack<NodeType*> stack;
    stack.push(current);

    while(!stack.empty())
    {
        NodeType *temp = stack.top();
        stack.pop();

        std::cout << temp->data << "  ";

        if(temp->right)
            stack.push(temp->right);
        if(temp->left)
            stack.push(temp->left);
    }
}

template<typename T>
void BinaryTree<T>::_inorderTraverse_Iter(NodeType *current) const
{
    std::stack<NodeType*> stack;
    NodeType *temp = current;

    while(temp || !stack.empty())
    {
        while(temp)
        {
            stack.push(temp);
            temp = temp->left;
        }

        if(!stack.empty())
        {
            temp = stack.top();
            std::cout << temp->data << "  ";
            stack.pop();

            temp = temp->right;
        }
    }
}

/*
enum{unvisited, visited};
template<typename T>
void BinaryTree<T>::_postorderTraverse_Iter(NodeType * current) const
{
    if(!current) return;

    std::stack<std::pair<NodeType*, int>> stack;
    stack.push(std::make_pair<current, unvisited>);

    while(!stack.empty())
    {
        NodeType *temp = stack.top().first;
        if(stack.top().second == unvisited)
        {
            stack.top().second = visited;

            if(temp->right)
                stack.push(std::make_pair<temp->right, unvisited>);
            if(temp->left)
                stack.push(std::make_pair<temp->left, unvisited>);
        }
        else
        {
            std::cout << temp.first << "  ";
            stack.pop();
        }
    }
}
*/

template<typename T>
void BinaryTree<T>::_postorderTraverse_Iter(NodeType * current) const
{
    if(!current) return;

    std::stack<NodeType*> stack;
    stack.push(current);
    std::stack<NodeType*> stackOfTemp;

    while(!stack.empty())
    {
        NodeType *temp = stack.top();
        stack.pop();
        stackOfTemp.push(temp);

        if(temp->left)
            stack.push(temp->left);
        if(temp->right)
            stack.push(temp->right);
    }

    while(!stackOfTemp.empty())
    {
        std::cout << stackOfTemp.top()->data << "  ";
        stackOfTemp.pop();
    }
}

template<typename T>
void BinaryTree<T>::_levelTraverse(NodeType * current) const
{
    if(!current) return;

    std::queue<NodeType*> queue;
    NodeType *temp = current;
    queue.push(temp);

    while(!queue.empty())
    {
        temp = queue.front();
        std::cout << temp->data << "  ";
        queue.pop();

        if(temp->left)
            queue.push(temp->left);
        if(temp->right)
            queue.push(temp->right);
    }
}

template<typename T>
void BinaryTree<T>::_zigzagTraverse(NodeType * current) const
{
    if(!current) return;

    NodeType *temp = current;
    std::stack<NodeType*> stackLeftToRight;
    std::stack<NodeType*> stackRightToLeft;
    stackLeftToRight.push(temp);

    while(!stackLeftToRight.empty() || !stackRightToLeft.empty())
    {
        while(!stackLeftToRight.empty())
        {
            temp = stackLeftToRight.top();
            std::cout << temp->data << "  ";
            stackLeftToRight.pop();

            if(temp->left)
                stackRightToLeft.push(temp->left);
            if(temp->right)
                stackRightToLeft.push(temp->right);
        }

        while(!stackRightToLeft.empty())
        {
            temp = stackRightToLeft.top();
            std::cout << temp->data << "  ";
            stackRightToLeft.pop();

            if(temp->right)
                stackLeftToRight.push(temp->right);
            if(temp->left)
                stackLeftToRight.push(temp->left);
        }
    }
}

template<typename T>
size_t BinaryTree<T>::_size(NodeType *current) const
{
    return current ? 1 + _size(current->left) + _size(current->right) : 0;
}

template<typename T>
size_t BinaryTree<T>::_height(NodeType *current) const
{
    if(!current) return 0;

    size_t heightOfLeft = 1 + _height(current->left);
    size_t heightOfRight = 1 + _height(current->right);

    return heightOfLeft > heightOfRight ? heightOfLeft : heightOfRight;
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_parent(NodeType * current, const NodeType *givenNode) const
{
    if(!current || !givenNode) return nullptr;

    if(current->left == givenNode || current->right == givenNode)
        return current;

    NodeType * result = _parent(current->left, givenNode);
    if(!result)
        result = _parent(current->right, givenNode);

    return result;
}

template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_find(NodeType *current, const T & key) const
{
    if(!current) return nullptr;

    if(current->data == key) return current;

    NodeType *result = _find(current->left, key);
    if(!result)
        result = _find(current->right, key);

    return result;
}

template<typename T>
bool BinaryTree<T>::_equal(NodeType *leftRoot, NodeType *rightRoot) const
{
    if(!leftRoot && !rightRoot) return true;
    if(!leftRoot || !rightRoot) return false;

    bool result = (leftRoot == rightRoot)
        && _equal(leftRoot->left, rightRoot->left)
        && _equal(leftRoot->right, rightRoot->right);

    return result;
}

#endif

部分测试代码

/********************************************
 *  Author        : 
 *  Email         : 
 *  Filename      : mainForBinaryTree.cpp
 *  Creation time : 2018-01-03 00:02:05
 *  Last modified : 2018-01-03 01:15:40
 *  Description   : ---
 *******************************************/

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

void test1()
{
    std::cout << "stream creation test:\n";

    BinaryTree<int> *bt = new BinaryTree<int>(-1);
    bt->createBT();

    std::cout << "         levelTraverse(): ";
    bt->levelTraverse();
    std::cout << "\n";

    std::cout << "        zigzagTraverse(): ";
    bt->zigzagTraverse();
    std::cout << "\n";

    std::cout << " preorderTraverse_Iter(): ";
    bt->preorderTraverse_Iter();
    std::cout << "\n";

    std::cout << "  inorderTraverse_Iter(): ";
    bt->inorderTraverse_Iter();
    std::cout << "\n";

    std::cout << "postorderTraverse_Iter(): ";
    bt->postorderTraverse_Iter();
    std::cout << "\n";

    std::cout << "                  size(): ";
    std::cout << bt->size() << std::endl;

    std::cout << "                 hight(): ";
    std::cout << bt->height() << std::endl;

    std::cout << "                  find(): ";
    int key = 5;
    bt->print(bt->find(key));
    std::cout << "\n";
}

void test2()
{
    std::cout << "\nstring creation test:\n";

    BinaryTree<char> *bt = new BinaryTree<char>('#');
    const char * str = "abc##d##e##";
    bt->createBT(str);

    std::cout << "         levelTraverse(): ";
    bt->levelTraverse();
    std::cout << "\n";

    std::cout << "        zigzagTraverse(): ";
    bt->zigzagTraverse();
    std::cout << "\n";

    std::cout << " preorderTraverse_Iter(): ";
    bt->preorderTraverse_Iter();
    std::cout << "\n";

    std::cout << "  inorderTraverse_Iter(): ";
    bt->inorderTraverse_Iter();
    std::cout << "\n";

    std::cout << "postorderTraverse_Iter(): ";
    bt->postorderTraverse_Iter();
    std::cout << "\n";

    std::cout << "                  size(): ";
    std::cout << bt->size() << std::endl;

    std::cout << "                 hight(): ";
    std::cout << bt->height() << std::endl;

    std::cout << "                  find(): ";
    char key = 'e';
    bt->print(bt->find(key));
    std::cout << "\n";
}

int main()
{
    test1();
    test2();
}

测试结果

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值