自建二叉树,及收获的经验

来源:互联网 发布:合并pdf软件 编辑:程序博客网 时间:2024/06/04 18:38

二叉树常用来表示:表达式、文件系统、URL、域名、学院组织、族谱
他们的共同点就是有层次结构

实现:

包含的方法:

插入/删除结点

获取树的基本信息

前序/中序/后序/层次遍历

template<typename value_type>class BinTree {using size_type = unsigned;using calcu_type = int;#ifndef _STACK_#include<stack>#endif // !_STACK_#ifndef _QUEUE_#include<queue>#endif // !_QUEUE_private:class BinNode {public:const bool _voidNode = true;size_type _depth = 0;size_type _size = 1;size_type _height = 0;BinNode* _father = nullptr;BinNode* _leftChild = nullptr;BinNode* _rightChild = nullptr;value_type _value;void _update_size(calcu_type num) {BinNode* now = this->_father;while (now->_father != nullptr) {//非root时now->_size += num;now = now->_father;}now->_size += num;}void _update_height(calcu_type num) {//更新祖先高度BinNode* now = this;BinNode* sib;while (now->_father != nullptr) {//now非rootif (now->_father->_leftChild == now)sib = now->_father->_rightChild;else sib = now->_father->_leftChild;if (now->_height > sib->_height || sib->_voidNode)now->_father->_height += num;now = now->_father;}}void _update_size_and_height(calcu_type num) {_update_size(num);_update_height(num);}public:BinNode(const value_type&val):_value(val), _father(nullptr), _voidNode(false), _size(1){_rightChild = new BinNode();_leftChild = new BinNode();}//rootBinNode(const value_type& val, BinNode* father):_value(val), _father(father), _voidNode(false){_depth = father->_depth + 1;//left voidNode is provided by father_rightChild = new BinNode();}//new childBinNode() {}//voidNode~BinNode() {delete _rightChild;delete _leftChild;}size_type get_height() { return this->_height; }BinNode* insert_left_child(const value_type& val) {BinNode* tmp = new BinNode(val, this);tmp->_leftChild = this->_leftChild;// 传递被替换的空结点this->_leftChild = tmp;this->_leftChild->_update_size_and_height(1);return this->_leftChild;}BinNode* insert_right_child(const value_type& val) {BinNode* tmp = new BinNode(val, this);tmp->_leftChild = this->_rightChild;// 传递被替换的空结点this->_rightChild = tmp;this->_rightChild->_update_size_and_height(1);return this->_rightChild;}};BinNode* root = nullptr;BinNode* _curNode = root;public:BinTree() {}BinTree(const value_type& val) {root = new BinNode(val);_curNode = root;}~BinTree() { delete root; }bool empty() { return root == nullptr; }size_type get_height() { return root->_height; }size_type get_cur_depth() { return _curNode->_depth; }bool is_void_node() { return _curNode->_voidNode; }const value_type& get_cur_value() { return _curNode->_value; }const value_type& insert_as_right_child(const value_type& val) {if (this->empty()) {root = _curNode = new BinNode(val);return val;}else {_curNode = _curNode->insert_right_child(val);return _curNode->_value;}}const value_type& insert_as_left_child(const value_type& val) {if (this->empty()) {root = _curNode = new BinNode(val);return val;}else {_curNode = _curNode->insert_left_child(val);return _curNode->_value;}}template<typename method>void trav_level(method& visit) {if (this->empty())return;BinNode* front = root;std::stack<BinNode*>pointerQueue;pointerQueue.push(front);while (!pointerStack.empty()){front = pointerQueue.pop();visit(front->_value);if (front->_leftChild->_voidNode == false)pointerQueue.push(front->_leftChild);if (front->_rightChild->_voidNode == false)pointerQueue.push(front->_rightChild);}}//层次遍历template<typename method>void trav_pre(method& visit) {if (this->empty())return;BinNode* front = root;std::stack<BinNode*>pointerStack;pointerStack.push(front);while (!pointerStack.empty()){front = pointerStack.pop();visit(front->_value);if (front->_leftChild->_voidNode == false)pointerStack.push(front->_leftChild);if (front->_rightChild->_voidNode == false)pointerStack.push(front->_rightChild);}}//preorder先序遍历template<typename method>void trav_in(method& visit) {if (this->empty())return;BinNode* front = root;std::stack<BinNode*>pointerStack;pointerStack.push(front);while (!pointerStack.empty()){if (front->_leftChild->_voidNode == false)pointerStack.push(front->_leftChild);front = pointerStack.pop();visit(front->_value);if (front->_rightChild->_voidNode == false)pointerStack.push(front->_rightChild);}}//inorder中序遍历template<typename method>void trav_post(method& visit) {if (this->empty())return;BinNode* front = root;std::stack<BinNode*>pointerStack;pointerStack.push(front);while (!pointerStack.empty()){front = pointerStack.pop();visit(front->_value);if (front->_rightChild->_voidNode == false)pointerStack.push(front->_rightChild);if (front->_leftChild->_voidNode == false)pointerStack.push(front->_leftChild);}}//postorder后序遍历value_type& roll_back(size_type times){if (times > _curNode->_depth)return this->back_to_root();else {for (size_type i = 1; i <= times; ++i)_curNode = _curNode->_father;return _curNode->_value;}} //roll back max to root, no excptionvalue_type& back_to_root() {_curNode = root;return _curNode->_value;}value_type& go_to_left_child() {_curNode = _curNode->_leftChild;return _curNode->_value;}value_type& go_to_right_child() {_curNode = _curNode->_rightChild;return _curNode->_value;}void delete_left_tree() {delete _curNode->_leftChild;_cureNode->_leftChild = new BinNode();}void delete_right_tree() {delete _curNode->_leftChild;_cureNode->_rightChild = new BinNode();}};

加入以下代码可用于测试:

class add_note {public:void operator()(std::string& val) {val += " visited!";}}add;int main() {BinTree<std::string>* p;{BinTree<std::string>aTree;p = &aTree;aTree.insert_as_left_child("root");aTree.insert_as_left_child("root's left");aTree.roll_back(1);aTree.insert_as_right_child("root's right");aTree.insert_as_left_child("root's left's left");aTree.trav_level(add);}int a = 0;}

总结:

1.关于 delete
delete 实际是调用对象的析构函数,析构函数结束的瞬间,相当于此对象(this)的堆空间被回收,但析构函数期间可以做其他复杂的操作
2.关于 指针容器
C++容器模板类中保存的是 原对象的复制品(调用拷贝构造函数或移动构造函数)。保存对象指针而不是对象本身,可以节省拷贝构造函数调用次数,建立“管理资源”的容器
3.现版本缺点:
1.不可多线程
2.未处理异常
3.未考虑继承问题
4.未知的栈类坑

原创粉丝点击