在功能样式中实现heapify操作

时间:2012-01-02 03:39:46

标签: haskell functional-programming ocaml

只是想知道有没有办法以功能样式实现heapify操作?

假设数据类型为:

type 'a heap = Empty | Node of  'a * 'a heap * 'a heap

2 个答案:

答案 0 :(得分:6)

在Haskell中说你的类型是

data Heap a = Empty | Node a (Heap a) (Heap a)

假设我们想要一个最大堆。让我们从一个函数moveDown开始,它修复一个可能有一个不正确的根的几乎堆。

moveDown :: (Ord a) => Heap a -> Heap a
moveDown Empty = Empty
moveDown h@(Node x Empty Empty) = h
moveDown (Node x (Node y Empty Empty) Empty) = Node larger (Node smaller Empty Empty) Empty
where
    (larger, smaller) = if x >= y then (x,y) else (y,x)
moveDown h@(Node x le@(Node y p q) ri@(Node z r s) )
    | (x >= y) && (x >= z) = h
    | (y >= x) && (y >= z) = Node y (moveDown (Node x p q)) ri
    | (z >= x) && (z >= y) = Node z le (moveDown (Node x r s))

请注意,由于堆的结构,如果节点具有左子节点但没有右子节点,则左子节点没有子节点。此外,节点不可能有一个正确的孩子但没有左孩子。

现在heapify很简单:

heapify :: (Ord a) => Heap a -> Heap a
heapify Empty = Empty
heapify (Node x p q) = moveDown (Node x (heapify p) (heapify q))

答案 1 :(得分:0)

附加heapify和heapsort的代码..

`

import qualified Data.Char as C
import qualified Data.List as L
import qualified Data.Map as M

type Value = Int
data Heap = Nil
          | Node Heap Value Heap

instance Show Heap where
  show = showHeap 0

type Indent = Int

tabs :: Int -> String
tabs n = replicate n '\t'

showHeap :: Indent -> Heap -> String
showHeap indent Nil = tabs indent
showHeap indent (Node l v r) = concat $ (map (\s -> "\n" ++ (tabs indent)  ++ s) [showHeap (indent+1) l, show v, showHeap (indent+1) r])

height :: Heap -> Int
height Nil = 0
height (Node l _ r) = 1 + max (height r) (height l) 

emptyHeap :: Heap
emptyHeap = Nil

heapify :: [Int] -> Heap
heapify vs = heapify' vs emptyHeap
  where
    heapify' :: [Value] -> Heap -> Heap
    heapify' [] hp = hp
    heapify' (v:vs) hp = heapify' vs (insertIntoHeap v hp)

insertIntoHeap :: Value -> Heap -> Heap
insertIntoHeap v' Nil = Node Nil v' Nil
insertIntoHeap v' (Node l v r) | v' <= v = if (height l <= height r) 
                                           then (Node (insertIntoHeap v l) v' r)
                                           else (Node l v' (insertIntoHeap v r))
                               | otherwise = if (height l <= height r)
                                             then (Node (insertIntoHeap v' l) v r)
                                             else (Node l v (insertIntoHeap v' r))

removeMin :: Heap -> (Value, Heap)
removeMin (Node l v r) = (v, mergeHeaps l r)

removeNMinFromHeap :: Heap -> Int -> [Value]
removeNMinFromHeap Nil _ = []
removeNMinFromHeap _ 0 = []
removeNMinFromHeap h n = (m:(removeNMinFromHeap h' (n-1)))
  where
    (m, h') = removeMin h

mergeHeaps :: Heap -> Heap -> Heap
mergeHeaps Nil h = h
mergeHeaps h Nil = h
mergeHeaps l@(Node l1 v1 r1) r@(Node l2 v2 r2) | v1 <= v2 = (Node (mergeHeaps l1 r1) v1 r)
                                               | otherwise = Node l v2  (mergeHeaps l2 r2)


heapSort :: [Value] -> [Value]
heapSort xs = removeNMinFromHeap heaped (length xs)
  where
    heaped = heapify xs

input :: [Value]
input = [3,2,1,4,3,2,10,11,2,5,6,7]

input2 :: [Value]
input2 = concat $ replicate 2 [3,2,1,4,3,2,10,11,2,5,6,7]

h1 :: Heap
h1 = heapify input

`