二叉树(1)二叉树的基本操作

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

定义的结构体里面必须至少包含以下名称的成员:

  "key"、"left"、"right"、"parent"。

封装文件名:BinaryTreeOperations.h;名称空间:BTO

基础接口如下:

  一、遍历操作:

    ① 先序、中序、后序遍历递归版:

      void preorderTraversal(_Node*, const _Func&);

      void inorderTraversal(_Node*, const _Func&);

      void postorderTraversal(_Node*, const _Func&);

    ② 先序、中序、后序遍历非递归版:

      void iterativePreorderTraversal(_Node*, const _Func&);

      void iterativeInorderTraversal(_Node*, const _Func&);

      void iterativePostorderTraversal(_Node*, const _Func&);

    ③ 层序遍历:

      oid levelTraversal(_Node*, const _Func&);

     说明:_Func 是函数对象,接受一个 _Node* 参数,更广泛的支持对数据的操作。

  二、查找操作:

    ① 查找指定键值的节点 迭代和非迭代版:

      _Node* find(_Node*, const _Ty&);

      _Node* iterativeFind(_Node*, const _Ty&);

    ② 查找最大最小键值的节点:

      _Node* findMaximum(_Node*);

      _Node* findMinimum(_Node*);

    ③ 获取二叉树的深度(层数):

       size_t getLevel(_Node*);

  三、插入操作:

    std::pair<_Node*, bool> insert(_Node*&, const _Ty&);

    说明:该操作不允许插入已经存在的键值,用 std:pair 返回插入情况:成功则返回 指向插入节点的指针 和 true,失败则返回 nullptr 和 false。

  四、拷贝操作 迭代和非迭代版:

    _Node* copy(_Node*, _Node* _ret = nullptr);

    _Node* iterativeCopy(_Node*, _Node* _ret = nullptr);

    说明:第一个参数是待拷贝的二叉树、用 ret 返回拷贝后的根节点,调用时 ret 必须指向 nullptr。

  五、清空操作 递归:

    void clear(_Node*&);

  六、单旋转操作:

    ① 左旋:_Node* leftRotate(_Node*);

    ② 右旋:_Node* rightRotate(_Node*);

    说明:伸展树、AVL 树、红黑树 等都需要使用旋转功能,因此提供旋转操作。

      返回旋转后子树的根节点,以便 AVL 树调整平衡因子 和 红黑树变色 等需求。

测试代码 main.cpp:

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

using std::cout;
using std::endl;

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 << "preorderTraversal:" << 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 << "inorderTraversal:" << 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 << "postorderTraversal:" << 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 << "levelTraversal:" << 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;

    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>
    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*&);

    /* Rotate operation */
    template<typename _Node>
    _Node* leftRotate(_Node*);
    template<typename _Node>
    _Node* rightRotate(_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 < _node->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>
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 operation */
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;
}

/* Rotate operation */
template<typename _Node>
_Node* BTO::leftRotate(_Node* _node)
{
    _Node* rightNode = _node->right;
    if (_node->parent != nullptr)
    {
        if (_node->parent->right == _node) _node->parent->right = rightNode;
        else _node->parent->left = rightNode;
    }
    rightNode->parent = _node->parent;
    _node->right = rightNode->left;
    if (rightNode->left != nullptr) rightNode->left->parent = _node;
    _node->parent = rightNode;
    rightNode->left = _node;
    return rightNode;
}
template<typename _Node>
_Node* BTO::rightRotate(_Node* _node)
{
    _Node* leftNode = _node->left;
    if (_node->parent != nullptr)
    {
        if (_node->parent->left == _node) _node->parent->left = leftNode;
        else _node->parent->right = leftNode;
    }
    leftNode->parent = _node->parent;
    _node->left = leftNode->right;
    if (leftNode->right != nullptr) leftNode->right->parent = _node;
    _node->parent = leftNode;
    leftNode->right = _node;
    return leftNode;
}


#endif // !__BINARY_TREE_OPERATIONS_H__

猜你喜欢

转载自www.cnblogs.com/teternity/p/BinaryTreeOperations.html