二叉樹的基本操作,為 二叉查找(搜索、排序)樹、二叉平衡樹(AVL樹)、紅黑樹 等提供基礎介面。 名稱空間:namespace BTO 基礎介面如: ① 遍歷操作: 遞歸 和 非遞歸 版本的 先序、中序、後序 遍歷。 層序遍歷。 介面原型:void xxxTraversal(_Node*& _nod ...
封裝二叉樹的基本操作,為 二叉查找(搜索、排序)樹,二叉平衡樹(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) return 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__