haskell bubblesort在第一步停止

时间:2015-10-20 04:28:01

标签: sorting haskell

为什么这段代码只排序一次?它应该去递归吗? 我尝试复制和使用函数几次但结果相同

import Data.Char(digitToInt)
main = do
    let input = "014191633811200332532482200388402372212502263534033843815342500002960238365203448225037732492472423604003650332739521403775274133234120141613263263284258349238980000299142823491385101303491002740220381422901923619346834530150013398923221429717193717"
    print $ bubblesort input

bubblesort input 
   | input == sorted = sorted 
   | otherwise       = bubblesort sorted
  where 
     sorted = sort_once input

sort_once::String->String
sort_once [] = []
sort_once (x:[]) = x:[]
sort_once (x:y:[]) = sort_two x y
sort_once input@(x:y:xy) = (sort_two x y)++(sort_once xy)


--sort_two::String=>Char->Char
sort_two aa bb |
 a<b = aa:bb:[]::String |
 otherwise = bb:aa:[]::String
  where 
   a=digitToInt aa::Int
   b=digitToInt bb::Int

如果有兴趣我使用下面的提示修改代码,感谢大家的答案:

import Data.Char(digitToInt)
main = do
    let input = "014191633811200332532482200388402372212502263534033843815342500002960238365203448225037732492472423604003650332739521403775274133234120141613263263284258349238980000299142823491385101303491002740220381422901923619346834530150013398923221429717193717"
    let result = bubblesort (string_to_int_arr input) ::[Int]
    print result

bubblesort::[Int]->[Int]
bubblesort input 
 | (input == sorted) = sorted 
 | otherwise = bubblesort sorted
  where 
   sorted = sort_once input

string_to_int_arr :: String->[Int]
string_to_int_arr input = map (read . (:"")) input :: [Int]

sort_once::[Int]->[Int]
sort_once [] = []
sort_once (x:[]) = x:[]
sort_once (x:y:[]) = (lesser x y):(greater x y):[]
sort_once (x:y:xy) = (lesser x y):(sort_once $ (greater x y):xy)


greater::Int->Int->Int
greater a b
 | a>b=a 
 | otherwise=b

lesser::Int->Int->Int
lesser a b
 | a<b=a 
 | otherwise=b

1 个答案:

答案 0 :(得分:3)

sort_once未实现bubblesort迭代。记住bubblesort的整体想法:你想“一直冒出最大的元素”。

但是,假设你在开始时拥有最大的元素,之后有一些任意元素,比如"321"sort_once会发生什么?

sort_once "321" = sort_two '3' '2' ++ sort_once "1"
                = sort_two '3' '2' ++ "1"
                = ['2', '3']       ++ sort_once "1"
                = "231"

如果sort_once应该反映完整的bubblesort迭代,则这是不正确的。毕竟,最大的元素现在停留在第二个位置而不是最后一个位置。 sort_once的下一次使用不会改变:

sort_once "231" = sort_two '2' '3' ++ sort_once "1"
                = sort_two '2' '3' ++ "1"
                = ['2', '3']  ++ sort_once "1"
                = "231"

因此,您的“排序”会在一次迭代后停止。你可能会问,如何解决这个问题。好吧,在sort_once的递归调用中,您需要考虑更大的元素:

sort_once (x:y:xy) = 
   let [lesser, greater] = sort_two x y
   in lesser : (sort_once (greater : xy))
   --                      ^^^^^^^
   --  still look at the greater element

顺便说一下,这应该鼓励您将sort_two的类型更改为Char -> Char -> (Char, Char)。毕竟,sort_two返回的列表应该总是有两个元素。

锻炼

  • 目前,您的代码使用中间Int来比较两个字符。但是,您可以将字符与<>进行比较。尝试在没有sort_two的情况下实施digitToInt
  • 现在您已在<中使用了>sort_two,概括了sort_oncesort,以便您可以对[Int]进行排序, [Integer],或任何其他可以比较的东西。提示:查看(<)
  • 的类型