ST ã¢ããã®ä¸ã§ã¯ãé åã«å¯¾ãã¦ç ´å£çãªæä½ãã§ããã®ã§ã試ãã«ãã¼ãã½ã¼ããä½ã£ã¦ã¿ã¾ããããã¼ãã½ã¼ãã®ã¢ã«ã´ãªãºã ã¯ããç çã®ããã°ã©ãã³ã°ããåèã«ãã¾ããã
> x <- randomArray 10 100 > x array (1,10) [(1,71),(2,27),(3,85),(4,6),(5,79),(6,8),(7,58),(8,97),(9,25),(10,89)] > heapSort x array (1,10) [(1,6),(2,8),(3,25),(4,27),(5,58),(6,71),(7,79),(8,85),(9,89),(10,97)]
以ä¸ããã®ã³ã¼ãã§ãã(UArray ã«æå®ããã¤ã³ããã¯ã¹ãå¤ã®åå¶ç´ã¯ãã¾ãæ¸ããªãã¿ãããªã®ã§ãåã決ããã¡ã«ãã¦ãã¾ãã)
import Control.Applicative import Control.Monad import Control.Monad.ST import Data.Array.ST import Data.Array.Unboxed import Random ---------------------------------------------------------------- type Index = Int type Value = Int type UA = UArray Index Value type SUA s = STUArray s Index Value type PRED = Value -> Value -> Bool ---------------------------------------------------------------- heapSort :: UA -> UA heapSort ua = runSTUArray $ heapsort ua heapsort :: UA -> ST s (SUA s) heapsort ua = do let (beg,end) = bounds ua sua <- newArray_ (beg,end) -- this sets the type of 's' copy ua sua beg end forM_ [beg+1..end] $ shiftUp sua forM_ [end,end-1..beg+1] $ swapAndShiftDown sua beg return sua where copy from to beg end = forM_ [beg..end] $ \i -> writeArray to i (from ! i) swapAndShiftDown arr beg idx = swapAndDo arr beg (\_ _ -> True) idx (shiftDown arr beg (idx - beg)) shiftUp :: SUA s -> Index -> ST s () shiftUp _ 1 = return () shiftUp sua c = swapAndDo sua p (>) c (shiftUp sua p) where p = c `div` 2 shiftDown :: SUA s -> Index -> Index -> ST s () shiftDown sua p n | c1 > n = return () | c1 == n = swapAndDo sua p (>) c1 (return ()) | otherwise = do let c2 = c1 + 1 xc1 <- readArray sua c1 xc2 <- readArray sua c2 let c = if xc1 > xc2 then c1 else c2 swapAndDo sua p (>) c (shiftDown sua c n) where c1 = 2 * p swapAndDo :: SUA s -> Index -> PRED -> Index -> ST s () -> ST s () swapAndDo sua p op c cont = do xp <- readArray sua p xc <- readArray sua c when (xc `op` xp) $ do writeArray sua c xp writeArray sua p xc cont ---------------------------------------------------------------- randomArray :: Index -> Value -> IO UA randomArray n boundary = listArray (1,n) <$> getList where getList = replicateM n randomInt randomInt :: IO Int randomInt = getStdRandom (randomR (0,boundary))