Standard library · Numbers and collections

sort

Sorting vectors with the default or your own comparison, binary search, and a dozen sorting algorithms to learn from.

import sort
On this page
  1. Functions

For most work two functions are enough: Sort for numbers and strings, and SortBy when you decide yourself what "smaller" means, students by their marks for instance.

The functions named after an algorithm (quick, merge, bubble and the rest) all do the same job and give the same result. Most of them are here for teaching and for comparing algorithms. Sort picks a fast, dependable one for you.

The functions whose names end in ed, such as Sorted, return a new vector and leave the original alone; the others sort the vector in place.

Functions

HeapSort

func HeapSort<T>(v: Vector<T>)
Heap sort: always fast, n log n, and needs no extra memory.
sort-Algorithms.salam
import sort

func main:
    data := [9, 4, 7, 1, 8, 2, 6, 3, 5, 0]
    repeat 13 in round:
        mut v := Vector {} as Vector<int>
        each n in data:
            v.push(n)
        end
        switch round:
            0: sort.QuickSort(v) break end
            1: sort.MergeSort(v) break end
            2: sort.HeapSort(v) break end
            3: sort.InsertionSort(v) break end
            4: sort.BinaryInsertionSort(v) break end
            5: sort.SelectionSort(v) break end
            6: sort.BubbleSort(v) break end
            7: sort.ShellSort(v) break end
            8: sort.CombSort(v) break end
            9: sort.CocktailSort(v) break end
            10: sort.GnomeSort(v) break end
            11: sort.OddEvenSort(v) break end
            12: sort.PancakeSort(v) break end
        end
        print sort.IsSorted(v), ""
        v.free()
    end
    println ""
    mut d := Vector {} as Vector<int>
    defer d.free()
    each n in data:
        d.push(n)
    end
    sort.IntroSort(d)
    println d
