Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 我的二叉树&x27;s delete函数偶尔会导致重复条目_Haskell_Binary Search Tree - Fatal编程技术网

Haskell 我的二叉树&x27;s delete函数偶尔会导致重复条目

Haskell 我的二叉树&x27;s delete函数偶尔会导致重复条目,haskell,binary-search-tree,Haskell,Binary Search Tree,我创建了一个小的二叉树“库”,但tDelete在某些情况下不能正常工作。我在更简单的树上测试了它,效果很好,但在这个特定场景中,它会导致向树中添加一个重复节点。 这似乎是因为对tDelete的递归调用找不到fMin值。但它必须是可查找的,否则它只会返回原始树,而不是删除原始目标值,但不是替换的原始值 主要的例行公事概述了这个问题。最后打印的树删除了目标(992),并依次替换为找到的最小值(993),但在递归调用中从未找到/删除原始最小值(993)(导致两个993条目)。 我已经解决了,我看不出问

我创建了一个小的二叉树“库”,但tDelete在某些情况下不能正常工作。我在更简单的树上测试了它,效果很好,但在这个特定场景中,它会导致向树中添加一个重复节点。 这似乎是因为对tDelete的递归调用找不到fMin值。但它必须是可查找的,否则它只会返回原始树,而不是删除原始目标值,但不是替换的原始值

主要的例行公事概述了这个问题。最后打印的树删除了目标(992),并依次替换为找到的最小值(993),但在递归调用中从未找到/删除原始最小值(993)(导致两个993条目)。 我已经解决了,我看不出问题所在。如果fMin找到993作为替代品,为什么第二次调用tDelete无法找到(并删除)它

我原本以为是我的平衡算法搞乱了排序,但谢天谢地,我认为这是不可能的。如果是这样的话,993一开始就不会被找到(tMin至少找到过一次)。 如有任何见解,将不胜感激。我正要把它做成一张地图,但我需要先解决所有的问题

data Tree a = ETree | Node { leftTreeOf :: Tree a, rightTreeOf :: Tree a, tLoad :: a }

instance Show s => Show (Tree s) where
    show = showTree 0

showTree :: Show s => Int -> Tree s -> String
showTree depth t = "\n" ++ replicate (depth * 2) '-' ++ case t of
    ETree           -> "()"
    (Node lT rT a)  -> "(" ++ show a ++ ")" ++ showTree nD lT ++ showTree nD rT
    where nD = depth + 1

tInsert :: Ord o => o -> Tree o -> Tree o
tInsert x ETree = Node ETree ETree x
tInsert x (Node lT rT a)
    | x < a = Node (tInsert x lT) rT a
    | x > a = Node lT (tInsert x rT) a
    | otherwise = Node lT rT x

-- Replaces the L/R tree with nT
replaceL, replaceR :: Ord o => Tree o -> Tree o -> Tree o
replaceL _ ETree = ETree
replaceL nT (Node _ rT a) = Node nT rT a

replaceR _ ETree = ETree
replaceR nT (Node lT _ a) = Node lT nT a

-- Folds a list into a tree
tFromListL, tFromListR :: Ord o => [o] -> Tree o
tFromListL = foldl (flip tInsert) ETree
tFromListR = foldr tInsert ETree

leftRotation, rightRotation :: Ord o => Tree o -> Tree o
rightRotation ETree = ETree
rightRotation t@(Node lT _ _) = let replaced = replaceL (rightTreeOf lT) t in
    replaceR replaced lT

leftRotation ETree = ETree
leftRotation t@(Node _ rT _) = let replaced = replaceR (leftTreeOf rT) t in
    replaceL replaced rT

-- Turns a tree into a list
tToList :: Ord o => Tree o -> [o]
tToList ETree = []
tToList (Node lT rT a) = (tToList lT) ++ [a] ++ (tToList rT)

-- Splits a list roughly in half (as part of balancing)
splitInHalf :: [a] -> ([a],[a])
splitInHalf xs = splitAt (round $ (fromIntegral $ length xs) / 2.0) xs

-- Returns how unbalanced a node is
tUnbalancedBy :: Tree a -> Int
tUnbalancedBy ETree = 0
tUnbalancedBy (Node lT rT _) = absDiff (tDepth lT) (tDepth rT)

-- Arranges a list in such a way that it forms a more balanced tree
balanceList :: [a] -> [a]
balanceList xs = let (fH,sH) = splitInHalf xs in (reverse fH) ++ sH

-- "Inefficient balance"
tIneffBalance :: Ord o => Tree o -> Tree o
tIneffBalance = tFromListL . balanceList . tToList

