elixr 实现排序算法
冒泡排序:
defmodule BubbleSort do
@moduledoc """
Implementation of BubbleSort algorithm (https://en.wikipedia.org/wiki/Bubblesort)
Given an array of numbers, sorts it in ascending order
using the bubblesort algorithm.
Bubble sort algorithm uses a simple iterative strategy.
Starting with the first element, it compares it with the second element; if
the first one is larger, it swaps them, remembers that it performed a swap,
and continues to compare elements two and three, three and four and so forth.
When it reaches the end of the array, if at least one swap was performed, it
starts again at the beginning; if no swap was performed, the array is sorted,
and the algorithm terminates.
Example (the star denotes the current element):
[*2, 1, 5, 4, 3]
1. 2 is larger than 1: swap them
2. [1, *2, 5, 4, 3]
3. 2 is smaller than 5: no swap, continue at next element
4. [1, 2, *5, 4, 3]
5. 5 is larger than 4: swap them
6. [1, 2, 4, *5, 3]
7. 5 is larger than 3: swap them
8. [1, 2, 4, 3, *5]
9. end of array is reached; we performed at least one swap, so start again
10. [*1, 2, 4, 3, 5]
11. 1 is smaller than 2: no swap, continue at next element
12. [1, *2, 4, 3, 5]
13. 2 is smaller than 4: no swap, continue at next element
14. [1, 2, *4, 3, 5]
15. 4 is larger than 3: swap them
14. [1, 2, 3, *4, 5]
15. 4 is smaller than 5: no swap, continue at next element
16. [1, 2, 3, 4, *5]
17. end of array is reached; we performed at least one swap, so start again
(we'll skip the last couple of steps - the array is sorted, no swaps are performed, and the algorithm terminates)
[2, 1, 5, 4, 3] => [1, 2, 3, 4, 5]
Complexity: O(n*n)
"""
require Integer
@doc """
take a List and return the List with the numbers ordered
"""
@spec bubble_pass(list(Integer)) :: list(Integer)
def bubble_pass([]), do: []
def bubble_pass([x]), do: [x]
def bubble_pass([x1 | [x2 | xs]]) do
case x1 < x2 do
true -> Enum.concat([x1], bubble_pass(Enum.concat([x2], xs)))
false -> Enum.concat([x2], bubble_pass(Enum.concat([x1], xs)))
end
end
@spec bubble_sort(list(Integer)) :: list(Integer)
def bubble_sort(lst) do
bpassed = bubble_pass(lst)
case bpassed == lst do
true -> bpassed
false -> bubble_sort(bpassed)
end
end
end
快速排序
defmodule QuickSort do
@moduledoc """
Implementation of QuickSort algorithm (https://en.wikipedia.org/wiki/Quicksort)
You will be given an array of numbers, you have to sort numbers in ascending order
using quick sort algorithm.
Quick sort algorithm uses a divide and conquer strategy.
It takes a pivot, and sort other numbers in functions of the pivot, divided them
in a smaller and a bigger group. Execute this step until there is empty list.
Example:
[2, 1, 5, 4, 3]
1. pivot:2 smaller:[1] bigger:[5, 4, 3]
2. 2 [1] [5, 4, 3]
3. 2 [1] |
| 5 [4, 3] []
4. 2 [1] |
| 5 |
| 4 [3] []
5. [1, 2, 3, 4, 5] # Recursion reunite all splited lists.
[2, 1, 5, 4, 3] => [1, 2, 3, 4, 5]
Complexity: O(n log n)
"""
require Integer
@doc """
take a List and return the List with the numbers ordered
"""
@spec quick_sort(list(Integer)) :: list(Integer)
def quick_sort([]), do: []
def quick_sort([head | tail]) do
smaller = Enum.filter(tail, fn x -> x <= head end) |> quick_sort()
bigger = Enum.filter(tail, fn x -> x > head end) |> quick_sort()
Enum.concat(smaller, [head]) |> Enum.concat(bigger)
end
end
归并排序:
defmodule MergeSort do
@moduledoc """
Implementation of MergeSort algorithm (https://en.wikipedia.org/wiki/Merge_sort)
You will be given an array of numbers, you have to sort numbers in ascending order
using merge sort algorithm.
Merge sort algorithm uses a divide and conquer strategy.
It divide a list in two half. We compare the two heads of the halfs.
If the left one is smaller, we recursively sort with merge on tail of
left and the all right, and we put the head left at the top.
Else we do the same on reversed.
Example:
1. [2, 1, 5, 4, 3]
2. [2, 1, 5] [4, 3]
3. [2] [1, 5] | [3] [4]
4. [1, 2, 5] | [3] [4]
5. [1, 2, 3, 4, 5] # Recursite reunite all the small lists
[2, 1, 5, 4, 3] => [1, 2, 3, 4, 5]
Complexity: O(n log n)
"""
require Integer
@doc """
take a List and return the List with the numbers ordered
"""
@spec merge_sort(list(Integer)) :: list(Integer)
def merge_sort([]), do: []
def merge_sort([x]), do: [x]
def merge_sort(numbers) do
l = length(numbers)
half = div(l, 2)
right = merge_sort(Enum.take(numbers, half))
left = merge_sort(Enum.drop(numbers, half))
merge(right, left)
end
@spec merge(list(Integer), list(Integer)) :: list(Integer)
defp merge(left, []), do: Enum.concat([left])
defp merge([], right), do: Enum.concat([right])
defp merge([h_left | t_left], [h_right | t_right]) do
case h_left < h_right do
true -> merge(t_left, [h_right] ++ t_right) |> concat(h_left)
false -> Enum.concat([h_left], t_left) |> merge(t_right) |> concat(h_right)
end
end
@spec concat(list(Integer), Integer) :: list(Integer)
defp concat(list, element), do: Enum.concat([element], list)
end
选择排序:
defmodule SelectionSort do
@moduledoc """
Implementation of SelectionSort algorithm (https://en.wikipedia.org/wiki/Selection_sort)
You will be given an array of numbers, you have to sort numbers in ascending order
using selection sort algorithm.
The algorithm divides the input list into two parts:
- A sorted sublist of items which is built up from left to right at the front (left) of the list
- A sublist of the remaining unsorted items that occupy the rest of the list
Initially, the sorted sublist is empty and the unsorted sublist is the entire input list.
The algorithm proceeds by finding the smallest (or largest, depending on sorting order)
element in the unsorted sublist, exchanging (swapping) it with the leftmost unsorted
element (putting it in sorted order), and moving the sublist boundaries one element to the right.
Example:
Input: [11, 25, 12, 22, 64]
| Sorted sublist | Unsorted sublist | Least element in unsorted list
| [] | [11, 25, 12, 22, 64] | 11
| [11] | [25, 12, 22, 64] | 12
| [11, 12] | [25, 22, 64] | 22
| [11, 12, 22] | [25, 64] | 25
| [11, 12, 22, 25] | [64] | 64
| [11, 12, 22, 25, 64]| [] |
Complexity: O(n^2)
"""
require Integer
@doc """
take a List and return the List with the numbers ordered
"""
@spec selection_sort(list(Integer)) :: list(Integer)
def selection_sort(list) do
do_selection(list, [])
end
def do_selection([head | []], acc) do
acc ++ [head]
end
def do_selection(list, acc) do
min = min(list)
do_selection(:lists.delete(min, list), acc ++ [min])
end
defp min([first | [second | []]]) do
smaller(first, second)
end
defp min([first | [second | tail]]) do
min([smaller(first, second) | tail])
end
defp smaller(e1, e2) do
if e1 <= e2 do
e1
else
e2
end
end
end