У меня проблема, я не могу понять, как я должен решить, какое поддерево моя функция 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
функции, которая должна возвращать I-й элемент из мое дерево JoinList, i = [0..n]
моя функция indexJ
не работает =) Если у меня пустое дерево - это (размер 0) , если у меня есть один (размер 1) «данные» - это (размер 1) , но как насчет того, если у меня есть Append (размер 2) (Single (Size 1) 'k ') (Single (размер 1)' l '), какую ветку я должен выбрать? i-1 = 1 и i имеют две ветви с 1 элементом данных в каждом.
UPDATE: если кому-то нужно взять и функции капли для деревьев 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
Спасибо! Ваша версия работает правильно. Я тестирую его на своих JoinLists с 1,2,3,4 и 8 элементами данных =) –