【问题标题】:index function for balanced binary tree平衡二叉树的索引函数
【发布时间】:2013-05-11 22:32:42
【问题描述】:

我有问题,我无法弄清楚我必须如何决定我的函数 indexJ 在遍历平衡二叉树的每一步必须选择哪个子树 - JoinList

这个想法是缓存每个子树的大小(数据元素的数量)。然后可以在每个步骤中使用它来确定所需的索引是在左分支还是右分支。

我有这个代码:

data JoinList m a = Empty
                  | Single m a
                  | Append m (JoinList m a) (JoinList m a)
                  deriving (Eq, Show)

newtype Size = Size Int
  deriving (Eq, Ord, Show, Num)

getSize :: Size -> Int
getSize (Size i) = i

class Sized a where
  size :: a -> Size

instance Sized Size where
  size = id

instance Monoid Size where
  mempty  = Size 0
  mappend = (+)

我写函数:

tag :: Monoid m => JoinList m a -> m
tag Empty = mempty
tag (Single x dt) = x
tag (Append x l_list r_list) = x

(+++) :: Monoid m => JoinList m a -> JoinList m a -> JoinList m a
(+++) jl1 jl2 = Append (mappend (tag jl1) (tag jl2)) jl1 jl2

indexJ :: (Sized b, Monoid b) => Int -> JoinList b a -> Maybe a
indexJ _ Empty = Nothing
indexJ i jl | i < 0 || (i+1) > (sizeJl jl) = Nothing 

  where sizeJl = getSize . size . tag

indexJ 0 (Single m d) = Just d
indexJ 0 (Append m (Single sz1 dt1) jl2) = Just dt1
indexJ i (Append m jl1 jl2) = if (sizeJl jl1) >= (sizeJl jl2) 
                              then indexJ (i-1) jl1  
                              else indexJ (i-1) jl2 

  where sizeJl = getSize . size . tag

函数tag(+++) 运行良好,但我需要完成indexJ 函数,它必须从我的JoinList 树中返回第i 个元素,i = [0..n]

我的函数 indexJ 工作错误 =) 如果我有空树 - 它是(大小 0) 如果我有单个(尺寸 1)“数据” - 它是(尺寸 1) 但是如果我有 Append (Size 2) (Single (Size 1) 'k') (Single (Size 1) 'l') 我必须选择哪个分支呢? i-1 = 1 并且我有两个分支,每个分支都有 1 个数据元素。

更新:如果有人需要 JoinList 的树的获取和删除功能 我成功了:

dropJ :: (Sized b, Monoid b) => Int -> JoinList b a -> JoinList b a
dropJ _ Empty = Empty 
dropJ n jl | n <= 0 = jl
dropJ n jl | n >= (getSize . size $ tag jl) = Empty
dropJ n (Append m jL1 jL2)
  | n == s1 = jL2
  | n < s1 = (dropJ n jL1) +++ jL2
  | otherwise = dropJ (n - s1) jL2
                where s1 = getSize . size $ tag jL1

takeJ :: (Sized b, Monoid b) => Int -> JoinList b a -> JoinList b a
takeJ _ Empty = Empty 
takeJ n jl | n <= 0 = Empty
takeJ n jl | n >= (getSize . size $ tag jl) = jl
takeJ n (Append m jL1 jL2)
  | n == s1 = jL1
  | n < s1 = (takeJ n jL1)
  | otherwise = jL1 +++ takeJ (n - s1) jL2
                where s1 = getSize . size $ tag jL1

【问题讨论】:

    标签: haskell binary-tree monoids


    【解决方案1】:

    我想在

    Append m joinList1 joinList2
    

    joinList1 的元素用于占用第一个索引,然后是 joinList2 的元素。

    那么,在索引的时候

    indexJ i (Append m jL1 jL2)
    

    您必须将ijL1 的大小进行比较——让我们称之为s1。那么jL1的元素占据索引0到s1 - 1jL2的元素占据s1s1 + s2 - 1的索引,因此

    indexJ :: (Sized b, Monoid b) => Int -> JoinList b a -> Maybe a
    indexJ _ Empty  = Nothing
    indexJ i (Single m d)
        | i == 0    = Just d
        | otherwise = Nothing
    indexJ i (Append m jL1 jL2)
        | i < 0     = Nothing
        | i >= getSize (size m) = Nothing     -- optional, more efficient to have it
        | i < s1    = indexJ i jL1
        | otherwise = indexJ (i - s1) jL2
          where
            s1 = getSize . size $ tag jL1
    

    如果索引小于s1,我们在第一个子列表中查找,否则在第二个。

    【讨论】:

    • 谢谢!您的版本工作正常。我用 1,2,3,4 和 8 个数据元素在我的 JoinLists 上测试它 =)
    【解决方案2】:

    通常,您会通过数字序列来编码树结构中的位置,而不仅仅是单个数字。例如(假设索引从 0 开始):

    [] -- empty sequence = root of tree
    [0,1] -- first follow the first child, then the second child
    [0,0,0] -- go 3 levels down in the leftmost branch
    

    这将使索引函数的实现更加简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-18
      • 1970-01-01
      • 2013-05-21
      • 2012-05-13
      • 1970-01-01
      相关资源
      最近更新 更多