-- Finds the min/max values of a tree
tMin, tMax :: Ord o => Tree o -> o
tMin ETree = error "tMin called on an Empty Tree"
tMin (Node lT _ a) = case lT of
    ETree           -> a
    (Node lT' _ _)  -> tMin lT'

tMax ETree = error "tMax called on an Empty Tree"
tMax (Node _ rT a) = case rT of
    ETree           -> a
    (Node _ rT' _)  -> tMax rT'

-- Find the max depth of a tree 
tDepth :: Tree a -> Int
tDepth ETree = 0
tDepth (Node lT rT _) = 1 + max (tDepth lT) (tDepth rT)

-- Finds how many nodes a tree contains
tSize :: Tree a -> Int
tSize ETree = 0
tSize (Node lT rT _) = 1 + (tSize lT) + (tSize rT)

absDiff :: Int -> Int -> Int
absDiff x y = abs $ x - y

exceeds :: (Num n, Ord n) => n -> n -> Bool
exceeds x y = let t = 1 in x >= (y - t)

isInRangeOf :: (Num n, Ord n) => n -> n -> Bool
isInRangeOf x y = let t = 1 in
    x >= (y - t) && x <= (y + t)

-- Checks if a node is balanced
tIsBalanced :: Tree a -> Bool
tIsBalanced ETree = True
tIsBalanced n@(Node lT rT _) =
    tUnbalancedBy n <= 1 && tIsBalanced lT && tIsBalanced rT

tBalance :: Ord o => Tree o -> Tree o
tBalance ETree = ETree
tBalance n@(Node lT rT a)
    | lD `isInRangeOf` rD = Node (tBalance lT) (tBalance rT) a
    | lD `exceeds` rD = balanceRest $ rightRotation n
    | otherwise = balanceRest $ leftRotation n
    where
        (lD,rD) = (tDepth lT,tDepth rT)
        balanceRest t = replaceR (tBalance $ rightTreeOf t) $
            replaceL (tBalance $ leftTreeOf t) t

tBalanceNX :: Ord o => Int -> Tree o -> Tree o
tBalanceNX _ ETree = ETree
tBalanceNX n t = foldl (\a _-> tBalance a) t [1..n]

-- Checks if a value is an element of the tree
tElem :: Ord o => o -> Tree o -> Bool
tElem x ETree = False
tElem x (Node lT rT a)
    | x < a = tElem x lT
    | x > a = tElem x rT
    | otherwise = True

getSubTree :: Ord o => o -> Tree o -> Tree o
getSubTree _ ETree = ETree
getSubTree e t@(Node lT rT a)
    | e < a = getSubTree e lT
    | e > a = getSubTree e rT
    | otherwise = t

tDelete :: Ord o => o -> Tree o -> Tree o
tDelete _ ETree = ETree
tDelete _ n@(Node ETree ETree _) = n -- Or give "Not found" error?
tDelete tD n@(Node lT rT a)
    | tD < a = Node (tDelete tD lT) rT a
    | tD > a = Node lT (tDelete tD rT) a
    | otherwise = case (lT,rT) of
        (ETree,t)   -> t
        (t,ETree)   -> t
        (t,t')      -> let fMin = tMin t' in Node t (tDelete (fMin) t') fMin

getErrorTree :: Tree Int
getErrorTree = getSubTree 992 . tBalanceNX 100 $ tFromListL [1..1000]

main = do
    putStrLn "Deleting 992 yields two 993 trees"
    let errorTree = getErrorTree
    print errorTree
    putStrLn $ "993 findable in tree? " ++ show (993 `tElem` errorTree)
    print $ tDelete 992 errorTree
    putStrLn "The final tree ends up containing two 993 values; one as the root (intended), and one further down (unintended. It should have been deleted in the last case of the last guard of tDelete)"
data Tree a=ETree | Node{leftTreeOf::Tree a,rightreeof::Tree a,tLoad::a}
实例Show s=>Show(树s)where
show=showTree 0
showTree::Show s=>Int->Tree s->String
showTree depth t=“\n”++复制(深度*2)”-“++案例t
ETree->“()”
(节点lT rT a)->“(“++”显示a++“++”+++showTree和lT++showTree和rT
式中,nD=深度+1
tInsert::Ord o=>o->Tree o->Tree o
tInsert x ETree=节点ETree ETree x
t插入x(节点lT rT a)
|xa=节点lT(t插入x插入)a
|否则=节点lT rT x
--用nT替换L/R树
replaceL,replaceR::Ord o=>Tree o->Tree o->Tree o
replaceL u-ETree=ETree
替换nT(节点rT a)=节点nT rT a
替换者uetree=ETree
替换器nT(节点lT a)=节点lT nT a
--将列表折叠成树
tFromListL,tFromListR::Ord o=>[o]->Tree o
tFromListL=foldl(翻转tInsert)ETree
tFromListR=foldr tInsert ETree
左旋转,右旋转::Ord o=>树o->树o
右旋转ETree=ETree
右旋转t@(节点lT_uuuu)=让被替换=替换L(lT的右树)t in
替换者替换了lT
leftRotation ETree=ETree
leftRotation t@(Node_uRT_uUt)=让被替换=替换器(leftTreeOf rT)t in
替换
--将树转换为列表
tToList::Ord o=>树o->[o]
tToList ETree=[]
tToList(节点lT rT a)=(tToList lT)++[a]+(tToList rT)
--将列表大致分成两半(作为平衡的一部分)
splitInHalf::[a]->([a],[a])
splitInHalf xs=splitAt(舍入$(从整数$length xs)/2.0)xs
--返回节点的不平衡程度
tUnbalancedBy::树a->Int
tUnbalancedBy ETree=0
tUnbalancedBy(节点lT rT)=absDiff(tDepth lT)(tDepth rT)
--以形成更平衡的树的方式排列列表
余额表::[a]->[a]
平衡列表xs=let(fH,sH)=拆分中间xs in(反向fH)++sH
--“低效余额”
tIneffBalance::Ord o=>树o->树o
tineffsbalance=tFromListL。平衡表。tToList
--查找树的最小/最大值
tMin,tMax::Ord o=>Tree o->o
tMin ETree=错误“在空树上调用tMin”
tMin(节点lT a)=情况lT
ETree->a
(节点lT'\uu)->tMin lT'
tMax ETree=错误“在空树上调用tMax”
tMax(节点rT a)=情况rT
ETree->a
(节点uRT'->tMax rT'
--求树的最大深度
tDepth::树a->Int
tDepth ETree=0
tDepth(节点lT rT_u2;)=1+最大值(tDepth lT)(tDepth rT)
--查找树包含的节点数
树a->Int
tSize ETree=0
tSize(节点lT rT_u2;)=1+(tSize lT)+(tSize rT)
absDiff::Int->Int->Int
absDiff x y=abs$x-y
超过::(数量n,订单n)=>n->n->Bool
在x>=(y-t)中超过x y=让t=1
isInRangeOf::(Num n,Ord n)=>n->n->Bool
isInRangeOf x y=设t=1 in
x>=(y-t)和&x布尔
TISETREE=真
TISN@(节点lT rT)=
通过n树o->树o平衡
t平衡ETree=ETree
t天平n@(节点lT rT a)
|lD`isInRangeOf`rD=节点(tBalance lT)(tBalance rT)a
|lD`oversed`rD=balanceest$rightRotation n
|否则=balanceRest$leftRotation n
哪里
(lD,rD)=(tDepth lT,tDepth rT)
平衡器测试t=更换件(t天平$rightTreeOf t)$
替换(t余额$leftTreeOf t)t
tBalanceNX::Ord o=>Int->Tree o->Tree o
tBalanceNX_uetree=ETree
tBalanceNX n t=foldl(\a\u->TBALANCEA)t[1..n]
--检查值是否为树的元素
远程通信:Ord o=>o->Tree o->Bool
tElem x ETree=错误
远程x(节点lT rT a)
|xa=远程x远程
|否则=真
getSubTree::Ord o=>o->Tree o->Tree o
getSubTree\ueTree=ETree
getSubTree eT@(节点lT rT a)
|ea=getSubTree e rT
|否则=t
tDelete::Ord o=>o->Tree o->Tree o
tDelete uetree=ETree
tDelete_un@(Node-ETree-ETree)=n——还是给出“未找到”错误?
tDelete tD n@(节点lT rT a)
|tDa=节点lT(tDelete tD rT)a
|否则=的情况(lT,rT)
(ETree,t)->t
(t,ETree)->t
(t,t')->让节点t(tDelete(fMin)t')中的fMin=tMin t'fMin
getErrorTree::树Int
getErrorTree=getSubTree 992。tBalanceNX 100$tFromListL[1..1000]
main=do
putStrLn“删除992生成两棵993树”
设errorTree=getErrorTree
打印错误树
putStrLn$“993可在树中查找?”++显示(993`tElem`errorTree)
打印$tDelete 992错误树
putStrLn“最后一棵树结束了
tDelete _ n@(Node ETree ETree _) = n -- Or give "Not found" error?