The type is defined as
data BST = MakeNode BST String BST
| Empty
I'm trying to add a new leaf to the tree, but I don't really understand how to do it with recursion.
the function is set up like this
add :: String -> BST -> BST
The advantage of using binary trees is that you only need to look at the "current part" of the tree to know where to insert the node.
So, let's define the add function:
add :: String -> BST -> BST
If you insert something into an empty tree (Case #1), you just create a leaf directly:
add s Empty = MakeNode Empty s Empty
If you want to insert something into a node (Case #2), you have to decide which sub-node to insert the value in. You use comparisons to do this test:
add s t#(MakeNode l p r) -- left, pivot, right
| s > p = Node l p (add s r) -- Insert into right subtree
| s < p = Node (add s l) p r -- Insert into left subtree
| otherwise = t -- The tree already contains the value, so just return it
Note that this will not rebalance the binary tree. Binary tree rebalancing algorithms can be very complicated and will require a lot of code. So, if you insert a sorted list into the binary tree (e.g. ["a", "b", "c", "d"]), it will become very unbalanced, but such cases are very uncommon in practice.
Related
I wrote Tree RB in haskell, it looks like this:
data Tree a = Leaf | Node a Color (Tree a) (Tree a)
And also the signature of the insert:
insert :: (Ord a) => a -> Tree a -> Tree a
The question I'm worried about is that I want to insert all the values from the sheet into the structure, but I don't understand how to do this, because the new value must be called from the last state of the structure, can anyone help? I'm trying to do something like this:
add_elements:: Tree a -> [b] -> Tree a
add_elements t list= map ins $ list where
ins x = insert x t <-- data are always inserted in the same state of the structure
You here create a list of Trees where for each tree in the list, you have inserted an element from the list in the original tree, so if you use the empty tree and elements 2 and 5, then you made a tree with 2 as element, and a tree with 5 as element.
You can work with foldl :: Foldable f => (b -> a -> b) -> b -> f a -> b to work wit an accumulator that starts with an initial element, and each time calls the function with that accumulator and the next item in a foldable (list) to obtain the next version of the accumulator.
This will thus look like:
addElements :: Ord a => Tree a -> [a] -> Tree a
addElements = foldl …
where I leave filling in the … part as an exercise.
I'm very new to haskell and need to use a specific data type for a problem I am working on.
data Tree a = Leaf a | Node [Tree a]
deriving (Show, Eq)
So when I make an instance of this e.g Node[Leaf 1, Leaf2, Leaf 3] how do I access these? It won't let me use head or tail or indexing with !! .
You perform pattern matching. For example if you want the first child, you can use:
firstChild :: Tree a -> Maybe (Tree a)
firstChild (Node (h:_)) = Just h
firstChild _ = Nothing
Here we wrap the answer in a Maybe type, since it is possible that we process a Leaf x or a Node [], such that there is no first child.
Or we can for instance obtain the i-th item with:
iThChild :: Int -> Tree a -> Tree a
iThChild i (Node cs) = cs !! i
So here we unwrap the Node constructor, obtain the list of children cs, and then perform cs !! i to obtain the i-th child. Note however that (!!) :: [a] -> Int -> a is usually a bit of an anti-pattern: it is unsafe, since we have no guarantees that the list contains enough elements, and using length is an anti-pattern as well, since the list can have infinite length, so we can no do such bound check.
Usually if one writes algorithms in Haskell, one tends to make use of linear access, and write total functions: functions that always return something.
So i have this data structure:
class ordering a where
order :: a-> Int
And i want to create a search tree, where every node is a list of elements, specified by their own order number( root is 1, root of left subtree is 2, root of right subtree is 3, and so on..). Every type of data that is inserted in the tree has an "order" number associated with it that only matters for "tree insertion purposes", and if it is equal to 1, it stays in the root, if it is two, it stays on the left side of the tree, and so on..
Here's my attempt at this:
data Tree a = EmptyTree
| Node a order a (Tree [a]) (Tree [a]) deriving (Show, Read, Eq)
What i've done, makes sense to me, but apparently is wrong, but honestly i have no idea why...
I'm new to Haskell, and i've been struggling to learn the language, so i appreciate any kind of help from you guys!
The ordering that you have defined is a type class, not a data structure. order is an operation, not a type. Putting the order operation in the Tree data structure makes no sense.
You also haven't shown us any code to actually insert data, so I'm unsure how this is supposed to work.
Let's start from the function actually. Apparently you want this:
insert :: Ord key => (key,val) -> Tree key val -> Tree key val
since your tree carries values that are to be inserted according to keys, this Tree type must enclose both of them:
data Ord key => Tree key val = EmptyTree
| Node key val (Tree key val) (Tree key val)
now it's easy to implement the insert function. Each tree of a type Tree key val will be able to carry keys of type key and values of type val. To accommodate for various concrete value types in one tree you can use a tagged union type for it:
data Myval = My_c1 | My_c2 | MyInt Int | MyInts [Int] | MyString String | ...
now a tree of type, e.g., Tree Int Myval will carry values tagged with Myval constructors, inserted according to the user supplied Int keys.
If you mean that every data type has its own key,
ordkey :: Myval -> Int
ordkey My_c1 = 1
ordkey My_c2 = 2
ordkey (MyInt _) = 3
....
then you won't use insert directly, but rather through an intermediary,
ordinsert val tree = insert (ordkey val,val) tree
This is of course a simple, unsophisticated way to go about it, maybe this is what you meant.
How do you delete the minimum in BST? I can't seem to find a way to keep the tree
data BST = EmptyT
| Node Float BST BST
deriving (Eq, Show, Read)
deleteMin :: BST -> Maybe BST
deleteMin EmptyT = Nothing
deleteMin (Node x left right)
|left == EmptyT = ?
|otherwise = ?
do i need getters and setters?
Haskell does not have "getters and setter" in the OOP sense, though you can
come up with similar concepts. If you wish to delete a value in your binary
tree, you have to construct a new tree with the value missing. That is how you
"keep the tree."
Assuming you are using a standard BST, then the leftmost node in the tree will
contain the minimum element. So, by traversing your tree towards the left,
you should eventually run into a situation that looks like Node x EmptyT r.
Any other node, you just recursively call deleteMin on the left branch.
This gives a function that looks like
deleteMin :: BST -> Maybe BST
deleteMin EmptyT = Nothing
deleteMin (Node x EmptyT right) = Just right
deleteMin (Node x left right) =
case deleteMin left of
Nothing -> Nothing
Just nl -> Just $ Node x nl right
You have to check the result of each call to deleteMin to check for
Nothing. I don't think you really need to return a Maybe BST, unless you
really need to indicate that there is no element to delete. It makes more
sense (to me at least) to just return an empty tree if there is nothing to
delete.
I think most would also consider the use of pattern matching preferable over using guards with an equality check.
Here I have in mind that a possible configuration is a tree of specifications, each specification has a corresponding keyword (the string) and type. Something like this:
data Select = And | Or
data ConfigTree = Node Select [ConfigTree] | Leaf (String, *)
I'm not sure how to write this properly, given that there's no "type of types", but nevermind that for the moment.
Now, given such a tree, I want to build a parser that can read a possible valid configuration; I assume I already have sub-parsers that can parse keyword/type pairs.
For instance, a possible configuration tree is:
Node And [ Leaf ("width", Double)
, Node Or [ Leaf ("height", Double) , Leaf ("aspectratio", Double)
]
which can specify the size of a rectangle. A possible configuration file would be, say:
aspectratio = 2
width = 10
(Let's assume that a configuration file is just a list of newline separated pairs, keyword = blah, where blah is something the corresponding parser for that keyword can deal with; but they can be in any order, and just have to match up with one possible "valid subset" of the tree, where a valid subset is any subset containing the top node, that contains all the children of an "and" node it contains, and say exactly one child of an "or" node it contains.)
I have no idea how to even start building such a parser. Can anyone give some tips about how to proceed, or a way to completely restructure the above ConfigTree datatype to something more amenable to parsing?
The problem with building a parser for this, is that your input format doesn't match your data type at all. The input format is a simple, easily parsable list of key-value pairs while your data type is a tree. E.g. to determine if all the sub-trees in an And node are valid you have to know the complete input.
So, instead of doing validating the list of key-value pairs directly in the parser, just do it afterwards.
I've put together a small example to show what I mean:
data Type = TDouble | TString
data Select = And | Or
data ConfigTree = Node Select [ConfigTree] | Leaf (String, Type)
-- matches a list of key-value pairs against a tree
match :: [(String, String)] -> ConfigTree -> Bool
match sts (Leaf (s, t)) = case filter ((== s) . fst) sts of
-- we don't want multiple occurences of a key
[(_, v)] -> if valid v t then True else False
_ -> False
match sts (Node And cfgs) = and . map (match sts) $ cfgs
-- not completely what you described, because it will match 1 or more
match sts (Node Or cfgs) = or . map (match sts) $ cfgs
-- validates a string against a type
valid :: String -> Type -> Bool
valid s TDouble = case reads s :: [(Double, String)] of
[(_, "")] -> True
_ -> False
valid _ TString = True
-- this is what you actually parsed
config = [ ("aspectratio", "2")
, ("width", "123")
, ("name", "Sam")
]
-- the example tree
cfgTree = Node And [ Leaf ("width", TDouble)
, Node Or [ Leaf ("height", TDouble), Leaf ("aspectratio", TDouble)]
]
I don't think that this is a particularly useful example, because all it does is check if your config data are valid, it doesn't extract them, but I hope it demonstrates what I meant.