一段时间以来,我一直在努力制定一种良好的排序算法。起初,我认为插入排序是个好主意,但列表很大时,会遇到与Haskell quicksort处理内存类似的问题。
然后我尝试组成自己的排序算法,该算法与插入排序的工作原理相同,但是它尝试减少内存使用并减少重复以提高速度:
modsort' :: (Ord a, Eq a) => [a] -> [(a, Int)]
modsort' [] = []
modsort' ls@(x:xs) = insert (x, count x ls) $ modsort' (filter (\i -> i /= x) xs)
where
insert :: (Ord a, Eq a) => (a, Int) -> [(a, Int)] -> [(a, Int)]
insert i1 [] = [i1]
insert i1@(x, _) i2@((y, f):xs)
| x <= y = i1:i2
| x > y = (y, f) : insert i1 xs
count :: Eq a => a -> [a] -> Int
count i xs' = count' i xs' 0
where count' _ [] n = n
count' i (x:xs) n
| i == x = count' i xs (n + 1)
| otherwise = count' i xs n
uncompress :: [(a, Int)] -> [a]
uncompress [] = []
uncompress ( (v, n) : rest) = repeat' v n ++ uncompress rest
where repeat' _ 0 = []
repeat' i n = i : repeat' i (n - 1)
与Haskell的其他一些算法相比,我在网上看到的这个算法似乎更长一些。对于具有很多重复(例如语言:单词,字母)的很长的列表,它的伸缩性很好,但是当列表几乎没有重复(Data.List sort能够排序[10000,9999..1]时,则完全失败) ]在2秒内花费了50)。
是否有一种方法可以改善此问题或忽略的一些小问题,还是应该尝试制定一种不同/更好的排序算法?