1 // preorder、postorder、inorderのそれぞれの探索を利用できる、
3 // 汎用二分木では、以下の処理を行うことができます。
4 // insert - 特定のNodeに対する値の設定
5 // set_left - 左の葉に値を追加する。
6 // set_right - 右の葉に値を追加する。
7 // inorder_begin/end - 通りがけ順に探索するiteratorの開始・終了点を
9 // preorder_begin/end - 行きがけ順に探索するiteratorの開始・終了点を
11 // postorder_begin/end - 帰り掛け順に探索するiteratorの開始・終了点を
14 // postorder/preorder/inorderは、それぞれテンプレート引数で
15 // 指定することができます。デフォルトはinorderが指定されたことと同一です。
16 #ifndef _UTAKATA_LIB_BINARY_TREE_H_
17 #define _UTAKATA_LIB_BINARY_TREE_H_
20 namespace binary_tree_detail {
22 // 内部でleafなどとして扱われるnode構造体です。この構造体公開はされますが、
26 node() : parent_(0), left_(0), right_(0),
27 next_sibling_(0), prev_sibling_(0), data_() {}
28 node(const T& data) : parent_(0), left_(0), right_(0),
29 next_sibling_(0), prev_sibling_(0),
34 // 同じ親に接続されている前後のnodeを指します。
35 // ただし、二分木の場合、左ノードの場合はnext_sibling_に右ノードが、
36 // 右ノードの場合はpref_sibling_に左ノードが設定され、
37 // それぞれprev/nextは0が設定されます。
38 node<T>* next_sibling_;
39 node<T>* prev_sibling_;
45 // 渡されたT型のポインタから、次に進むべきデータを判別するための
47 // pre_orderは、根・左部分木・右部分木の順にtreeへのアクセスを行います。
48 // 渡された段階で、すでに根にアクセスされているため、この場合は
50 // また、一つ前にアクセスしたデータを記憶しており、一つ前にアクセスした
51 // データが、渡されたデータのどの位置に該当するのかをチェックし、
55 // 渡されたtargetに対して、次のデータに行くかどうかをチェックします。
56 // left、rightの両方が存在しない場合、parent_のnext_siblingが存在するか
58 bool has_next(const node<T>* target) const {
59 const node<T>* now_target = target;
65 if (target->left_ || target->right_) {
69 while (now_target->next_sibling_ == 0) {
70 if (!now_target->parent_) {
73 now_target = now_target->parent_;
78 // 渡されたtargetから、次に進むべきデータを返します。
79 // has_nextがfalseを返却する場合、0が返却されます。
80 node<T>* next(node<T>* target) {
83 } else if (target->right_) {
84 return target->right_;
87 node<T>* now_target = target;
88 while (now_target->next_sibling_ == 0) {
89 now_target = now_target->parent_;
90 if (now_target == 0) {
94 return now_target->next_sibling_;
98 } // end of namespace binary_tree
100 // 汎用的な二分木テンプレートを提供します。
101 // テンプレート引数は、第一引数が利用する型、第二引数が、二分木の
103 // 二分木の探索方法は、in_order、pre_order、post_orderが用意されて
105 // デフォルトで用意されている探索方法については、すべてakebono::binary_tree_detail
107 // 内部ノードへのアクセスは可能ですが、get_*、has_*による間接的アクセスが
109 template <typename T,
110 template<typename S> class Traverse =
111 akebono::binary_tree_detail::pre_order>
115 // 内部のnodeを利用し、また渡されたtraverserに基づいて、nodeの探索を行います。
118 // コピーコンストラクタ、及びデフォルトコンストラクタです。
119 iterator() : node_(0), traverser_() {}
120 iterator(const iterator& it) : node_(it.node_),
121 traverser_(it.traverser_) {}
122 explicit iterator(binary_tree_detail::node<T>* convert) : node_(convert), traverser_() {}
126 // 渡されたiteratorとの比較を行います。内部で保持しているnode_が
127 // 同一位置を指していることが条件となります。
128 bool operator==(const iterator& it) const {return node_ == it.node_;}
129 bool operator!=(const iterator& it) const {return !(*this == it);}
131 // 現在指しているnode内のデータへアクセスします。
132 // node内部ではTとしてのみ保持しているため、変則的にしています。
133 const T& operator*() const {return node_->data_;}
134 const T* operator->() const {return &(node_->data_);}
135 T& operator*() {return node_->data_;}
136 T* operator->() {return &(node_->data_);}
138 // 現在指しているnode_を次の要素を指すように変更します。この際、
139 // Traverseで指定されたTraverserを利用します。
140 // Traverse::has_nextは、渡されたnode_のアクセスを行うかどうかを
141 // 表し、Traverse::nextは、次にアクセスすべきnode_を返します。
142 iterator& operator++() {
143 node_ = traverser_.next(node_);
147 iterator operator++(int) {
149 node_ = traverser_.next(node_);
153 // 各データを格納しているnodeです。node内では、単純にデータを保持
154 // しているため、取得したポインタを操作することは許可されません。
155 binary_tree_detail::node<T>* node_;
157 // operator++によって、二分木の探索を行うためのtraverserです。
158 Traverse<T> traverser_;
161 // 番兵として機能するend_を設定します。
162 binary_tree() : root_(new binary_tree_detail::node<T>()),
163 end_(new binary_tree_detail::node<T>()) {
167 root_->next_sibling_ = end_;
168 root_->prev_sibling_ = 0;
173 end_->prev_sibling_ = root_;
174 end_->next_sibling_ = 0;
177 virtual ~binary_tree() {
178 if (root_) {delete root_;}
179 if (end_) {delete end_;}
182 // rootを指すiteratorを作成して返します。
184 return iterator(root_);
187 // end_を指すiteratorを返却します。
189 return iterator(end_);
192 // 渡されたiteratorの左側に新規に葉を作成し、dataを設定します。
193 // 正常に終了した場合、新規に作成された葉を指すiteratorが
195 // 正常に終了しなかった場合、end()で返されるiteratorと同一のiteratorが返されます。
196 iterator set_left(const iterator& target,
198 if (target == end()) {
202 binary_tree_detail::node<T>* target_node = target.node_;
203 target_node->left_ = new binary_tree_detail::node<T>(data);
205 target_node->left_->parent_ = target_node;
206 target_node->left_->next_sibling_ = target_node->right_;
208 if (target_node->right_) {
209 target_node->right_->prev_sibling_ = target_node->left_;
211 iterator ret(target_node->left_);
215 // 渡されたiteratorの右側に新規に葉を作成し、dataを設定します。
216 // 正常に終了した場合、新規に作成された葉を指すiteratorが
218 iterator set_right(const iterator& target,
220 if (target == end()) {
224 binary_tree_detail::node<T>* target_node = target.node_;
225 target_node->right_ = new binary_tree_detail::node<T>(data);
227 target_node->right_->parent_ = target_node;
228 target_node->right_->prev_sibling_ = target_node->left_;
230 if (target_node->left_) {
231 target_node->left_->next_sibling_ = target_node->right_;
233 iterator ret(target_node->right_);
239 // 二分木のルートとして設定されます。デフォルトではend_を指しています。
240 // root_がend_を指している場合、binary_tree::empty()がtrueを返します。
241 binary_tree_detail::node<T>* root_;
243 // 常に二分木の末尾として設定されます。ここでの二分木の末尾とは、
245 binary_tree_detail::node<T>* end_;
247 } // end of namespace akebono
249 #endif /* _UTAKATA_LIB_BINARY_TREE_H_ */