Haskell에서 트리가 이진 검색 트리인지 확인


10
  type BSTree a = BinaryTree a

  data BinaryTree a = Null | Node (BinaryTree a) a (BinaryTree a)
                      deriving Show

  flattenTree :: BinaryTree a -> [a]
  flattenTree  tree = case tree of
      Null -> []
      Node left val right -> (flattenTree left) ++ [val] ++ (flattenTree right)

  isBSTree :: (Ord a) => BinaryTree a -> Bool
  isBSTree btree = case btree of
      Null -> False
      tree -> (flattenTree tree) == sort (flattenTree tree)

내가하고 싶은 것은 주어진 트리가 이진 검색 트리인지 여부를 결정하는 함수를 작성하는 것입니다. 내 방법은 목록의 모든 값을 그룹화하고 가져 오기 Data.List한 다음 목록을 정렬하여 동일한 지 여부를 찾는 것입니다. 조금 복잡합니다. 다른 모듈을 가져 오지 않고도이 작업을 수행 할 수 있습니까?


flattenTree먼저 정의하지 않습니다 . False노드가 해당 노드를 기반으로하는 전체 하위 트리를 순회하지 않고 검색 속성을 위반하면 일찍 반환 할 수 있습니다 .
chepner

@ chepner 문제는 sort~가 아니라 flattenTree~에 있습니다.
Will Ness

네, 다른 답변을 본 후에 저에게 일어났습니다.
chepner

답변:


13

나무를 평평하게하지 않고 할 수있는 방법이 있습니다.

여기 정의에서

data BinaryTree a = Null | Node (BinaryTree a) a (BinaryTree a)
     deriving Show

무시 Node하고 괄호를 무시 하고 왼쪽에서 오른쪽으로 나무를 가로 지르면 Nulls와 as 가 번갈아 나타납니다 . 즉, 두 값 사이에가 있습니다 Null.

내 계획은 각 하위 트리 만족에 적합한 지 확인하는 것입니다 요구 사항 : 우리가 할 수있는 수정 각각의 요구 사항을 Node우리가 사이 값 기억하는, 다음 테스트 각각에 그들을 Null. 존재하므로 Null값의 순서로 각 쌍 사이에서, 우리는 모든 순서 (왼쪽에서 오른쪽) 쌍은 비 - 감소하는 것을 테스트 할 것이다.

요구 사항은 무엇입니까? 트리의 값에 대한 느슨한 하한입니다. 가장 왼쪽과 오른쪽 끝에있는 요구 사항을 포함하여 요구 사항을 표현하기 위해 다음과 같이 Bot톰과 Top요소로 주문을 확장 할 수 있습니다 .

data TopBot a = Bot | Val a | Top deriving (Show, Eq, Ord)

이제 주어진 트리가 순서와 주어진 범위 사이의 요구 사항을 충족시키는 지 확인하십시오.

ordBetween :: Ord a => TopBot a -> TopBot a -> BinaryTree a -> Bool
  -- tighten the demanded bounds, left and right of any Node
ordBetween lo hi (Node l x r) = ordBetween lo (Val x) l && ordBetween (Val x) hi r
  -- check that the demanded bounds are in order when we reach Null
ordBetween lo hi Null         = lo <= hi

이진 검색 트리 순서와 사이에 나무입니다 BotTop.

isBSTree :: Ord a => BinaryTree a -> Bool
isBSTree = ordBetween Bot Top

각 하위 트리에서 실제 극값을 계산하여 바깥쪽으로 버블 링하면 필요한 것보다 많은 정보를 얻을 수 있으며 왼쪽 또는 오른쪽 하위 트리가 비어있는 경우에 적합합니다. 요구 사항을 유지 관리하고 확인하여 내부로 밀어 넣는 것이 다소 균일합니다.


6

힌트는 다음과 같습니다. 보조 기능 만들기

isBSTree' :: (Ord a) => BinaryTree a -> BSTResult a

어디로 BSTResult a정의

data BSTResult a
   = NotBST             -- not a BST
   | EmptyBST           -- empty tree (hence a BST)
   | NonEmptyBST a a    -- nonempty BST with provided minimum and maximum

하위 트리의 결과를 활용하여 계산을 진행하기 위해 특히 최소 및 최대를 재귀 적으로 진행할 수 있어야합니다.

당신이있는 경우 예를 들어 tree = Node left 20 right, 함께 isBSTree' left = NonEmptyBST 1 14하고 isBSTree' right = NonEmptyBST 21 45, 다음 isBSTree' tree이어야한다 NonEmptyBST 1 45.

를 제외하고 같은 경우에는 tree = Node left 24 right대신에을 가져야 isBSTree' tree = NotBST합니다.

결과를 Bool로 변환하는 것은 사소한 일입니다.


1
또는 명백한 Monoid를 정의 BSTResult a하고 접습니다. :) (또는 합법적 인 Monoid가 아닌 경우에도 ....)
Will Ness

(그러나 어쨌든 그것은 합법적입니다)
Will Ness

3

, 목록을 정렬 할 필요가 없습니다. 모든 요소가 다음 요소보다 작거나 같은지 확인할 수 있습니다. 우리가이 작업을 수행 할 수 있기 때문에이 더 효율적입니다 O (n)의 정렬 된 목록을 평가하는 반면, 완전히 한다 (N O를 로그 N) .

따라서 다음을 통해이를 확인할 수 있습니다.

ordered :: Ord a => [a] -> Bool
ordered [] = True
ordered xa@(_:xs) = and (zipWith (<=) xa xs)

이진 트리가 다음과 같은 이진 검색 트리인지 확인할 수 있습니다.

isBSTree :: Ord a => BinaryTree a -> Bool
isBSTree = ordered . flattenTree

Null빈 트리이기 때문에 이진 검색 트리 라고 주장 할 수 있다고 생각 합니다. 따라서 모든 노드 (노드가 없음)에 대해 왼쪽 하위 트리의 요소가 노드의 값보다 작거나 같고 오른쪽 하위 트리의 요소가 모두 노드의 값보다 크거나 같습니다. .


1

다음과 같이 트리에서 왼쪽에서 오른쪽으로 진행할 수 있습니다.

isBSTtreeG :: Ord a => BinaryTree a -> Bool
isBSTtreeG t = gopher Nothing [Right t]
    where
    gopher  _   []                        =  True
    gopher  x   (Right Null:ts)           =  gopher x ts
    gopher  x   (Right (Node lt v rt):ts) =  gopher x (Right lt:Left v:Right rt:ts)
    gopher Nothing   (Left v:ts)          =  gopher (Just v) ts
    gopher (Just y)  (Left v:ts)          =  y <= v && gopher (Just v) ts

John McCarthy 's에서gopher 영감을 얻었습니다 .

명시 적 푸시 다운 목록은 연속 전달로 제거 할 수 있습니다.

isBSTtreeC :: Ord a => BinaryTree a -> Bool
isBSTtreeC t = gopher Nothing t (const True)
    where
    gopher  x   Null           g  =  g x 
    gopher  x   (Node lt v rt) g  =  gopher x lt (\case
                                       Nothing -> gopher (Just v) rt g
                                       Just y  -> y <= v && gopher (Just v) rt g)

지금까지 가장 큰 요소 하나만 유지 하면 충분합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.