Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-03

How to iterate through a TAvgLvlTree

15 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

Is it possible to iterate through all items in a TAvgLvlTree? I couldn't find an easy method for doing that.

thanks,

Felipe Monteiro de Carvalho

Reply by email

Mattias Gaertner
to Mattias Gaertner
Show quoted text 9 lines
On Fri, 16 Mar 2012 09:30:22 +0100 Felipe Monteiro de Carvalho wrote: > Hello, > > Is it possible to iterate through all items in a TAvgLvlTree? I > couldn't find an easy method for doing that. for Node in Tree do

You might also find the following useful:

Tree.FindLowest
Tree.FindHighest
Tree.FindSuccessor(Node)
Tree.FindPrecessor(Node)

Mattias

Reply by email

Alexander Klenin
to Mattias Gaertner: On Fri, 16 Mar 2012 09:30:22 +0100 for Node in Tree do Mattias
Mattias Gaertner wrote
> Is it possible to iterate through all items in a TAvgLvlTree? I > couldn't find an easy method for doing that. for Node in Tree do

By the way, I think you are using TAvgLvlTree rather often, so did you ever wanted another traversal order besides the default one?

You replaced my proposal of extending the for..in loop on the wiki by an example implementing it using the current syntax.

So, I am interested -- did you actually use you implementation? What is your opinion -- did it work well for you?
In particular, I am interested in the memory management issues -- how is enumerator instance freed in your example?

Finally, do you feel the need for the remaining extension proposal -- namely, getting the index from enumerator?

Alexander S. Klenin

Reply by email

Mattias Gaertner
to Alexander Klenin
Show quoted text 9 lines
On Fri, Mar 16, 2012 at 19:36, Mattias Gaertner wrote: >> Is it possible to iterate through all items in a TAvgLvlTree? I >> couldn't find an easy method for doing that. > > for Node in Tree do By the way, I think you are using TAvgLvlTree rather often, so did you ever wanted another traversal order besides the default one?

Of course.

You replaced my proposal of extending the for..in loop on the wiki by an example implementing it using the current syntax. So, I am interested -- did you actually use you implementation?

Yes.

What is your opinion -- did it work well for you?

Yes.

In particular, I am interested in the memory management issues -- how is enumerator instance freed in your example?

If you mean the fpc enumerators: They are freed by compiler magic after the loop.

Finally, do you feel the need for the remaining extension proposal -- namely, getting the index from enumerator?

An index is hardly needed for an AVL tree.

Mattias

Reply by email

Alexander Klenin
to Mattias Gaertner
Mattias Gaertner wrote 32 lines
On Fri, 16 Mar 2012 20:47:15 +1100 Alexander Klenin wrote: > On Fri, Mar 16, 2012 at 19:36, Mattias Gaertner > wrote: > >> Is it possible to iterate through all items in a TAvgLvlTree? I > >> couldn't find an easy method for doing that. > > > > for Node in Tree do > > By the way, I think you are using TAvgLvlTree rather often, > so did you ever wanted another traversal order besides the default one? Of course. > You replaced my proposal of extending the for..in loop on the wiki > by an example implementing it using the current syntax. > > So, I am interested -- did you actually use you implementation? Yes. > What is your opinion -- did it work well for you? Yes. > In particular, I am interested in the memory management issues -- > how is enumerator instance freed in your example? If you mean the fpc enumerators: They are freed by compiler magic after the loop.

So perhaps this fact should be added to the manual? http://www.freepascal.org/docs-html/ref/refsu50.html

Alexander S. Klenin

Reply by email

Felipe Monteiro de Carvalho
to Alexander Klenin

Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute to TFPList in objects which offer an indirect interface to the internal list, such as TLazAccessibleObject.

My idea is defining:
Index zero = Tree.FindLowest
Indez Count-1= Tree.FindHighest

On each access store the last accessed node and if the next call wants a node index=oldindex+1 or -1 then just use:

Tree.FindSuccessor(Node)
Tree.FindPrecessor(Node)

Because almost always I use the array access only to iterate in a loop.

Non-ordened access ofcourse would be slow because it would require a loop till the index is found.

Felipe Monteiro de Carvalho

Reply by email

Alexander Klenin
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 15 lines
Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute to TFPList in objects which offer an indirect interface to the internal list, such as TLazAccessibleObject. My idea is defining: Index zero = Tree.FindLowest Indez Count-1= Tree.FindHighest On each access store the last accessed node and if the next call wants a node index=oldindex+1 or -1 then just use: ?Tree.FindSuccessor(Node) ?Tree.FindPrecessor(Node) Because almost always I use the array access only to iterate in a loop.

Ouch. This is exactly what enumerators are were designed to avoid. Maybe convert TLazAccessibleObject to expect enumerable instead?

Alexander S. Klenin

Reply by email

