Some time ago, several people on the forum warmly discussed the two-forked tree as iterator. Some people have written to some C celebrity celebrities, which is very professional.
Honestly, I saw this topic at the time, I feel a bit boring, why? Because the binary tree is a binary tree, its structure is: left son, right son, parent node, etc.
The structure of the item is a linear front drive, followed.
Although the two are not between the wind, there is no way, but it should also be independent of each other.
To make a two-forked tree is not unable, as long as a traversal rule is defined, it is entirely possible to access the binary tree in the way of Iterator.
However, this may be like a STL can do Windows Programming, but STL and Windows Programming are independent of each other. No one needs to rely on who. You have to join the Windows SDK in STL, then say: because Windows Programming is very common, so in order to facilitate the user, I add HWND to STL, and I will mess.
Coupled the Iterator and the binary tree to consider, in my opinion, it is a clear design problem. It is unpredictable to complicate simple things. Although it can be done, the code reuse and structures have problems.
Ok, the problem is taking it. Here should be said that I think the right practice:
1. The binary tree is a binary tree, and the function of the old man is realized. Don't consider Iterator.
2. If it is considered to require iterator, such as pre-sequence, order, and back. Don't worry. You can do an adapter of a binary tree-based iTerator. This Adapter is independent of any binary tree. It is only just put the binary tree into linearly accessible Iterator.
This adapter defines the interface of a binary tree. Then just map any objects that meet this interface into iterator.
3. How to use this item's Adapter for a binary tree?
Put this binary tree first mapped to the interface required by this Adapter. Then, put the Adapter on the binary tree, iterator is coming out. This Iterator library is like a universal converter, one plugging on any binary tree, it will.
The advantage of this structure is that Iterator does not rely on the implementation of the binary tree, and the binary tree does not rely on Iterator. A binary tree can be achieved with any suitable Adapter. An Adapter can also be used for any one of the binary trees.
Below is the code of the C Bidirectional Iterator Adapter I just debugged. It can be implemented in any binary tree (of course, you have to write an adapter to map the binary tree to my binaryal interface, don't tell me, you don't know how to do it)
Namespace Trit {/ *
The interface of the binary tree is like this: template
This is the generated Iterator interface: template protocol itrator {operator bool (); node_ptr deref (); self next (); self prev ();} * /
template class Iterator {protected: typedef Iterator It; public:! NODE_PTR deref () const {return node;} operator bool () const {return node = NODE_PTR (0);} Iterator (NODE_PTR const n : Node (n) {} friend bool operator == (const it & a, const it& b) {return a.deref () == b.deref ();} Friend Bool Operator! = (Const IT & A, Const IT & b) {return! (a == b);} it & operator = (const it & other) {this-> node = other.Node; return * this;} it end () {return node_ptr (0);} static node_ptr GETROOT (Node_Ptr Node); Node_Ptr TMP (RET-> getParent ()); for (; tmp! = node_ptr (0); RET = TMP, TMP = RET-> getParent ()); Return Ret } Static node_ptr getleftmost (node_ptr node) {node_ptr return (Node_ptr TMP (RET-> getleft ()); for (;! Isnull (tmp); RET = TMP, TMP = RET-> Getleft ()); Return ret;} static node_ptr getleftdeep (node_ptr node) {node_ptr return (node); for (;;) {node_ptr TMPL (Ret-> getleft (); if (isnull (TMPL)) {node_ptr TMPR (Ret-> GetRight ()); IF (isnull (TMPR)) {Return Ret; } Else {ret = tmpr;}} else {ret = tmpl;}}} static bool isNull (NODE_PTR ptr) {return ptr == NODE_PTR (0);} private: NODE_PTR node;}; template class Preorder ;
Template Class Postorder; Template class inorder;
Template class preorder / * supports iterator * /: public iterator {
Typedef preorder self; public: self next () const {return goleft (deref ());} self prev () const {typef revtree adapter; adapter ket (deref ()); PostOrder IT (rt); Return Self (it.next (). Deref (). getadaptee ();} Self Begin () const {return self (Deref ()));} private: Static Self Ret (Node_ptr ME, Node_ptr from) {if (ISNULL (me)) {return self (node_ptr (0));} else if (from == me-> getleft ()) {return Goright (me);} else {return Goparent (ME) }} Static self goeft (node_ptr const node) {node-> getleft ()); if (isnull (left)) {Return Goright (Node);} else {return self (left);}} static Self goRight (NODE_PTR const node) {NODE_PTR const right (node-> getRight ()); if (isNull (right)) {return goParent (node);} else {return Self (right);}} static Self goParent (NODE_PTR Const node) {return RET (Node-> getParent (), node);} public: preorder (node_ptr const n): it (n) {} self & operator = (const it!) {return (self &) iper (self) ip :: operator = (other }};
template class Inorder: public Iterator {typedef Inorder Self; public: Self next () const {return goRight (deref ());} Self prev () const {typedef RevTree Adapter Adapter RT (Deref ()); inorder IT (RT); it.next (). Deref (). Getadaptee ();} self begin () const {return self (GetleftMost (Deref (Deref) )))));} Private: static self return {if (ISNULL (me)) {return self (node_ptr (0));} else if (me-> getleft () == from ) {RETURN SELF (ME); else {returnoment (me);}}
Static self goright (node_ptr const node) {node_ptr const right (node-> getright ()); if (isnull (right)) {returnoment (node);} else {return self (GetleftMost (right));}} static Self goparent (node-> getparent ();} public: inorder (node_ptr const n): IT (n) {} self & operator = IT :: Operator = (other);}}; template class postorder: public itrator {typef postorder self; public: self next () {return goparent (deref ());} SELF Prev () {typedef revevtree Adapter; Adapter RT (deref ()); Preorder It (rt); it.next (). Deref (). getadaptee ());} Self Begin ) {RETURN SELF (deref ()));} Static Self Ret (Node_Ptr Const Me, Node_Ptr Const from) {if (ISNULL (ME)) {Return Self (Node_ptr (0));} if (me-> Getleft () == from) {Return Goright (me);} else {return self (me);}} private: static self goright (node_ptr const node) {node_ptr const right (node-> getrig HT ()); ISNULL (Right)) {Return Self (Node);} else {return self (GetleFTeep (Right));}} static self goparent (node_ptr const node) {Return Ret (node-> getParent) ), node);} public: postorder (node_ptr const n): IT (n) {} self & operator = (convert it&) {return (self &) iper = (})
}
template class RevTree / * supports Tree * / {typedef RevTree Self; public: RevTree (NODE_PTR const t): tr (t) {} Self getLeft () const {return Self (tr- > getright ());} self getright () const {return self (tr-> getleft ());} self getparent () const {return self (tr-> getParent ());} const self * operator -> Const {Return this;} BOOL Operator == (const self) const {return this-> tr == b.tr;} BOOL OPERATOR == (const node_ptr b) {Return this-> Tr == b;} Friend Bool Operator == (Const Node_ptr A, Const Self & B) {RETURN A == B.tr;} Self & Operator = (const self & =) {TR = other.tr; return * this;}
Node_ptr getadaptee () const {return tr;} private: Node_ptr Tr;}
}
Here is the test code because the focus here is not how to implement a binary tree, which uses a very simple binary tree. Just to indicate how you give an Iterator service for an arbitrary binary tree.
#include #include "trit.h" using namespace trit; class TreeCons {public: TreeCons * getLeft () const {return left;} TreeCons * getRight () const {return right;} TreeCons * getParent () Const {returnent;} void setparent (Treecons * p) {this-> parent = p;} const char * get () {return val;} Treecons (Treecons * L, Treecons * r, const char * v): Left (L), Right (R), Parent (0), VAL (V) {} private: Treecons * Left; Treecons * Right; Treecons * Parent; const char * val;}; typedef preorder pre; typef Inorder in; typedef postorder Post;
Template void printit (it; it; it = it.next ()) {cout << it.deref () -> get ();} cout << endl;} template Void PrintRev (IT IT) {for (; it; it = it.prev ()) {cout << it.deref () -> get ();} cout << endl;} int main () {Treecons * D = new Treecons (0, 0, "d"); treecons * e = new Treecons (0, 0, "e"); treecons * b = new Treecons (D, E, "B"); D-> SetParent (b); e-> setParent (b); treecons * f = new Treecons (0, 0, "f"); treecons * c = new Treecons (0, f, "c"); f-> setParent ( c); treecons * a = new Treecons (B, C, "a"); b-> setParent (a); c-> setparent (a); printit (pre (a)); Printit (PRE (C). BeGin ()); Printit (in (a)); Printit (in (a)); Printit (POST (a)); Printit (Post (a) .begin ()); Printrev (POST (a )); PrintRev (in (a)); PrintRev (pre (a)); delete a; delete b; delete C; delete d; delete e; return 1;}
Maybe you will feel that this Iterator and STL's interface have little. Oh, this realizes the minimum function principle, the other Operator , write a small adapter to convert the interface, should it be?
:>
In addition, I also wrote a Java version of Binary Tree - Iterator's Adapter. Using Java's GC function, it does not require a node to have a parent pointer.