【问题标题】:reconstruct the binary tree with two lists after preorder and inorder在 preorder 和 inorder 之后用两个列表重建二叉树
【发布时间】:2019-04-25 11:55:39
【问题描述】:

--给出两个列表,一个按前序排序,另一个按中序排序。这两个列表来自同一个二叉树。有了这两个列表,二叉树就是 --reconstructed。

-- 网上没有找到“rank”这个功能。我的教授告诉我们,“rank”函数可以输出一个元素在列表中的位置。

错误发生在使用函数“rank”的下一行。

所以我有两个问题。

  1. “排名”功能如何?
  2. 表达式“reconstruct :: [Int]->IntTree”是否正确?我不知道。
main :: IO ()    -- This says that main is an IO action.
main = return () -- This tells main to do nothing

data IntTree = Empty | Branch IntTree Int IntTree deriving (Show, Eq)

reconstruct :: [Int]->IntTree
--  Pattern matching 
reconstruct (x:xs) y = Branch (reconstruct take((rank x y) xs) take ((rank x y) y)) x x (reconstruct drop ((rank x y)+1 xs) drop ((rank x y)+1 y)) 

修正后

import Data.List


main :: IO ()    -- This says that main is an IO action.
main = return () -- This tells main to do nothing

data IntTree = Empty | Branch IntTree Int IntTree deriving (Show, Eq)

--Two lists are given, one sorted by preorder, the other sorted by inorder. 
-- And the two lists are from the same binary tree. With the two lists the binary tree is reconstructed.

reconstruct :: [Int]->[Int]->IntTree
--  Pattern matching 
reconstruct [] [] = Empty
reconstruct (x:xs) y = Branch (reconstruct take (length (fst p) xs) (fst p)) x (reconstruct drop (length (fst p) xs) (snd p))
    where p = span (x/=) y 

reconstruct _ _ = error "incomplete pattern"

错误


E:\Haskell\Uebungsblatt_2_Aufgabe_1.hs:15:32: error:
    * Couldn't match expected type `[Int] -> IntTree'
                  with actual type `IntTree'
    * The function `reconstruct' is applied to three arguments,
      but its type `[Int] -> [Int] -> IntTree' has only two
      In the first argument of `Branch', namely
        `(reconstruct take (length (fst p) xs) (fst p))'
      In the expression:
        Branch
          (reconstruct take (length (fst p) xs) (fst p))
          x
          (reconstruct drop (length (fst p) xs) (snd p))
   |
15 | reconstruct (x:xs) y = Branch (reconstruct take (length (fst p) xs) (fst p)) x (reconstruct drop (length (fst p) xs) (snd p))

   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

E:\Haskell\Uebungsblatt_2_Aufgabe_1.hs:15:44: error:
    * Couldn't match expected type `[Int]'
                  with actual type `Int -> [a0] -> [a0]'
    * Probable cause: `take' is applied to too few arguments
      In the first argument of `reconstruct', namely `take'
      In the first argument of `Branch', namely
        `(reconstruct take (length (fst p) xs) (fst p))'
      In the expression:
        Branch
          (reconstruct take (length (fst p) xs) (fst p))
          x
          (reconstruct drop (length (fst p) xs) (snd p))
   |
15 | reconstruct (x:xs) y = Branch (reconstruct take (length (fst p) xs) (fst p)) x (reconstruct drop (length (fst p) xs) (snd p))

   |                                            ^^^^

E:\Haskell\Uebungsblatt_2_Aufgabe_1.hs:15:50: error:
    * Couldn't match expected type `[Int] -> [Int]'
                  with actual type `Int'
    * The function `length' is applied to two arguments,
      but its type `[Int] -> Int' has only one
      In the second argument of `reconstruct', namely
        `(length (fst p) xs)'
      In the first argument of `Branch', namely
        `(reconstruct take (length (fst p) xs) (fst p))'
   |
15 | reconstruct (x:xs) y = Branch (reconstruct take (length (fst p) xs) (fst p)) x (reconstruct drop (length (fst p) xs) (snd p))

   |                                                  ^^^^^^^^^^^^^^^^^

E:\Haskell\Uebungsblatt_2_Aufgabe_1.hs:15:81: error:
    * Couldn't match expected type `[Int] -> IntTree'
                  with actual type `IntTree'
    * The function `reconstruct' is applied to three arguments,
      but its type `[Int] -> [Int] -> IntTree' has only two
      In the third argument of `Branch', namely
        `(reconstruct drop (length (fst p) xs) (snd p))'
      In the expression:
        Branch
          (reconstruct take (length (fst p) xs) (fst p))
          x
          (reconstruct drop (length (fst p) xs) (snd p))
   |
15 | reconstruct (x:xs) y = Branch (reconstruct take (length (fst p) xs) (fst p)) x (reconstruct drop (length (fst p) xs) (snd p))

   |                                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

E:\Haskell\Uebungsblatt_2_Aufgabe_1.hs:15:93: error:
    * Couldn't match expected type `[Int]'
                  with actual type `Int -> [a1] -> [a1]'
    * Probable cause: `drop' is applied to too few arguments
      In the first argument of `reconstruct', namely `drop'
      In the third argument of `Branch', namely
        `(reconstruct drop (length (fst p) xs) (snd p))'
      In the expression:
        Branch
          (reconstruct take (length (fst p) xs) (fst p))
          x
          (reconstruct drop (length (fst p) xs) (snd p))
   |
