
Oops, mistake in sender name. Hi, i wanted to write an algorithm for loading a binary tree, then get the values in order and other operations. So, i created a data type : data AR a = R a (AR a) (AR a) | N deriving (Show, Ord, Eq) for an example : R 30 (R 10 (N) (R 20 N N )) (R 40 (N) (R 50 N N )) the main problem i had is : how to update such a complex value, to add another one. After hours of trying (and error !) my solution is : find where to insert the new value, then read the whole tree and copy its values, except for the one for insert. The tree must be read entirely as long as there are values to insert. For large numbers of values, i guess calculation time will increase seriously. I wrote it using "basic" Haskell capabilities. Are there some modules that manage this in a quicker way? using mutable variables ? Below is my code. How can it be improved ? Several limitations to my program (i could solve them) : . only Int values (strings should not be a problem) . minimum 2 values to make a tree . no duplicate values :it's used to find the node where to insert a new value. To allow duplicates, i should generate a unique "node id". -- cre [30, 10, 40, 50, 20] cre :: [Int] -> AR Int cre val = -- add values except the first one cre' (tail val) arb where -- init tree with first value arb=R (head val) N N -- Add values to the tree cre' :: [Int] -> AR Int -> AR Int cre' [] arb = arb -- at the end, get last value for the tree data cre' (x:xs) arb = cre' xs (cre'' x arb) -- Find the node where to insert the new value and proceed cre'' :: Int -> AR Int -> AR Int cre'' n arb = cre''' n arb (r, gd) where (r, gd)= trouve n arb -- insert at node value r, g(auche) ou d(roite) -- Read the whole tree and update the specified node to insert the new value cre''' :: Int -> AR Int -> (Int, String) -> AR Int cre''' _ N _ = N cre''' n (R x y z) (r, gd) = R x (cre''' n y' (r,gd)) (cre''' n z' (r,gd)) where -- left value (<) y' = if x == r && gd=="g" then R n N N else y -- right value (>) z' = if x == r && gd=="d" then R n N N else z -- find the node where to insert the value trouve :: Int -> AR Int -> (Int, String) trouve n (R x y z) | n <= x && y == N = (x, "g") | n <= x = trouve n y | n > x && z == N = (x, "d") | n > x = trouve n z trouve n (N) = (0, " ") Thanks for your comments and help. Didier.

On Thursday 06 May 2010 21:51:47, legajid wrote:
Oops, mistake in sender name.
Hi, i wanted to write an algorithm for loading a binary tree, then get the values in order and other operations.
So, i created a data type : data AR a = R a (AR a) (AR a) | N deriving (Show, Ord, Eq) for an example : R 30 (R 10 (N) (R 20 N N )) (R 40 (N) (R 50 N N ))
the main problem i had is : how to update such a complex value, to add another one.
insert :: Ord a => a -> AR a -> AR a insert x ar@(R y l r) | x < y = R y (insert x l) r | x == y = ar | otherwise = R y l (insert x r) insert x N = R x N N However, this might lead to very skewed trees. In general it is preferable to use balanced trees to prevent that. Then you would store the size (or the depth) in the nodes alongside the data and rebalance the tree when it becomes too skewed. There are packages for trees on Hackage, also you could look at the implementation of Data.Set for deeper insights.
After hours of trying (and error !) my solution is : find where to insert the new value, then read the whole tree and copy its values, except for the one for insert. The tree must be read entirely as long as there are values to insert. For large numbers of values, i guess calculation time will increase seriously.
If you don't balance the tree, you risk that its depth (and hence an insert) is O(size), making the building of a tree of size n an O(n^2) algorithm [okay, that is the worst case, when the list of items to insert is basically sorted; more often it would be a depth of O(n^0.5) or so]. With a balanced tree, the depth is O(log size), making the building an O(n*log n) algorithm. Also, for efficiency, you should make the tree strict (at least the structure), data AR a = R a !(AR a) !(Ar a)
I wrote it using "basic" Haskell capabilities. Are there some modules that manage this in a quicker way?
Search Hackage for "tree", look at Data.Set.
using mutable variables ?
Below is my code. How can it be improved ? Several limitations to my program (i could solve them) : . only Int values (strings should not be a problem) . minimum 2 values to make a tree . no duplicate values :it's used to find the node where to insert a new value. To allow duplicates, i should generate a unique "node id".
-- cre [30, 10, 40, 50, 20] cre :: [Int] -> AR Int cre val = -- add values except the first one cre' (tail val) arb where -- init tree with first value arb=R (head val) N N
-- Add values to the tree cre' :: [Int] -> AR Int -> AR Int cre' [] arb = arb -- at the end, get last value for the tree data cre' (x:xs) arb = cre' xs (cre'' x arb)
-- Find the node where to insert the new value and proceed cre'' :: Int -> AR Int -> AR Int cre'' n arb = cre''' n arb (r, gd) where (r, gd)= trouve n arb -- insert at node value r, g(auche) ou d(roite)
-- Read the whole tree and update the specified node to insert the new value cre''' :: Int -> AR Int -> (Int, String) -> AR Int cre''' _ N _ = N cre''' n (R x y z) (r, gd) = R x (cre''' n y' (r,gd)) (cre''' n z' (r,gd)) where -- left value (<) y' = if x == r && gd=="g" then R n N N else y -- right value (>) z' = if x == r && gd=="d" then R n N N else z
-- find the node where to insert the value trouve :: Int -> AR Int -> (Int, String) trouve n (R x y z)
| n <= x && y == N = (x, "g") | n <= x = trouve n y | n > x && z == N = (x, "d") | n > x = trouve n z
trouve n (N) = (0, " ")
Thanks for your comments and help.
Didier.

Have a look at AVL Trees or Red-black trees. They are both types of self balancing trees which is what I think you're looking for. -- - Scott Kidder () ascii ribbon campaign - against html e-mail /\ www.asciiribbon.org - against proprietary attachments

On Thu, May 6, 2010 at 9:51 PM, legajid
Oops, mistake in sender name.
Hi, i wanted to write an algorithm for loading a binary tree, then get the values in order and other operations.
So, i created a data type : data AR a = R a (AR a) (AR a) | N deriving (Show, Ord, Eq) for an example : R 30 (R 10 (N) (R 20 N N )) (R 40 (N) (R 50 N N ))
the main problem i had is : how to update such a complex value, to add another one. After hours of trying (and error !) my solution is : find where to insert the new value, then read the whole tree and copy its values, except for the one for insert.
Let's say your tree is either empty or is a node that holds a value and two subtrees, one for values that are smaller and one for values that are greater. What if you want to insert a value into an empty tree ? You make a node with the given value and the two subtrees empty ins v N = R v N N what is the tree isn't empty ? two possibilities: - the value to insert is smaller than the node's value -> replace the subtree of smaller values by the result of inserting the value into that subtree - it's bigger ins v (R v' s1 s2) | v < v' = R v' (ins v s1) s2 | v > v' = R v' s1 (ins v s2) question : what to do if v == v' ? I leave the question to you :) That's it :)

Hi, much more simple and efficient than my solution. I just see a strange thing. I changed < to <=, then > to >= in order to insert duplicate values, and added a top level function to give a list of values to insert. with <=, inser [40,40,30,40,50] gives R 40 (R 40 (R 30 N (R 40 N N)) N) (R 50 N N) with >=, inser [40,40,30,40,50] gives R 40 (R 30 N N) (R 40 N (R 40 N (R 50 N N))) Traversing the tree in ascending order from left to right, the results are the same. In the first case, left tree has a depth of three. In the second case, right tree does. But are these different layouts totally equivalent? I think that the depth of each branch is dependent upon the order of input data and the test (<=, >=). Can i evaluate this prior to loading the tree, so that i avoid having a tree with a branch much larger than the other one ? Thanks, Didier David Virebayre a écrit :
On Thu, May 6, 2010 at 9:51 PM, legajid
wrote: Oops, mistake in sender name.
Hi, i wanted to write an algorithm for loading a binary tree, then get the values in order and other operations.
So, i created a data type : data AR a = R a (AR a) (AR a) | N deriving (Show, Ord, Eq) for an example : R 30 (R 10 (N) (R 20 N N )) (R 40 (N) (R 50 N N ))
the main problem i had is : how to update such a complex value, to add another one. After hours of trying (and error !) my solution is : find where to insert the new value, then read the whole tree and copy its values, except for the one for insert.
Let's say your tree is either empty or is a node that holds a value and two subtrees, one for values that are smaller and one for values that are greater.
What if you want to insert a value into an empty tree ? You make a node with the given value and the two subtrees empty
ins v N = R v N N
what is the tree isn't empty ? two possibilities: - the value to insert is smaller than the node's value -> replace the subtree of smaller values by the result of inserting the value into that subtree - it's bigger
ins v (R v' s1 s2) | v < v' = R v' (ins v s1) s2 | v > v' = R v' s1 (ins v s2)
question : what to do if v == v' ? I leave the question to you :)
That's it :)
participants (4)
-
Daniel Fischer
-
David Virebayre
-
legajid
-
Scott Kidder