end
Outputtrue true true true true true true true true true true true true [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

CountingSort

func CountingSort(v: Vector<int>)
Counting sort for whole numbers; very fast when the range of values is small.
sort-IntSorts.salam
import sort

func main:
    repeat 3 in round:
        mut v := Vector {} as Vector<int>
        defer v.free()
        each n in [170, 45, 75, 90, 802, 24, 2, 66]:
            v.push(n)
        end
        if round == 0:
            sort.RadixSort(v)
        else round == 1:
            sort.CountingSort(v)
        else:
            sort.BucketSort(v)
        end
        println v
    end
end
Output[2, 24, 45, 66, 75, 90, 170, 802] [2, 24, 45, 66, 75, 90, 170, 802] [2, 24, 45, 66, 75, 90, 170, 802]

BinarySearch

func BinarySearch<T>(v: Vector<T>, x: T): int
Finds x in a sorted vector by binary search, or returns minus one when it is not there.
sort-BinarySearch.salam
import sort

func main:
    mut numbers := Vector {} as Vector<int>
    defer numbers.free()
    each n in [1, 3, 3, 3, 7, 9]:
        numbers.push(n)
    end
    println sort.BinarySearch(numbers, 7), sort.BinarySearch(numbers, 4)
    println sort.LowerBound(numbers, 3), sort.UpperBound(numbers, 3)
end
Output4 -1 1 4

LowerBound

func LowerBound<T>(v: Vector<T>, x: T): int
The first position whose element is not less than x: where x would be inserted to keep the vector sorted.

The example for this item is shown with the ones above: sort-BinarySearch.salam

UpperBound

func UpperBound<T>(v: Vector<T>, x: T): int
The first position whose element is greater than x. The distance between the upper and the lower bound is how many times x occurs.

The example for this item is shown with the ones above: sort-BinarySearch.salam

ShellSort

func ShellSort<T>(v: Vector<T>)
Shell sort, a faster insertion sort.

The example for this item is shown with the ones above: sort-Algorithms.salam

SortBy

func SortBy<T>(v: Vector<T>, less: func(T, T): bool)
Sorts the vector with the comparison function less; less(a, b) has to return true when a should come before b.
sort-SortBy.salam
import sort

struct Student:
    pub name: str = ""
    pub mark: int = 0
end

func main:
    mut class := Vector {} as Vector<Student>
    defer class.free()
    class.push(Student { name = "Sara", mark = 18 })
    class.push(Student { name = "Ali", mark = 15 })
    class.push(Student { name = "Reza", mark = 18 })
    class.push(Student { name = "Maryam", mark = 20 })
    higher := (a: Student, b: Student): ret a.mark > b.mark end
    sort.StableSortBy(class, higher)
    each s in class:
        print s.name, ""
    end
    println ""
    println sort.IsSortedBy(class, higher)
    lower := (a: Student, b: Student): ret a.mark < b.mark end
    ascending := sort.SortedBy(class, lower)
    println ascending.get(0).name
    sort.SortBy(class, lower)
    println class.get(0).name
end
OutputMaryam Sara Reza Ali true Ali Ali

StableSortBy

func StableSortBy<T>(v: Vector<T>, less: func(T, T): bool)
Like SortBy, but equal elements keep the order they were in; in the example Sara stays before Reza because she came first.

The example for this item is shown with the ones above: sort-SortBy.salam

SortedBy

func SortedBy<T>(v: Vector<T>, less: func(T, T): bool): Vector<T>
A sorted copy, using your own comparison.

The example for this item is shown with the ones above: sort-SortBy.salam

IsSortedBy

func IsSortedBy<T>(v: Vector<T>, less: func(T, T): bool): bool
True when the vector is sorted according to the comparison function.

The example for this item is shown with the ones above: sort-SortBy.salam

QuickSort

func QuickSort<T>(v: Vector<T>)
Quick sort, the fastest in practice for most data.

The example for this item is shown with the ones above: sort-Algorithms.salam

IsSorted

func IsSorted<T>(v: Vector<T>): bool
True when the vector is sorted in ascending order.
sort-Sort.salam
import sort

func main:
    mut numbers := Vector {} as Vector<int>
    defer numbers.free()
    each n in [5, 3, 9, 1, 7]:
        numbers.push(n)
    end
    println sort.IsSorted(numbers)
    ordered := sort.Sorted(numbers)
    println ordered, numbers
    sort.Sort(numbers)
    println numbers, sort.IsSorted(numbers)
    sort.SortDesc(numbers)
    println numbers
    sort.Reverse(numbers)
    println numbers, sort.Min(numbers), sort.Max(numbers)
    sort.Swap(numbers, 0, 4)
    println numbers
end
Outputfalse [1, 3, 5, 7, 9] [5, 3, 9, 1, 7] [1, 3, 5, 7, 9] true [9, 7, 5, 3, 1] [1, 3, 5, 7, 9] 1 9 [9, 3, 5, 7, 1]

Reverse

func Reverse<T>(v: Vector<T>)
Reverses the order of the vector's elements.

The example for this item is shown with the ones above: sort-Sort.salam

Min

func Min<T>(v: Vector<T>): T
The smallest element of the vector.

The example for this item is shown with the ones above: sort-Sort.salam

Max

func Max<T>(v: Vector<T>): T
The largest element of the vector.

The example for this item is shown with the ones above: sort-Sort.salam

RadixSort

func RadixSort(v: Vector<int>)
Radix sort for whole numbers; it sorts digit by digit and makes no comparisons.

The example for this item is shown with the ones above: sort-IntSorts.salam

PancakeSort

func PancakeSort<T>(v: Vector<T>)
Pancake sort, which sorts using nothing but reversals of a prefix. For teaching.

The example for this item is shown with the ones above: sort-Algorithms.salam

CocktailSort

func CocktailSort<T>(v: Vector<T>)
Cocktail sort, a bubble sort that runs left to right and back again on each pass.

The example for this item is shown with the ones above: sort-Algorithms.salam

CombSort

func CombSort<T>(v: Vector<T>)
Comb sort, an improved bubble sort.

The example for this item is shown with the ones above: sort-Algorithms.salam

SelectionSort

func SelectionSort<T>(v: Vector<T>)
Selection sort, which brings the smallest remaining element forward each time.

The example for this item is shown with the ones above: sort-Algorithms.salam

BucketSort

func BucketSort(v: Vector<int>)
Bucket sort for whole numbers; fast when the numbers are spread evenly over a range.

The example for this item is shown with the ones above: sort-IntSorts.salam

SortIndex

func SortIndex(idx &: Vector<int>, keys &: Vector<f64>)
Instead of sorting the data, sorts the indices in idx by keys in ascending order. Use it when several vectors share an order and you want to see all of them sorted together.
sort-SortIndex.salam
import sort

func main:
    names := ["Tehran", "Shiraz", "Tabriz"]
    mut population := Vector {} as Vector<f64>
    mut order := Vector {} as Vector<int>
    defer population.free()
    defer order.free()
    population.push(8.7)
    population.push(1.6)
    population.push(1.65)
    repeat 3 in i:
        order.push(i)
    end
    sort.SortIndex(order, population)
    each i in order:
        print names[i], ""
    end
    println ""
    sort.SortIndexDesc(order, population)
    each i in order:
        print names[i], ""
    end
    println ""
end
OutputShiraz Tabriz Tehran Tehran Tabriz Shiraz

SortIndexDesc

func SortIndexDesc(idx &: Vector<int>, keys &: Vector<f64>)
Like SortIndex, descending.

The example for this item is shown with the ones above: sort-SortIndex.salam

GnomeSort

func GnomeSort<T>(v: Vector<T>)
Gnome sort: like insertion sort, simple and slow.

The example for this item is shown with the ones above: sort-Algorithms.salam

Swap

func Swap<T>(v: Vector<T>, i: int, j: int)
Exchanges two elements of a vector.

The example for this item is shown with the ones above: sort-Sort.salam

InsertionSort

func InsertionSort<T>(v: Vector<T>)
Insertion sort, very good on small or nearly sorted vectors.

The example for this item is shown with the ones above: sort-Algorithms.salam

BinaryInsertionSort

func BinaryInsertionSort<T>(v: Vector<T>)
An insertion sort that finds the insertion point by binary search.

The example for this item is shown with the ones above: sort-Algorithms.salam

Sort

func Sort<T>(v: Vector<T>)
Sorts the vector in ascending order. The default choice for sorting.

The example for this item is shown with the ones above: sort-Sort.salam

SortDesc

func SortDesc<T>(v: Vector<T>)
Sorts the vector in descending order.

The example for this item is shown with the ones above: sort-Sort.salam

Sorted

func Sorted<T>(v: Vector<T>): Vector<T>
An ascending sorted copy of the vector; the original is unchanged.

The example for this item is shown with the ones above: sort-Sort.salam

OddEvenSort

func OddEvenSort<T>(v: Vector<T>)
Odd-even sort, designed for parallel processing.

The example for this item is shown with the ones above: sort-Algorithms.salam

BubbleSort

func BubbleSort<T>(v: Vector<T>)
Bubble sort: simple and slow, for teaching.

The example for this item is shown with the ones above: sort-Algorithms.salam

MergeSort

func MergeSort<T>(v: Vector<T>)
Merge sort: always fast and stable, but it needs extra memory.

The example for this item is shown with the ones above: sort-Algorithms.salam

IntroSort

func IntroSort<T>(v: Vector<T>)
Introsort: it starts as a quick sort and switches to a heap sort when it has to, so it never degrades.

The example for this item is shown with the ones above: sort-Algorithms.salam