15 | reconstruct (x:xs) y = Branch (reconstruct take (length (fst p) xs) (fst p)) x (reconstruct drop (length (fst p) xs) (snd p))

   |                                                                                             ^^^^

E:\Haskell\Uebungsblatt_2_Aufgabe_1.hs:15:99: error:
    * Couldn't match expected type `[Int] -> [Int]'
                  with actual type `Int'
    * The function `length' is applied to two arguments,
      but its type `[Int] -> Int' has only one
      In the second argument of `reconstruct', namely
        `(length (fst p) xs)'
      In the third argument of `Branch', namely
        `(reconstruct drop (length (fst p) xs) (snd p))'
   |
15 | reconstruct (x:xs) y = Branch (reconstruct take (length (fst p) xs) (fst p)) x (reconstruct drop (length (fst p) xs) (snd p))

   |                                                                                                   ^^^^^^^^^^^^^^^^^
[Finished in 0.5s]

【问题讨论】:

  • 我不知道rank 是什么——它肯定不是标准的Haskell 函数。你应该问问你的教授。
  • reconstruct 的类型签名与提供的参数数量不匹配。如果输入是两个列表,那么可能是reconstruct :: [Int] -> [Int] -> IntTree。我认为你脑子里的函数绑定优先级错误 - f a (b) c = f a b c 而不是 f (a b) c(注意 f (a) = f af (a b) /= f a b)。从描述来看,rank 只是标准的 Haskell find。您可能会受益于使用splitAt 而不是droptake

标签: haskell


【解决方案1】:
reconstruct :: [Int] -> [Int] -> IntTree
reconstruct [] [] = Empty
reconstruct (x:xs) y = let (l,_:r) = span (x /=) y
                           (l',r') = splitAt (length l) xs
                       in Branch (reconstruct l' l) x (reconstruct r' r)
reconstruct _ _ = error "incomplete pattern"

这似乎适用于我尝试的单个测试用例,并且几乎是您打算编写的(我认为)。如果节点可以拥有与自己相同内容的左后代(?),则会遇到问题。我认为它可能会遍历l 两次(由于length),如果需要,您可以使用zip 和一些额外的逻辑来解决这个问题。

【讨论】:

  • 非常感谢。我试着理解它
  • @A Tayler ghci> span (/=4) [1,2,3,4,5,6,7] ([1,2,3],[4,5,6,7]) 我找到了函数“span”的例子。但我不明白 "(l,:r)" 和 ""(l,:r)"" 是什么意思?我可以使用 fst 和 sec 来获取列表吗?
  • (l, _:r) 绑定一个元组,其第二个元素是一个非空列表。 l 成为第一个元素,r 成为第二个元素的tail。你可以写 p = span ... l = fst p r = tail . snd $ p 但正如你所看到的,它更冗长。 _ 表示我们忽略了元组右半部分列表中的head - 从技术上讲,因为我们“知道”它是x,这会复制代码中的+1,从而删除x .
  • 我是 Haskell 的新手,兄弟
  • 尝试写ghci > (l,_:r) = span (/=4) [1,2,3,4,5,6,7]然后检查l,r的值。
【解决方案2】:

函数`reconstruct'应用于三个参数,但它的类型`[Int] -> [Int] -> IntTree'只有两个

(reconstruct take (length (fst p) xs) (fst p))

您将 reconstruct 函数应用于 3 个参数,如错误消息中所述:take(length (fst p) xs)(fst p)

类似的错误是长度应用:你传递了 2 个参数给它。

也许您打算将 FUNCTION(ARGUMENT) 作为单个参数传递给下一个函数。它不是这样工作的,它将被视为 2 个参数:FUNCTION(ARGUMENT)。相反,您应该使用 (FUNCTION ARGUMENT),如果 ARGUMENT 很复杂,则应使用 (FUNCTION (ARGUMENT))

此外,您不应将函数的参数与函数分开分组:take (length ... LIST)。这被视为单个参数(length ... LIST)。它们应该与函数处于同一括号级别。

所以你的第一个重构调用应该是这样的:

(reconstruct (take (length (fst p)) xs) (fst p))

可能其余的表达式也有类似的问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多