Task: Sorting algorithms_Cocktail sort with shifting bounds


C++: #include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <vector>


template <typename iterator>
void cocktail_shaker_sort(iterator begin, iterator end) {
    if (begin == end)
        return;
    for (--end; begin < end; ) {
        iterator new_begin = end;
        iterator new_end = begin;
        for (iterator i = begin; i < end; ++i) {
            iterator j = i + 1;
            if (*j < *i) {
                std::iter_swap(i, j);
                new_end = i;
            }
        }
        end = new_end;
        for (iterator i = end; i > begin; --i) {
            iterator j = i - 1;
            if (*i < *j) {
                std::iter_swap(i, j);
                new_begin = i;
            }
        }
        begin = new_begin;
    }
}

template <typename iterator>
void print(iterator begin, iterator end) {
    if (begin == end)
        return;
    std::cout << *begin++;
    while (begin != end)
        std::cout << ' ' << *begin++;
    std::cout << '\n';
}

int main() {
    std::vector<int> v{5, 1, -6, 12, 3, 13, 2, 4, 0, 15};
    std::cout << "before: ";
    print(v.begin(), v.end());
    cocktail_shaker_sort(v.begin(), v.end());
    assert(std::is_sorted(v.begin(), v.end()));
    std::cout << "after: ";
    print(v.begin(), v.end());
    return 0;
}



Go: package main

import (
    "fmt"
    "math/rand"
    "time"
)


func cocktailShakerSort(a []int) {
    var begin = 0
    var end = len(a) - 2
    for begin <= end {
        newBegin := end
        newEnd := begin
        for i := begin; i <= end; i++ {
            if a[i] > a[i+1] {
                a[i+1], a[i] = a[i], a[i+1]
                newEnd = i
            }
        }
        end = newEnd - 1
        for i := end; i >= begin; i-- {
            if a[i] > a[i+1] {
                a[i+1], a[i] = a[i], a[i+1]
                newBegin = i
            }
        }
        begin = newBegin + 1
    }
}


func cocktailSort(a []int) {
    last := len(a) - 1
    for {
        swapped := false
        for i := 0; i < last; i++ {
            if a[i] > a[i+1] {
                a[i], a[i+1] = a[i+1], a[i]
                swapped = true
            }
        }
        if !swapped {
            return
        }
        swapped = false
        for i := last - 1; i >= 0; i-- {
            if a[i] > a[i+1] {
                a[i], a[i+1] = a[i+1], a[i]
                swapped = true
            }
        }
        if !swapped {
            return
        }
    }
}

func main() {
    
    a := []int{21, 4, -9, 62, -7, 107, -62, 4, 0, -170}
    fmt.Println("Original array:", a)
    b := make([]int, len(a))
    copy(b, a) 
    cocktailSort(a)
    fmt.Println("Cocktail sort :", a)
    cocktailShakerSort(b)
    fmt.Println("C/Shaker sort :", b)

    
    rand.Seed(time.Now().UnixNano())
    fmt.Println("\nRelative speed of the two sorts")
    fmt.Println("  N    x faster (CSS v CS)")
    fmt.Println("-----  -------------------")
    const runs = 10 
    for _, n := range []int{1000, 2000, 4000, 8000, 10000, 20000} {
        sum := 0.0
        for i := 1; i <= runs; i++ {
            
            
            nums := make([]int, n)
            for i := 0; i < n; i++ {
                rn := rand.Intn(100000)
                if i%2 == 1 {
                    rn = -rn
                }
                nums[i] = rn
            }
            
            nums2 := make([]int, n)
            copy(nums2, nums)

            start := time.Now()
            cocktailSort(nums)
            elapsed := time.Since(start)
            start2 := time.Now()
            cocktailShakerSort(nums2)
            elapsed2 := time.Since(start2)
            sum += float64(elapsed) / float64(elapsed2)
        }
        fmt.Printf(" %2dk      %0.3f\n", n/1000, sum/runs)
    }
}