2013-08-18 3 views
1
insertionSort :: (Ord a) => [a] -> [a] 
insertionSort (x:xs) = insertionSortIter [x] xs 
    where insertionSortIter sorted []  = sorted 
      insertionSortIter sorted (x:xs) = insertionSortIter (insert x sorted (length sorted)) xs 
      insert x list n --insert x in list at n 
       | n == 0 = x:list 
       | x < list !! (n - 1) = insert x list (n - 1) 
       | otherwise = firstns ++ (x:other) where (firstns, other) = splitAt n list 
-- [1..10000] 30s      
mergeSort :: (Ord a) => [a] -> [a] 
mergeSort (x:[])  = [x] 
mergeSort list  = merge (mergeSort list1) (mergeSort list2) 
     where (list1, list2) = splitAt (length list `div` 2) list 
       merge [] list  = list 
       merge list []  = list 
       merge (x:xs) (y:ys) = if x < y then x:(merge xs (y:ys)) else y:(merge (x:xs) ys) 
-- [1..10000] 2.4s 

Время исполнения указано со временем постройки (при 1 или 1,5 с). Но все же вы можете почувствовать разницу.Медленная сортировка вставки

Возможно, проблема заключается в выполнении каждой ветви в защите insert или firstns ++ (x:other) слишком медленно. Но в любом случае, чтобы поместить элемент в конец списка, мне нужно пройти весь список для O (n).

+1

и в чем вопрос? –

+0

'insertionSortIter' выполняет итерацию через позиции O (n) и вызывает на каждой итерации оператор O (n) -time' !! ', делая его O (n^2) просто для вставки одного элемента. Не делай этого. –

+0

ДМИТРИЙ, рад вас видеть. почему так медленно. Что я делаю не так. – vlastachu

ответ

2

Ваша insert функция работает медленно. Вот как это сделать вставки рода:

insertionSort :: Ord a => [a] -> [a] 
insertionSort xs = f [] xs 
    where 
    f rs []  = rs 
    f rs (x:xs) = f (insert x rs) xs 

    insert x []   = [x] 
    insert x [email protected](r:rs) = if x < r then x:rrs else r:insert x rs 

В случае путаницы, синтаксис [email protected](r:rs) означает, что rrs является всем списком, r является его головой, и rs является его хвостом.

insert просматривает список и помещает все элементы, которые должны быть перед x, то тушит x следуют элементы, которые должны быть после x.

+0

Ницца, спасибо! В оригинальной вставке сортировка O (n) в лучшем случае. Итак, O (n) в худшем случае, и, похоже, мы ничего не можем с этим поделать. – vlastachu

+0

Вы можете использовать foldr вместо f. – augustss

+0

Таким образом, конечным кодом является 'insertionSort (x: xs) = foldr insert [x] xs'. Очень хорошо. По какой-то причине в моей голове была мысль, что мы не можем получить список в foldr. Довольный тем, что этот стереотип нарушен. hmm, но с foldr sort работает нелинейно медленнее. – vlastachu