二叉树二叉树基本操作通用接口

Posted teternity

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树二叉树基本操作通用接口相关的知识,希望对你有一定的参考价值。

二叉树的基本操作,为 二叉查找(搜索、排序)树、二叉平衡树(AVL树)、红黑树 等提供基础接口。

名称空间:namespace BTO

基础接口如:

  ① 遍历操作:

    递归 和 非递归 版本的 先序、中序、后序 遍历。

    层序遍历。

    接口原型:void xxxTraversal(_Node*& _node, const _Func& _func);

    其中 _Func 为函数对象,接受一个 _Node* 的参数,用于在遍历时作用于各个节点。

  ② find 操作:

    寻找指定键的节点(迭代和非迭代版本)。

    寻找键最大最小值的节点。

    寻找前驱后继。

    获取二叉树的高度。

    接口原型:_Node* xxxfindxxx(_Node*& _node, const _Ty& _key);

    其中 _Ty 为键类型。

  ③ 插入操作:

    接口原型:std::pair<_Node*, bool> insert(_Node*& _node, const _Ty& _key);

    其中 将键为 _Ty 类型的值 _key 添加到节点为 _Node* 类型的根为 _node 的二叉树中。

    返回插入节点的指针和是否成功插入的 bool 值(不存在键值相同的节点,若插入键已经存在,则插入失败返回 pair(nullptr, false) )。

  ④ 复制操作(迭代和非迭代版本):

    接口原型:_Node* xxxCopy(_Node*& _node, _Node* _ret);

    其中 _node 为待复制二叉树的根节点,_ret 必须为 nullptr 且默认为 nullptr,返回新树的根节点 _ret。

  ⑤ 清空操作:

    接口原型:void clear(_Node*& _node);

    清除 _node 为根的二叉树,务必保证 _node 不是子树。

 

测试代码 main.cpp:

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

template<typename _Ty>
struct Node
{
    _Ty key;
    Node* left = nullptr;
    Node* right = nullptr;
    Node* parent = nullptr;
    Node(const _Ty& _key) :key(_key) {}
};

int main()
{
    Node<int>* root = nullptr;
    auto il = { 5,3,7,4,8,1,0,9,2,6 };
    for (auto& x : il) BTO::insert(root, x);

    cout << "先序遍历:" << endl;
    BTO::preorderTraversal(root, [](const Node<int>* _node) { cout << _node->key << " "; });
    cout << endl;
    BTO::iterativePreorderTraversal(root, [](const Node<int>* _node) { cout << _node->key << " "; });
    cout << endl << endl;
    cout << "中序遍历:" << endl;
    BTO::inorderTraversal(root, [](const Node<int>* _node) { cout << _node->key << " "; });
    cout << endl;
    BTO::iterativeInorderTraversal(root, [](const Node<int>* _node) { cout << _node->key << " "; });
    cout << endl << endl;
    cout << "后序遍历:" << endl;
    BTO::postorderTraversal(root, [](const Node<int>* _node) { cout << _node->key << " "; });
    cout << endl;
    BTO::iterativePostorderTraversal(root, [](const Node<int>* _node) { cout << _node->key << " "; });
    cout << endl << endl;
    cout << "层序遍历:" << endl;
    BTO::levelTraversal(root, [](const Node<int>* _node) { cout << _node->key << " "; });
    cout << endl << endl;

    cout << "BTO::find(root, 5)->key:" << endl;
    auto p5 = BTO::find(root, 5);
    if (p5 != nullptr) cout << p5->key << ", " << BTO::iterativeFind(root, 5)->key << endl;
    else cout << "nullptr" << endl;
    cout << "BTO::find(root, 11)->key:" << endl;
    auto p11 = BTO::find(root, 11);
    if (p11 != nullptr) cout << p11->key << ", " << BTO::iterativeFind(root, 11)->key << endl;
    else cout << "nullptr" << endl << endl;

    cout << "BTO::findMaximum(root)->key:" << endl;
    cout << BTO::findMaximum(root)->key << endl;
    cout << "BTO::findMinimum(root)->key:" << endl;
    cout << BTO::findMinimum(root)->key << endl << endl;

    cout << "BTO::findPrecursor(p5)->key:" << endl;
    cout << BTO::findPrecursor(p5)->key << endl;
    cout << "BTO::findSuccessor(p5)->key:" << endl;
    cout << BTO::findSuccessor(p5)->key << endl << endl;

    auto root2 = BTO::copy(root);
    auto root3 = BTO::copy(root);
    cout << "BTO::getLevel(root):" << endl;
    cout << BTO::getLevel(root) << endl;
    cout << "BTO::getLevel(root2):" << endl;
    cout << BTO::getLevel(root2) << endl;
    cout << "BTO::getLevel(root3):" << endl;
    cout << BTO::getLevel(root3) << endl << endl;

    BTO::clear(root);
    BTO::clear(root2);
    BTO::clear(root3);
    return 0;
}

 

头文件 BinaryTreeOperations.h:

