实现类似于冒泡排序的排序方法

时间:2012-06-12 00:48:07

标签: list sorting haskell

我试图找出如何实现类似冒泡排序的排序方法,但在某些方面有所不同。

伪代码将是这样的:

  1. 获取列表并获取列表中的第一个元素
  2. 如果旁边的元素较小,则交换元素
  3. else将元素标记为已移动并重复,直到所有元素都标记为
  4. 以下是我对实现此问题的看法:

    sortElement [] elm= []
    sortElement [x] elm= [x]
    sortElement lis@(x:y:xs) elm = 
    --first if is to find the element in the list that i want to move
    if elm /=x  
    then x:sortElement(y:xs) elm 
    else if x > y then y:sortElement(x:xs) elm 
    else lis
    
    stackBubble lis = stackBubble' lis lis
    
    stackBubble' [] [] = [] 
    stackBubble' [x] [] = [x]
    stackBubble' [] [x] = []
    stackBubble' lis@(x:xs) lis1@(x1:xs1) = do 
    
    sortElement(stackBubble' lis xs1) x1
    

    我得到的错误是

      

    函数stackBubble'

    中的非穷举模式

    如果我喜欢别处的建议:

    sortElement(x:stackBubble' xs xs1) x1
    

    一次迭代后我得到一个完全排序的列表,当我想得到这样的东西时:

    [4,2,7,1] => iterating 4 [2,4,7,1], after iterating all the elements [2,4,1,7].
    

3 个答案:

答案 0 :(得分:2)

您收到错误是因为stackBubble'在一个参数为空且另一个参数有多个元素时未指定结果。

答案 1 :(得分:2)

我开始编写更正版本的代码,但在我这样做的时候问题得到了回答。为了演示,我会把它包括在这里:

bubbleSort l =
  bSort l []
  where bSort []        acc = acc
        bSort [x]       acc = acc ++ [x]
        bSort (x:y:xys) acc
          | x > y     = bSort (acc ++ (y:x:xys)) []
          | otherwise = bSort (y:xys) (acc ++ [x])

请注意,即使按冒泡排序标准,这可能也非常低效,因为所有列表连接(最有可能优先附加到累加器列表的头部,然后在必要时反转)。这种实现非常幼稚,但是相当简洁,也许是有启发性的,尽管更多是因为它的粗犷而不是任何积极的美德。

答案 2 :(得分:2)

解决这个问题的最简单方法可能是使用警卫和简单的递归,例如:

bubble :: Ord a => [a] -> [a]
bubble (x:y:xs) | x > y = y : bubble (x : xs)
                | otherwise = x : bubble (y : xs)
bubble x = x

你有防护罩了吗?万一你还没有,我会简单解释一下。警卫的语法是

| (expression that evaluates to Bool) = code

就像模式匹配一​​样,Haskell将从上到下检查守卫并执行第一个返回true的守卫。 otherwise是“堕落案例”,其定义为True

逐行完成代码:

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

我们将列表分成x:y:xs并运行第一个保护,检查y是否小于x,如果是y,则附加到我们正在构建的结果列表中,并使用(x: XS)。

                | otherwise = x : bubble (y : xs)

第二个警卫总是返回True,将x保持在它的位置并再次调用气泡,列表仍然是相同的顺序。
最后一行只返回最后一个元素,或者如果你用空列表调用该函数,则返回一个空列表。

假设示例列表[4,2,5,1],执行将如下所示:

1: 2 is smaller than 4 -> 2 : bubble [4,5,1]
2: 5 is not smaller than 4 -> 2 : 4 : bubble [5,1]
3: 1 is smaller than 5 -> 2 : 4 : 1 : bubble [5]
4: end of list -> 2 : 4 : 1 : 5 -> [2,4,1,5]

此实现没有明确地“标记”移动的元素,但这不是必需的。