📜 ⬆️ ⬇️

Traversing a tree without recursion and without a stack

I came up with a simple iterator for traversing an arbitrary tree:
(to ease the code first)

struct Document <br/>{<br/> Concept *root;<br/> struct Iter <br/> {<br/> Concept *start;<br/> Concept *cur;<br/> Concept *bottom;<br/> }iter;<br/> <br/> Concept* Begin(Concept *c)<br/> {<br/> iter.start = c;<br/> iter.cur = c;<br/> iter.bottom = 0 ;<br/> return Next();<br/> }<br/> Concept * Next()<br/> {<br/> if (!iter.cur) return 0 ;<br/> <br/> while (iter.cur != iter.bottom && iter.cur->first_child)<br/> iter.cur = iter.cur->first_child;<br/> <br/> Concept *ret = iter.cur;<br/> <br/> if (iter.cur == iter.start)<br/> iter.cur = 0 ;<br/> else if (iter.cur->next)<br/> iter.cur = iter.cur->next;<br/> else <br/> {<br/> iter.cur = iter.cur->parent;<br/> iter.bottom = iter.cur;<br/> }<br/> return ret;<br/> }<br/>};<br/> <br/>

This feature allows you to greatly simplify the code and do so:
Concept *clicked = ConceptFromMouse();<br/> for (Concept *c = document->Begin(clicked); c; c=document->Next())<br/>{<br/> DoSomething( c );<br/>} <br/>

Bypasses the tree in the same order as this recursion:
void DoSomethingHelper(root)<br/>{<br/> for (Concept *c = root; c; c=c->next)<br/> {<br/> DoSomethingHelper(c->first_child);<br/> }<br/> DoSomething(root);<br/>}<br/> <br/>

Description of work:


1. we fall into the very bottom along the chain first_child-> first-> child-> ... (this is the leftmost branch if the picture is drawn)
2. I remember to return the found element
3. I switch the iterator to the next element, which I will return at next. Next ()
at the same time, if I go up - I put the protection against falling down in the same place - I put iter.bottom
(besides, if he has children, he will again fall down, as it should, when calling Next ())

Application:


This is awesome when you need to do a lot of different actions with the tree in different places of the code. Especially when access to a tree is needed from other classes.
If you use the method with recursion - then you have to write a bunch of uncomfortable, ugly auxiliary functions. And so - work with a tree through a simple iterator:
')
void DocumentEditor::OnDrag( Concept *con, float dx, float dy )<br/>{<br/> // drag with childs <br/> for (Concept *c = document->Begin(con); c; c=document->Next())<br/> {<br/> c->x += dx;<br/> c->y += dy;<br/> }<br/>} <br/>

UPD:
[14:26:11] Petrov: I've encountered these types of algorithms about this:
www.perlmonks.org/?node_id=600456

Source: https://habr.com/ru/post/97841/


All Articles