#pragma once
#ifndef __BINARY_TREE_OPERATIONS_H__
#define __BINARY_TREE_OPERATIONS_H__


/*
    The node must have members which are named:
        "key"、"left"、"right"、"parent"
*/


#include <stack>
#include <queue>
#include <utility>
namespace BTO
{
    /* Traversal operations */
    // Recursive operations
    template<typename _Node, typename _Func>
    void preorderTraversal(_Node*&, const _Func&);
    template<typename _Node, typename _Func>
    void inorderTraversal(_Node*&, const _Func&);
    template<typename _Node, typename _Func>
    void postorderTraversal(_Node*&, const _Func&);
    // Iterative operations
    template<typename _Node, typename _Func>
    void iterativePreorderTraversal(_Node*&, const _Func&);
    template<typename _Node, typename _Func>
    void iterativeInorderTraversal(_Node*&, const _Func&);
    template<typename _Node, typename _Func>
    void iterativePostorderTraversal(_Node*&, const _Func&);
    // Level traversal
    template<typename _Node, typename _Func>
    void levelTraversal(_Node*&, const _Func&);

    /* Find operations */
    template<typename _Node, typename _Ty>
    _Node* find(_Node*&, const _Ty&);
    template<typename _Node, typename _Ty>
    _Node* iterativeFind(_Node*&, const _Ty&);
    template<typename _Node>
    _Node* findMaximum(_Node*&);
    template<typename _Node>
    _Node* findMinimum(_Node*&);
    template<typename _Node>
    _Node* findPrecursor(_Node*&);
    template<typename _Node>
    _Node* findSuccessor(_Node*&);
    template<typename _Node>
    size_t getLevel(_Node*&);

    /* Inset operation */
    template<typename _Node, typename _Ty>
    std::pair<_Node*, bool> insert(_Node*&, const _Ty&);

    /* Copy operation */
    template<typename _Node>
    _Node* copy(_Node*&, _Node* _ret = nullptr);
    template<typename _Node>
    _Node* iterativeCopy(_Node*&, _Node* _ret = nullptr);

    /* Clear operation */
    template<typename _Node>
    void clear(_Node*&);
}

/* Traversal operations */
template<typename _Node, typename _Func>
void BTO::preorderTraversal(_Node*& _node, const _Func& _func)
{
    if (_node == nullptr) return;
    _func(_node);
    preorderTraversal(_node->left, _func);
    preorderTraversal(_node->right, _func);
}

template<typename _Node, typename _Func>
void BTO::inorderTraversal(_Node*& _node, const _Func& _func)
{
    if (_node == nullptr) return;
    inorderTraversal(_node->left, _func);
    _func(_node);
    inorderTraversal(_node->right, _func);
}
template<typename _Node, typename _Func>
void BTO::postorderTraversal(_Node*& _node, const _Func& _func)
{
    if (_node == nullptr) return;
    postorderTraversal(_node->left, _func);
    postorderTraversal(_node->right, _func);
    _func(_node);
}
template<typename _Node, typename _Func>
void BTO::iterativePreorderTraversal(_Node*& _node, const _Func& _func)
{
    if (_node == nullptr) return;
    std::stack<_Node*> nodePointers;
    _Node* cur = _node;
    while (cur != nullptr || !nodePointers.empty())
    {
        _func(cur);
        nodePointers.push(cur);
        cur = cur->left;
        while (cur == nullptr && !nodePointers.empty())
        {
            cur = nodePointers.top()->right;
            nodePointers.pop();
        }
    }
}
template<typename _Node, typename _Func>
void BTO::iterativeInorderTraversal(_Node*& _node, const _Func& _func)
{
    if (_node == nullptr) return;
    std::stack<_Node*> nodePointers;
    _Node* cur = _node;
    while (cur != nullptr || !nodePointers.empty())
    {
        if (cur->left != nullptr)
        {
            nodePointers.push(cur);
            cur = cur->left;
        }
        else
        {
            _func(cur);
            cur = cur->right;
            while (cur == nullptr && !nodePointers.empty())
            {
                cur = nodePointers.top();
                nodePointers.pop();
                _func(cur);
                cur = cur->right;
            }
        }
    }
}
template<typename _Node, typename _Func>
void BTO::iterativePostorderTraversal(_Node*& _node, const _Func& _func)
{
    if (_node == nullptr) return;
    std::stack<_Node*> nodePointers;
    nodePointers.push(_node);
    _Node* last = nullptr;
    _Node* cur = nullptr;
    while (!nodePointers.empty())
    {
        cur = nodePointers.top();
        if ((cur->left == nullptr && cur->right == nullptr) || last != nullptr && (last == cur->left || last == cur->right))
        {
            _func(cur);
            nodePointers.pop();
            last = cur;
        }
        else
        {
            if (cur->right != nullptr) nodePointers.push(cur->right);
            if (cur->left != nullptr) nodePointers.push(cur->left);
        }
    }
}
template<typename _Node, typename _Func>
void BTO::levelTraversal(_Node*& _node, const _Func& _func)
{
    if (_node == nullptr) return;
    std::queue<_Node*> nodePointers;
    nodePointers.push(_node);
    _Node* cur = nullptr;
    while (!nodePointers.empty())
    {
        cur = nodePointers.front();
        _func(cur);
        if (cur->left != nullptr) nodePointers.push(cur->left);
        if (cur->right != nullptr) nodePointers.push(cur->right);
        nodePointers.pop();
    }
}

