我试图找出如何实现类似冒泡排序的排序方法,但在某些方面有所不同。
伪代码将是这样的:
以下是我对实现此问题的看法:
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].
答案 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]
此实现没有明确地“标记”移动的元素,但这不是必需的。