封装二叉树的基本操作,为 二叉查找(搜索、排序)树,二叉平衡树(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__