I’m trying to implement a delete() function for a ternary tree that represents a dictionary in Haskell, but I’m facing some issues. The tree structure is defined as follows:
data TTree k v = Node k (Maybe v) (TTree k v) (TTree k v) (TTree k v) | Leaf k v | E deriving Show
Here’s the delete function I’ve implemented so far:
delete :: Ord k => [k] -> TTree k v -> TTree k v
delete _ E = E
delete (x:xs) (Leaf c v)
| x == c && null xs = E
| otherwise = (Leaf c v)
delete (x:xs) (Node c Nothing izq cen der)
| x == c && not (null xs) = delete xs cen
| x == c = (Node c Nothing izq cen der)
| x < c = delete (x:xs) izq
| otherwise = delete (x:xs) der
delete (x:xs) (Node c (Just v) izq cen der)
| x < c = delete (x:xs) izq
| x > c = delete (x:xs) der
| x == c && not(null xs) = if hasSingleLeaf
then if head xs == leftLeafKey || head xs == centerLeafKey || head xs == rightLeafKey
then (Leaf x v)
else delete xs cen
else delete xs cen
| x == c && null xs = let hasCentralChild = not (empty cen)
hasRightChild = not (empty der)
hasLeftChild = not (empty izq)
in if hasCentralChild
then (Node c Nothing izq cen der)
else if hasRightChild && hasLeftChild
then Node (head minKey) (minVal) izq cen (delete minKey der)
else if hasRightChild && not hasLeftChild
then der
else izq
where
minKey = fst (getMin der)
minVal = Just (snd (getMin der))
leftLeafKey = head (fst (getMin izq))
centerLeafKey = head (fst (getMin cen))
rightLeafKey = head (fst (getMin der))
hasSingleLeaf = hasSingleLeafAsChild cen
And here are some extra functions I am using:
-- Function that given a tree, returns True if it has a single leaf as a child.
hasSingleLeafAsChild :: TTree k v -> Bool
hasSingleLeafAsChild E = False -- An empty tree doesn't have a single leaf as a child
hasSingleLeafAsChild (Leaf _ _) = True -- A leaf always has a single leaf as a child
hasSingleLeafAsChild (Node _ _ E cen E) = hasSingleLeafAsChild cen -- Only the central subtree is non-empty
hasSingleLeafAsChild (Node _ _ izq cen der) =
(isLeaf cen && isEmptyTree izq && isEmptyTree der) || -- The central subtree is a leaf and the left and right subtrees are empty
(isEmptyTree cen && isLeaf izq && isEmptyTree der) || -- The left subtree is a leaf and the central and right subtrees are empty
(isEmptyTree cen && isEmptyTree izq && isLeaf der) -- The right subtree is a leaf and the central and left subtrees are empty
where
isLeaf E = False
isLeaf (Leaf _ _) = True
isLeaf _ = False
isEmptyTree E = True
isEmptyTree _ = False
-- Function that given a tree, returns a tuple with the key of the smallest node and its associated value.
getMin :: Ord k => TTree k v -> ([k], v)
getMin E = error "The tree is empty"
getMin (Leaf c v) = ([c], v)
getMin (Node c (Just v) izq _ _) = getMin izq
getMin (Node c Nothing _ cen _) = getMin cen
-- Function that given a tree, returns whether it is empty or not.
empty :: Ord k => TTree k v -> Bool
empty E = True
empty _ = False
However, when testing the delete function with a tree, I’m getting incorrect results. For example, when I execute delete “sa” tree2, where tree2 = Node ‘s’ Nothing E (Node ‘e’ (Just 2) (Leaf ‘a’ 1) (Leaf ‘n’ 5) (Leaf ‘i’ 3)) E, I receive E, which is wrong.
Could someone help me identify and correct the errors in my delete function implementation for a ternary tree in Haskell?
Ignacio Rimini is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.