简体   繁体   中英

Sort algorithm for list of integers in Haskell with recursion

I need to sort an integer list on haskell, from smaller to greater numbers, but i dont know where to start.

The recursion syntax is kinda difficult for me

A little bit of help would be great.

Ive done this but it does not solve my problem:

ordenarMemoria :: [Int] -> [Int]
ordenarMemoria [] = []
ordenarMemoria (x:y:xs) 
    | y > x = ordenarMemoria (y:xs)
    | otherwise = ordenarMemoria (x:xs)

Thanks

You attempt is on the right track for a bubble sort , which is a good starting place for sorting. A few notes:

You handle the cases when the list is empty or has at least two elements ( x and y ), but you have forgotten the case when your list has exactly one element. You will always reach this case because you are calling your function recursively on smaller lists.

ordenarMemoria [x] = -- how do you sort a 1-element list?

Second note: in this pattern

ordenarMemoria (x:y:xs) 
    | y > x = ordenarMemoria (y:xs)
    | otherwise = ordenarMemoria (x:xs)

you are sorting a list starting with two elements x and y . You compare x to y , and then sort the rest of the list after removing one of the two elements. This is all good.

The question I have is: what happened to the other element? A sorted list has to have all the same elements as the input, so you should use both x and y in the output. So in:

    | y > x = ordenarMemoria (y:xs)

you have forgotten about x . Consider

    | y > x = x : ordenarMemoria (y:xs)

which indicates to output x , then the sorted remainder.

The other branch forgets about one of the inputs, too.

After you fix the function, you might notice that the list gets a bit more sorted, but it is still not completely sorted. That's a property of the bubble sort—you might have to run it multiple times.

I'll highly recommend you read Learn You a Haskell , there is an online version here , it has a chapter where you can learn how to sort lists using recursion, like Quicksort for example:

quicksort :: (Ord a) => [a] -> [a]  
quicksort [] = []  
quicksort (x:xs) =   
    let smallerSorted = quicksort [a | a <- xs, a <= x]  
        biggerSorted = quicksort [a | a <- xs, a > x]  
    in  smallerSorted ++ [x] ++ biggerSorted  

I need to sort an integer list

How about sort from Data.List ?

$ stack ghci
Prelude> :m + Data.List
Prelude Data.List> sort [2,3,1]
[1,2,3]

There are lots of choices. I generally recommend starting with bottom-up mergesort in Haskell, but heapsort isn't a bad choice either. Quicksort poses much more serious difficulties.

-- Given two lists, each of which is in increasing
-- order, produce a list in increasing order.
--
-- merge [1,4,5] [2,4,7] = [1,2,4,4,5,7]
merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ???
merge xs [] = ???
merge (x : xs) (y : ys)
  | x <= y = ???
  | otherwise = ???

-- Turn a list of elements into a list of lists
-- of elements, each of which has only one element.
--
-- splatter [1,2,3] = [[1], [2], [3]]
splatter :: [a] -> [[a]]
splatter = map ????

-- Given a list of sorted lists, merge the adjacent pairs of lists.
-- mergePairs [[1,3],[2,4],[0,8],[1,2],[5,7]]
--   = [[1,2,3,4],[0,1,2,8],[5,7]]
mergePairs :: Ord a => [[a]] -> [[a]]
mergePairs [] = ????
mergePairs [as] = ????
mergePairs (as : bs : more) = ????

-- Given a list of lists of sorted lists, merge them all
-- together into one list.
--
-- mergeToOne [[1,4],[2,3]] = [1,2,3,4]
mergeToOne :: Ord a => [[a]] -> [a]
mergeToOne [] = ???
mergeToOne [as] = ???
mergeToOne lots = ??? -- use mergePairs here

mergeSort :: Ord a => [a] -> [a]
mergeSort as = ???? -- Use splatter and mergeToOne

Once you've filled in the blanks above, try optimizing the sort by making splatter produce sorted lists of two or perhaps three elements instead of singletons.

Here is a modified either quicksort or insertion sort. It uses the fastest method of prefixing or suffixing values to the output list. If the next value is less than or greater than the first or last of the list, it is simply affixed to the beginning or end of the list. If the value is not less than the head value or greater than the last value then it must be inserted. The insertion is the same logic as the so-called quicksort above.

Now, the kicker. This function is made to run as a foldr function just to reduce the complexity of the the function. It can easily be converted to a recursive function but it runs fine with foldr .

f2x :: (Ord a) => a -> [a] -> [a]
f2x n ls
   | null ls = [n]
   | ( n <= (head ls) ) = n:ls -- ++[11]
   | ( n >= (last ls) ) = ls ++ [n] -- ++ [22]
   | True = [lx|lx <-ls,n > lx]++ n:[lx|lx <-ls,n < lx]

The comments after two line can be removed and the function can be run with scanr to see how many hits are with simple prefix or suffix of values and which are inserted somewhere other that the first or last value.

foldr f2x [] [5,4,3,2,1,0,9,8,7,6]

Or af = foldr a2x [] ... af [5,4,3,2,1,0,9,8,7,6] >-> [0,1,2,3,4,5,6,7,8,9]

EDIT 5/18/2018

The best thing about Stack Overflow is the people like @dfeuer that make you think. @dfeuer suggested using partition . I am like a child, not knowing how. I expressed my difficulty with partition but @dfeuer forced me to see how to use it. @dfeuer also pointed out that the use of last in the above function was wasteful. I did not know that, either.

The following function uses partition imported from Data.List . partition outputs a tuple pair. This function is also meant to use with foldr . It is a complete insertion sort function.

ft nv ls = b++[nv]++e where (b,e) = partition (<=nv) ls

Use it like above

foldr ft [] [5,4,3,2,1,0,9,8,7,6]

Haskell and functional programming is all about using existing functions in other functions.

putEleInSortedListA :: Ord a => a -> [a] -> [a]
putEleInSortedListA a [] = [a]
putEleInSortedListA a (b:bs)
  | a < b     = a : b : bs
  | otherwise = b: putEleInSortedListA a bs

sortListA :: Ord a => [a] -> [a]
sortListA la = foldr (\a b -> putEleInSortedListA a b) [] la

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM