【问题标题】:Implementing a sorting method similar to bubble sort实现类似于冒泡排序的排序方法
【发布时间】:2012-06-14 21:35:05
【问题描述】:

我试图弄清楚如何实现一种类似于冒泡排序但在某些方面有所不同的排序方法。

伪代码如下:

  1. 获取列表并获取列表中的第一个元素
  2. 如果它旁边的元素更小,则交换元素
  3. 否则将元素标记为已移动并重复,直到所有元素都被标记

这是我对实现这个问题的想法:

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].

【问题讨论】:

    标签: list sorting haskell


    【解决方案1】:

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

    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]
    

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

    【讨论】:

    • 好吧,这行得通,这和说的一样吗:bubble' lis@(x:y:xs) = if x > y then y:bubble' (x:xs) else x: bubble( y:xs) 。我已经尝试过猜测我在测试之前没有在控制台中重新加载。但是谢谢你,我想我后来的方法有点矫枉过正。
    • 是的。哦,顺便说一句,没有必要做lis@(x:y:xs),只需括号中的部分就足够了。否则,您将整个列表分配给lis,而无需使用它。如果你使用 -Wall 运行 GHC 会警告你这些事情
    • 感谢您的 -Wall 命令,现在正在使用它。感谢您的帮助,这是无价之宝。
    【解决方案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])
    

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

    【讨论】:

    • 感谢您的代码。我正在处理一种类似于冒泡排序但不完全相似的排序方法。它使每个元素(从元素 0 开始)冒泡,例如 [3,4,2,1,7] 将返回 [3,1,2,4,7]。
    【解决方案3】:

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

    【讨论】:

    • 是的,谢谢。在我修复它之后,我的代码仍然总是返回有序列表,你是否一眼就看到了一些错误?我想要完成的是,如果我有一个列表 [4,2,5,1],那么程序会调用 sortMe 并带有一个列表和一个要排序的元素,直到 lis1 为空,所以列表 [4,2,5,1 ] 会变成 [2,4,1,5]。谢谢你的收获
    猜你喜欢
    • 2012-07-23
    • 2017-03-11
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2013-02-02
    • 2014-02-20
    • 1970-01-01
    相关资源
    最近更新 更多