/* Find operations */
template<typename _Node, typename _Ty>
_Node* BTO::find(_Node*& _node, const _Ty& _key)
{
    if (_node == nullptr || _key == _node->key) return _node;
    if (_key < _key) return find(_node->left, _key);
    else return find(_node->right, _key);
}
template<typename _Node, typename _Ty>
_Node* BTO::iterativeFind(_Node*& _node, const _Ty& _key)
{
    _Node* cur = _node;
    while (cur != nullptr && cur->key != _key)
    {
        if (_key < cur->key) cur = cur->left;
        else cur = cur->right;
    }
    return cur;
}
template<typename _Node>
_Node* BTO::findMaximum(_Node*& _node)
{
    _Node* cur = _node;
    if (cur == nullptr) return cur;
    while (cur->right != nullptr)
        cur = cur->right;
    return cur;
}
template<typename _Node>
_Node* BTO::findMinimum(_Node*& _node)
{
    _Node* cur = _node;
    if (cur == nullptr) return cur;
    while (cur->left != nullptr)
        cur = cur->left;
    return cur;
}
template<typename _Node>
_Node* BTO::findPrecursor(_Node*& _node)
{
    _Node* cur = _node;
    if (cur->left != nullptr) return findMaximum(cur->left);
    _Node* par = cur->parent;
    while ((par != nullptr) && (cur == par->left))
    {
        cur = par;
        par = par->parent;
    }
    return par;
}
template<typename _Node>
_Node* BTO::findSuccessor(_Node*& _node)
{
    _Node* cur = _node;
    if (cur->right != nullptr) return findMinimum(cur->right);
    _Node* par = cur->parent;
    while ((par != nullptr) && (cur == par->right))
    {
        cur = par;
        par = par->parent;
    }
    return par;
}
template<typename _Node>
size_t BTO::getLevel(_Node*& _node)
{
    if (_node == nullptr) 0;
    size_t n = 0;
    std::queue<_Node*> nodePointers;
    nodePointers.push(_node);
    while (!nodePointers.empty())
    {
        _Node* levelBegin = nodePointers.front();
        _Node* levelEnd = nodePointers.back();
        _Node* cur = levelBegin;
        while (true)
        {
            if (cur->left != nullptr) nodePointers.push(cur->left);
            if (cur->right != nullptr) nodePointers.push(cur->right);
            if (cur == levelEnd)
                break;
            nodePointers.pop();
            cur = nodePointers.front();
        }
        nodePointers.pop();
        ++n;
    }
    return n;
}

/* Inset operation */
template<typename _Node, typename _Ty>
std::pair<_Node*, bool> BTO::insert(_Node*& _node, const _Ty& _key)
{
    std::pair<_Node*, bool> ret(nullptr, true);
    if (_node == nullptr)
    {
        _node = new _Node(_key);
        ret.first = _node;
        return ret;
    }
    _Node* cur = _node;
    while (true)
    {
        if (_key == cur->key)
        {
            ret.second = false;
            return ret;
        }
        else if (_key < cur->key && cur->left != nullptr) cur = cur->left;
        else if (_key > cur->key&& cur->right != nullptr) cur = cur->right;
        else break;
    }
    _Node* newNode = new _Node(_key);
    if (_key < cur->key) cur->left = newNode;
    else cur->right = newNode;
    newNode->parent = cur;
    ret.first = newNode;
    newNode = nullptr;
    return ret;
}

/* Copy operations */
template<typename _Node>
_Node* BTO::copy(_Node*& _node, _Node* _ret)
{
    if (_ret != nullptr) return nullptr;
    preorderTraversal(_node, [&_ret](_Node*& _no) { insert(_ret, _no->key); });
    return _ret;
}
template<typename _Node>
_Node* BTO::iterativeCopy(_Node*& _node, _Node* _ret)
{
    if (_ret != nullptr) return nullptr;
    iterativePreorderTraversal(_node, [&_ret](_Node*& _no) { insert(_ret, _no->key); });
    return _ret;
}

/* Clear operation */
template<typename _Node>
void BTO::clear(_Node*& _node)
{
    if (_node == nullptr) return;
    clear(_node->left);
    clear(_node->right);
    delete _node;
    _node = nullptr;
}


#endif // !__BINARY_TREE_OPERATIONS_H__

 

以上是关于二叉树二叉树基本操作通用接口的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法(周鹏-未出版)-第六章 树-6.3 二叉树基本操作的实现

二叉树的应用--二叉树排序树基本操作

数据结构 二叉树

数据机构实验报告-实验三 二叉树基本操作的实现

转 二叉树之Java实现二叉树基本操作

二叉树基本操作方法的递归调用实现