接着上一篇文章,下面给出 g++ 4.6.3 调试通过的通用二叉树程序的C++-0x源代码。由于Visual Studio和g++对模板的写法要求不完全一致,如果使用Visual Studio编译运行,可能需要对代码做一些小改动。使用g++编译运行时,请把本文中两个源文件以及上一篇文章中的 data_def.h 源文件拷贝到同一个文件夹中,然后使用这个命令行:
g++ -std=c++0x -O2 -obinary_tree binary_tree.cpp
从最后的main()函数以及所附的截图中可以清楚地看出,这个二叉树算法完全无视数据差异,同样的语法可以作用在两个完全不同的数据类型上。
这个是头文件。
// // FILE: binary_tree.h, this is the header file for binary tree structure and algorithms. // // Author: DGU, email: gdyxgzy@hotmail.com // If you would like to use whole or part of this code, or forward it to some other post, // please keep above header and send an email to my inbox. // // Note that I only implemented some methods, yet it should be easy to implement other methods(like finding the least-common-ancestor, etc.) // #ifndef ALGO_TREE_HEADER #define ALGO_TREE_HEADER #include <vector> #include <string> #include <exception> #include <stdexcept> #include "data_def.h" template<class T> class BinaryTree { public: typedef typename T::key_type key_type; typedef typename T::data_type data_type; struct Node { T data; Node* left; Node* right; Node() : data(T()), left(nullptr), right(nullptr) {}; Node(const T& d) : data(d), left(nullptr), right(nullptr) {}; explicit Node(const key_type& k, const data_type& d) : data(k, d), left(nullptr), right(nullptr) {}; const key_type GetKey(void) const { return data.get_key(); }; const data_type GetData(void) const { return data.get_data(); }; void SetData(data_type d) { data.set_data(d); }; }; class BinaryTreeException : public std::runtime_error { public: BinaryTreeException(const std::string& msg) : std::runtime_error(msg) {}; }; BinaryTree() { m_root = nullptr; }; BinaryTree(const std::vector<T>& pre_seq, const std::vector<T>& in_seq) { m_root = build_tree(pre_seq, in_seq); }; virtual ~BinaryTree() { kill_tree(m_root); m_root=NULL; }; const Node* GetRoot(void) const { return m_root; }; void PreOrderRecursive(const Node* root) const; void InOrderRecursive(const Node* root) const; void PostOrderRecursive(const Node* root) const; const std::vector<data_type> InOrderNoneRecursive(void) const; const std::vector<data_type> BreadthTraversal(void) const; protected: Node* build_tree(const std::vector<T>& pre_seq, const std::vector<T>& in_seq); void kill_tree(Node*& root); private: Node* m_root; }; /* // You could derive some sub-classes from this basic BinaryTree class template<class T> class BinarySearchTree : public BinaryTree<T> { }; template<class T> class RedBlackTree : public BinaryTree<T> { }; */ #endif //------------------- END OF THIS FILE ----------------//
这个是类的实现以及主程序。
// // FILE: binary_tree.cpp // // Author: DGU, email: gdyxgzy@hotmail.com // If you would like to use whole or part of this code, or forward it to some other site, // please keep this header, and send an email to my inbox. // #include <iostream> #include <sstream> #include <stack> #include <queue> #include <algorithm> #include "binary_tree.h" using namespace std; // build a tree from input pre-order and in-order traversal sequences, assume that all node keys // are Unique, otherwise we cannot locate the root node. And, of course, the 2 sequences‘s length must be equal template <class T> typename BinaryTree<T>::Node* BinaryTree<T>::build_tree(const vector<T>& pre_order_seq, const vector<T>& in_order_seq) { int N=pre_order_seq.size(); if(in_order_seq.size() != N) throw BinaryTreeException(string("sequence‘s length not equal")); if(N==0) return nullptr; T root_val = pre_order_seq[0]; if(N==1) { Node* root = new Node(root_val); if(root==nullptr) throw BinaryTreeException(string("bad memory allocation")); return root; } // find the root in the in-order sequence, before it is the left child, after it is the right child typename vector<T>::const_iterator root_pos = std::find(in_order_seq.begin(), in_order_seq.end(), root_val); // get the in-order sequence of left and right child respectively. vector<T> left_inorder, right_inorder; std::copy(in_order_seq.begin(), root_pos, back_inserter(left_inorder)); std::copy(++root_pos, in_order_seq.end(), back_inserter(right_inorder)); // get the pre-order sequence of left and right child respectively vector<T> left_preorder, right_preorder; std::copy(pre_order_seq.begin()+1, pre_order_seq.begin()+1+left_inorder.size(), back_inserter(left_preorder)); std::copy(pre_order_seq.begin()+1+left_inorder.size(), pre_order_seq.end(), back_inserter(right_preorder)); if( left_inorder.size()!=left_preorder.size() || right_inorder.size()!=right_preorder.size() ) throw BinaryTreeException(string("sub-sequence‘s length does not match")); Node* left_child = build_tree(left_preorder, left_inorder); Node* right_child = build_tree(right_preorder, right_inorder); Node* root = new Node(root_val); if(root == nullptr) throw BinaryTreeException(string("bad memory allocation")); root->left = left_child; root->right = right_child; return root; } template<class T> void BinaryTree<T>::kill_tree(Node*& root) { if(root) { kill_tree(root->left); kill_tree(root->right); delete root; root = NULL; } } template<class T> void BinaryTree<T>::PreOrderRecursive(const typename BinaryTree<T>::Node* root) const { if(root) { cout<<‘|‘<<root->GetData()<<"| "; //result.push_back(root->GetData()); PreOrderRecursive(root->left); PreOrderRecursive(root->right); } } template<class T> void BinaryTree<T>::InOrderRecursive(const typename BinaryTree<T>::Node* root) const { if(root) { InOrderRecursive(root->left); cout<<‘|‘<<root->GetData()<<"| "; InOrderRecursive(root->right); } } template<class T> void BinaryTree<T>::PostOrderRecursive(const typename BinaryTree<T>::Node* root) const { if(root) { PostOrderRecursive(root->left); PostOrderRecursive(root->right); cout<<‘|‘<<root->GetData()<<"| "; } } template<class T> const vector<typename BinaryTree<T>::data_type> BinaryTree<T>::InOrderNoneRecursive(void) const { vector<data_type> result; Node* root = m_root; if(root) { stack<Node*>stk; while(root || !stk.empty()) { if(root) { stk.push(root); root = root->left; } else { root = stk.top(); stk.pop(); result.push_back(root->GetData()); root = root->right; } } } return result; } template<class T> const vector<typename BinaryTree<T>::data_type> BinaryTree<T>::BreadthTraversal(void) const { vector<data_type> result; queue<Node*> q; q.push(m_root); while(!q.empty()) { Node* root = q.front(); q.pop(); if(root) { result.push_back(root->GetData()); if(root->left != nullptr) q.push(root->left); if(root->right != nullptr) q.push(root->right); } } return result; } // This template function is used to extract data from string inputs template<class T> vector<T> get_seq(const string& seq_str) { vector<T> seq; if(seq_str.length() <= 0) return seq; istringstream isstr(seq_str);//(string(seq_str)); !!! T t; while(isstr>>t) seq.push_back(t); return seq; } int main() { cout << "***---------------- binary tree operations for DataStruct1 ----------------***" << endl; const char *pre_key_str = "1 2 4 5 7 10 3 6 8 9"; const char *in_key_str = "4 2 7 10 5 1 3 8 6 9"; const char *pre_data_str = "aaa bbb ddd eee ggg jjj ccc fff hhh iii"; const char *in_data_str = "ddd bbb ggg jjj eee aaa ccc hhh fff iii"; vector<typename BinaryTree<DataStruct1>::key_type> pre_key_seq = get_seq<typename BinaryTree<DataStruct1>::key_type>(string(pre_key_str)); vector<typename BinaryTree<DataStruct1>::key_type> in_key_seq = get_seq<typename BinaryTree<DataStruct1>::key_type>(string(in_key_str)); vector<typename BinaryTree<DataStruct1>::data_type> pre_data_seq = get_seq<typename BinaryTree<DataStruct1>::data_type>(string(pre_data_str)); vector<typename BinaryTree<DataStruct1>::data_type> in_data_seq = get_seq<typename BinaryTree<DataStruct1>::data_type>(string(in_data_str)); vector<DataStruct1> pre_seq; for(unsigned int i=0; i<pre_key_seq.size(); ++i) pre_seq.push_back(DataStruct1(pre_key_seq[i], pre_data_seq[i])); vector<DataStruct1> in_seq; for(unsigned int i=0; i<in_key_seq.size(); ++i) in_seq.push_back(DataStruct1(in_key_seq[i], in_data_seq[i])); BinaryTree<DataStruct1> bt1(pre_seq, in_seq); cout << "The in-order sequence is: "; bt1.InOrderRecursive(bt1.GetRoot()); cout << endl << endl; cout << "The pre-order sequence is: "; bt1.PreOrderRecursive(bt1.GetRoot()); cout << endl << endl; cout << "The post-order sequence is: "; bt1.PostOrderRecursive(bt1.GetRoot()); cout << endl << endl; vector<typename BinaryTree<DataStruct1>::data_type> breadth_seq = bt1.BreadthTraversal(); cout << "The breadth traversal sequence is: "; for(auto x:breadth_seq) cout << "|" << x << "| "; cout << endl; cout << "***---------------- binary tree operations for DataStruct2 ----------------***" << endl; const char *pre_str = "1.1 2.2 4.4 5.5 7.7 10.10 3.3 6.6 8.8 9.9"; const char *in_str = "4.4 2.2 7.7 10.10 5.5 1.1 3.3 8.8 6.6 9.9"; vector<double> pre_dbl_seq = get_seq<double>(string(pre_str)); vector<double> in_dbl_seq = get_seq<double>(string(in_str)); vector<DataStruct2> pre_seq2; for(auto x:pre_dbl_seq) pre_seq2.push_back(DataStruct2(x)); vector<DataStruct2> in_seq2; for(auto x:in_dbl_seq) in_seq2.push_back(DataStruct2(x)); BinaryTree<DataStruct2> bt2(pre_seq2, in_seq2); vector<typename BinaryTree<DataStruct2>::data_type> none_recur_in_seq = bt2.InOrderNoneRecursive(); cout << "The in-order sequence is: "; for(auto x:none_recur_in_seq) cout << "|" << x << "| "; cout << endl; return 0; }
下面是程序运行的截图:
Object Oriented Design -- Data and Algorithm Separation (2),布布扣,bubuko.com
Object Oriented Design -- Data and Algorithm Separation (2)
原文:http://blog.csdn.net/erdangjiade/article/details/22896109