如何对单向链表进行排序。 (这里的问题是单链表的属性+使用LinkedList进行排序比数组更难) 我希望看到伪代码。
请尽可能使其在时间和空间上效率最高。
谢谢!
检查列表是否为空或只有一个元素。如果是,则返回未更改的列表。
将列表分成两半。对两部分进行合并排序。
通过重复从两个列表中取出较小的元素来合并列表。由于部分列表已经排序,因此这只是查看两个列表中的第一个元素并选择较小的元素的问题。
返回合并后的列表。
import Data.List(splitAt)
--Mergesorts a list by smallest element first.
sort :: Ord a => [a] -> [a]
sort = sortBy (<)
--Generic sort that can sort in any order.
sortBy :: (a -> a -> Bool) -> [a] -> [a]
sortBy _ [] = []
sortBy _ [x] = [x]
sortBy f xs = merge f (sortBy f first) (sortBy f second)
where
(first,second) = split xs
--Splits a list in half.
split :: [a] -> ([a],[a])
split xs = splitAt (halfLength xs) xs
--Returns a lists length divided by two as a whole number (rounded).
halfLength :: [a] -> Int
halfLength = round . (/2) . fromIntegral . length
--Merges two lists in the provided order.
merge :: (a -> a -> Bool) -> [a] -> [a] -> [a]
merge _ [] [] = []
merge _ [] (y:ys) = y:ys
merge _ (x:xs) [] = x:xs
merge f (x:xs) (y:ys) =
if f x y
then x : merge f xs (y:ys)
else y : merge f (x:xs) ys
由于链表仅是由其他项指向的一些项,因此您可以使用O(n)时间和O(n)空间构建指针数组,使用任何出色的排序算法进行排序,其时间复杂度为O(n log n),空间复杂度为O(1),然后使用O(n)时间和O(1)空间从头开始重构链表。
总体而言,这是O(n log n)时间和O(n)空间。
插入排序和快速排序在单链表上的效率与数组相同。