Martin
to Felipe Monteiro de Carvalho: Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute…
Felipe Monteiro de Carvalho wrote 19 lines
Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute to TFPList in objects which offer an indirect interface to the internal list, such as TLazAccessibleObject. My idea is defining: Index zero = Tree.FindLowest Indez Count-1= Tree.FindHighest On each access store the last accessed node and if the next call wants a node index=oldindex+1 or -1 then just use: Tree.FindSuccessor(Node) Tree.FindPrecessor(Node) Because almost always I use the array access only to iterate in a loop. Non-ordened access ofcourse would be slow because it would require a loop till the index is found.
And don't forget to invalidate the index on any node operation
(*change/add/remove)

But I would try to avoid that.

If you need that, synedi has an AVL tree which can be used (abused) to keep track of the position/index. It will need minor modifications, as it currently stores the data, as difference to the previous node, rather than absolute value

Reply by email

Felipe Monteiro de Carvalho
to Alexander Klenin: On Fri, Mar 16, 2012 at 21:36, Felipe Monteiro de Carvalho Ouch. This is exactly what…
Alexander Klenin wrote
Ouch. This is exactly what enumerators are were designed to avoid. Maybe convert TLazAccessibleObject to expect enumerable instead?

Could you be more specific as to what type you are talking about and would it look like a routine in TLazAccessibleObject which offers the iteration functionality?

Felipe Monteiro de Carvalho

Reply by email

Mattias Gaertner
to Felipe Monteiro de Carvalho: Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute…
Can I add a routine to access the AvgLvlTree as an array?

No.

A tree in general has no first or 0 element.

If you want to iterate through all nodes, use an enumerator or the findlowest+findsuccessor.

If you want a hybrid of array and avl tree use a differential tree. Martin has implemented a specific one. Maybe a descendant of TAvgLvlTree can be implemented as a generic one.

Show quoted text 15 lines
To make it a better substitute to TFPList in objects which offer an indirect interface to the internal list, such as TLazAccessibleObject. My idea is defining: Index zero = Tree.FindLowest Indez Count-1= Tree.FindHighest On each access store the last accessed node and if the next call wants a node index=oldindex+1 or -1 then just use: Tree.FindSuccessor(Node) Tree.FindPrecessor(Node) Because almost always I use the array access only to iterate in a loop.

That's one specific use case.
For other examples how avl trees can be used see the hundreds of places in the IDE.

Non-ordened access ofcourse would be slow because it would require a loop till the index is found.

Keep the last node. It can be found in O(logn).
Why use an integer to refer to an element?

Mattias

Reply by email

Felipe Monteiro de Carvalho
to Mattias Gaertner
Mattias Gaertner wrote
Why use an integer to refer to an element?

Backwards compatibility. I have multiple libraries which offer an interface to an internal list and I designed all to offer array-access because this is convenient and is how TFPList works. I don't want to break backwards compatibility, so if this can't be added to the AVL tree I will need multiple copies of the AVL tree 2 array code.

Felipe Monteiro de Carvalho

Reply by email

Mattias Gaertner
to Felipe Monteiro de Carvalho: Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute…
Show quoted text 18 lines
Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute to TFPList in objects which offer an indirect interface to the internal list, such as TLazAccessibleObject. My idea is defining: Index zero = Tree.FindLowest Indez Count-1= Tree.FindHighest On each access store the last accessed node and if the next call wants a node index=oldindex+1 or -1 then just use: Tree.FindSuccessor(Node) Tree.FindPrecessor(Node) Because almost always I use the array access only to iterate in a loop. Non-ordened access ofcourse would be slow because it would require a loop till the index is found.

I implemented a TIndexedAVLTree.
This allows log(n) access to items via the position. For example to get the fourth node:

Node:=Tree[3];
It has the above caching mechanism to speed up common queries. So,
running with a "for i:=0 to Tree.Count-1 do" needs O(n).

Otherwise it is a normal AVL tree, so insertion, deletion and finding takes O(log(n)).

I also added a second enumerator to TAvgLvlTree to run from highest to lowest and I removed the nodememmanager making it is easier to use with threads.

Mattias

Reply by email

Marc Weustink
to Felipe Monteiro de Carvalho: Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute…
Felipe Monteiro de Carvalho wrote 15 lines
Can I add a routine to access the AvgLvlTree as an array? To make it a better substitute to TFPList in objects which offer an indirect interface to the internal list, such as TLazAccessibleObject. My idea is defining: Index zero = Tree.FindLowest Indez Count-1= Tree.FindHighest On each access store the last accessed node and if the next call wants a node index=oldindex+1 or -1 then just use: Tree.FindSuccessor(Node) Tree.FindPrecessor(Node) Because almost always I use the array access only to iterate in a loop.

Lazarus has a TMap implementations where a AvgLvlTree is used for looking up items and has a own AvgLvlTreeItem which is a double linked list so items can be iterated.
Tree.FindSuccessor(Node)/Tree.FindPrecessor(Node) can cause a lot of nodes traveled.

Marc

Non-ordened access ofcourse would be slow because it would require a loop till the index is found.

Reply by email