Finding the number of the neighbours of a given node of a multiway tree (rose tree) in Haskell

307 views Asked by At

Consider the following definition of a Rose Tree: The tree can contains unique nodes.

data NTree a = Nil | Node { root :: a, subtree :: [NTree a]} deriving Show
-- or just data NTree a = Nil | Node a [NTree a]

t1 :: NTree Int
t1 = Node 1 [Node 2 [ Node 5 [Nil], Node 6 [Nil], Node 7 [Nil]], Node 3 [Node 8 [Nil], Node 9 [Nil]], Node 4 [Nil]]
{-
t1:        1
        /  |  \
       /   |   \
     2     3     4
   / | \   | \
  5  6  7  8  9
-}

How to find the number of neighbours of a given node of a rose tree? Examples what I mean:

--Function that finds the number of the neighbours of a given node
neighboursOf :: (Eq a) => NTree a -> a -> Int
--Examples:
print (neighboursOf t1 3) -- -> 3 (The neighbours are 1,8 and 9)
print (neighboursOf t1 1) -- -> 3 (The neighbours are 2,3 and 4)
print (neighboursOf t1 8) -- -> 1 (The neighbour is 3)
print (neighboursOf t1 10) -- -> error "Not existing node"

I don't know how to implement the function

neighboursOf :: (Eq a) => NTree a -> a -> Int

Could you help me to implement the function?

Edit: I came up with this solution:

data NTree a = Nil | Node {root :: a, subtree :: [NTree a] } deriving (Show , Eq)

neighborsOf :: (Eq a) => NTree a -> a -> Int
neighborsOf Nil _ = error "Empty tree"
neighborsOf tree element
    | helper tree element True == 0 = error "No such element"
    | otherwise = helper tree element True

helper ::(Eq a) => NTree a -> a -> Bool -> Int
helper Nil _ _ = 0
helper tree el isSuperior
    | root tree == el && isSuperior && subtree tree == [Nil] = 0
    | root tree == el && isSuperior = length $ subtree tree
    | root tree == el && subtree tree == [Nil] = 1
    | root tree == el = length (subtree tree) + 1
    | otherwise = helper' (subtree tree) el
        where 
            helper' :: (Eq a) => [NTree a] -> a -> Int
            helper' [] _ = 0
            helper' (tree:subtrees) el = helper tree el False  + helper' subtrees el

And I think it is a very bad solution. Could you suggest to me some improvements?

1

There are 1 answers

4
Will Ness On

OK now we can start thinking about it. So your neighbors are either children, or a parent, of the node.

You can write two separate functions, one is childrenOf :: Node -> [Node], the other is parentOf :: Node -> [Node], then use the two functions' results and combine them into the one you need. simple. :)

There can only ever be one parent for a node in a tree, so why did I specify the list, [Node], as the result of parentOf? Can there be only one parent always?