只是想知道有没有办法以功能样式实现heapify操作?
假设数据类型为:
type 'a heap = Empty | Node of 'a * 'a heap * 'a heap
答案 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
`