Time：2021-10-27

# origin

Recently read < < my first algorithm book > > ([Japan] Ishida Baohui; Miyazaki Xiuyi)
This series of notes is intended to use golang exercises

# Insert sort

``````Insertion sort is an algorithm to sort data from the left end of the sequence.

In the sorting process, the data on the left is returned one after another,
The data left on the right is the data that has not been sorted.

The idea of inserting sorting is to take out a data from the unordered area on the right,
Then insert it into the appropriate position in the sorted area.

The time complexity is the same as that of bubble sorting, which is O (n ^ 2).

From < < my first algorithm book > > [Japan] Ishida Baohui; Miyazaki Xiuyi``````

# Basic process

1. Given array to be sorted data [n]
2. If n < = 1, return directly
3. Treat data  as sorted
4. Starting at position 1, “insert” to the sorted area on the left
5. Similar to bubble sorting, compare data  with the number in front of it
6. Because the sorted area is on the left, this round of comparison can be terminated when the first smaller number is encountered. The previous number will only be smaller and there is no need to compare
7. Cycle 4-6 until all the numbers on the right are inserted into the left area to complete the sorting

# Improvement process (binary insertion)

1. Since the left area is a sorted area, you can use the binary search method to quickly locate the insertion position
2. Given the sorted area data [0: n] on the left
3. Ready to insert data [n + 1]
4. Initial state, set left = 0, right = n-1
5. Take position P = (left + right) / 2
6. Compare data [P] with data [n + 1]
7. If data [P] = = data [n + 1], insert position P directly
8. If the data [P] is larger, it means that the target position is still more left, set right = P – 1
9. If the data [P] is smaller, it means that the target position is still more right, set left = P + 1
10. Cycle 5-9 steps until left and right converge to the same position
11. Compare data [left] with data [n + 1]. If it is less than or equal to, insert it into the left + 1 position; otherwise, insert it into the left position
12. Cycle steps 3-11 until all the numbers on the right are inserted into the left area to complete the sorting

# target

• Implement and verify the ordinary insertion sort and binary insertion sort, and observe the efficiency difference between them
• Compatibility with arbitrary value types by defining comparison functions
• The reverse order output is realized by adjusting the comparison function

# Design

• Isorter: defines the sorting algorithm interface and the value comparison function
• Tinsertsort: realize insertion sorting, switch insertion functions through parameter control, and realize ordinary insertion and binary insertion respectively

# unit testing

insert_ sort_ Test.go, the test process is basically consistent with the selection and sorting
From the test results, ordinary insertion sorting is about 30% faster than selective sorting, and binary insertion is nearly four times faster than ordinary insertion

``````package sorting

import (
"fmt"
"learning/gooop/sorting"
"learning/gooop/sorting/insert_sort"
"math/rand"
"testing"
"time"
)

func Test_InsertSort(t *testing.T) {
fnAssertTrue := func(b bool, msg string) {
if !b {
t.Fatal(msg)
}
}

reversed := false
fnCompare := func(a interface{}, b interface{}) sorting.CompareResult {
i1 := a.(int)
i2 := b.(int)

if i1 < i2 {
if reversed {
return sorting.GREATER
} else {
return sorting.LESS
}
} else if i1 == i2 {
return sorting.EQUAL
} else {
if reversed {
return sorting.LESS
} else {
return sorting.GREATER
}
}
}

fnTestSorter := func(sorter sorting.ISorter) {
reversed = false

// test simple array
samples := []interface{} { 2,3,1 }
sorter.Sort(samples, fnCompare)
fnAssertTrue(fmt.Sprintf("%v", samples) == "[1 2 3]",  "expecting 1,2,3")
t.Log("pass sorting [2 3 1] >> [1 2 3]")

// test 10000 items sorting
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
sampleCount := 10000
t.Logf("prepare large array with %v items", sampleCount)
samples = make([]interface{}, sampleCount)
for i := 0;i < sampleCount;i++ {
samples[i] = rnd.Intn(sampleCount*10)
}

t.Logf("sorting large array with %v items", sampleCount)
t0 := time.Now().UnixNano()
sorter.Sort(samples, fnCompare)
cost := time.Now().UnixNano() - t0
for i := 1;i < sampleCount;i++ {
fnAssertTrue(fnCompare(samples[i-1], samples[i]) != sorting.GREATER, "expecting <=")
}
t.Logf("end sorting large array, cost = %v ms", cost / 1000000)

// test 0-20
sampleCount = 20
t.Log("sorting 0-20")
samples = make([]interface{}, sampleCount)
for i := 0;i < sampleCount;i++ {
for {
p := rnd.Intn(sampleCount)
if samples[p] == nil {
samples[p] = i
break
}
}
}
t.Logf("unsort = %v", samples)

sorter.Sort(samples, fnCompare)
t.Logf("sorted = %v", samples)
fnAssertTrue(fmt.Sprintf("%v", samples) == "[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]", "expecting 0-20")
t.Log("pass sorting 0-20")

// test special
samples = []interface{} {}
sorter.Sort(samples, fnCompare)
t.Log("pass sorting []")

samples = []interface{} { 1 }
sorter.Sort(samples, fnCompare)
t.Log("pass sorting ")

samples = []interface{} { 3,1 }
sorter.Sort(samples, fnCompare)
fnAssertTrue(fmt.Sprintf("%v", samples) == "[1 3]",  "expecting 1,3")
t.Log("pass sorting [1 3]")

reversed = true
samples = []interface{} { 2, 3,1 }
sorter.Sort(samples, fnCompare)
fnAssertTrue(fmt.Sprintf("%v", samples) == "[3 2 1]",  "expecting 3,2,1")
t.Log("pass sorting [3 2 1]")
}

t.Log("\ntesting SimpleInsertSorter")
fnTestSorter(insert_sort.SimpleInsertSorter)

t.Log("\ntesting BinaryInsertSorter")
fnTestSorter(insert_sort.BinaryInsertSorter)
}``````

# Test output

``````\$ go test -v insert_sort_test.go
=== RUN   Test_InsertSort
insert_sort_test.go:109:
testing SimpleInsertSorter
insert_sort_test.go:48: pass sorting [2 3 1] >> [1 2 3]
insert_sort_test.go:53: prepare large array with 10000 items
insert_sort_test.go:59: sorting large array with 10000 items
insert_sort_test.go:66: end sorting large array, cost = 188 ms
insert_sort_test.go:70: sorting 0-20
insert_sort_test.go:81: unsort = [10 6 14 18 12 11 19 9 17 8 7 0 15 16 1 3 5 13 4 2]
insert_sort_test.go:84: sorted = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
insert_sort_test.go:86: pass sorting 0-20
insert_sort_test.go:91: pass sorting []
insert_sort_test.go:95: pass sorting 
insert_sort_test.go:100: pass sorting [1 3]
insert_sort_test.go:106: pass sorting [3 2 1]
insert_sort_test.go:112:
testing BinaryInsertSorter
insert_sort_test.go:48: pass sorting [2 3 1] >> [1 2 3]
insert_sort_test.go:53: prepare large array with 10000 items
insert_sort_test.go:59: sorting large array with 10000 items
insert_sort_test.go:66: end sorting large array, cost = 46 ms
insert_sort_test.go:70: sorting 0-20
insert_sort_test.go:81: unsort = [3 19 13 17 11 4 15 10 14 5 6 0 7 2 8 16 18 12 1 9]
insert_sort_test.go:84: sorted = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
insert_sort_test.go:86: pass sorting 0-20
insert_sort_test.go:91: pass sorting []
insert_sort_test.go:95: pass sorting 
insert_sort_test.go:100: pass sorting [1 3]
insert_sort_test.go:106: pass sorting [3 2 1]
--- PASS: Test_InsertSort (0.24s)
PASS
ok      command-line-arguments  0.237s``````

# ISorter.go

Define sorting algorithm interface and value comparison function

``````package sorting

type ISorter interface {
Sort(data []interface{}, comparator CompareFunction) []interface{}
}

type CompareFunction func(a interface{}, b interface{}) CompareResult

type CompareResult int
const LESS CompareResult = -1
const EQUAL CompareResult = 0
const GREATER CompareResult = 1``````

# tInsertSort.go

Realize insertion sorting, switch the insertion function through parameter control, and realize ordinary insertion and binary insertion respectively

``````package insert_sort

import (
"learning/gooop/sorting"
)

type tInsertSort struct {
fnInsert fnInsertFunction
}

func newInsertSort(usingBinarySearch bool) sorting.ISorter {
it := &tInsertSort{
nil,
}
if usingBinarySearch {
it.fnInsert = binaryInsert
} else {
it.fnInsert = simpleInsert
}
return it
}

type fnInsertFunction func(data []interface{}, from int, to int, comparator sorting.CompareFunction)

//Insert sort
func (me *tInsertSort) Sort(data []interface{}, comparator sorting.CompareFunction) []interface{} {
if data == nil {
return nil
}

size := len(data)
if size <= 1 {
return data
}

for i := 1;i < size;i++ {
me.fnInsert(data, 0, i, comparator)
}

return data
}

//Insert the value at to into the [from, to) position of the ordered sequence data
func simpleInsert(data []interface{}, from int, to int, comparator sorting.CompareFunction) {
for i := to;i>from;i-- {
prev := i - 1
if comparator(data[prev], data[i]) == sorting.GREATER {
data[prev], data[i] = data[i], data[prev]
} else {
break
}
}
}

//Insert the value at to into the [from, to) position of the ordered sequence data
func binaryInsert(data []interface{}, from int, to int, comparator sorting.CompareFunction) {
p := binaryIndexOf(data, from, to - 1, data[to], comparator)
if p != to {
v := data[to]
moveArrayRange(data, p, p + 1, to - p)
data[p] = v
}
}

//Moves the specified range of the array as a whole
func moveArrayRange(data []interface{}, src int, dst int, size int) {
t := dst + size - 1
for i := src + size - 1;i >= src;i-- {
data[t] = data[i]
t--
}
}

//Binary search for the first subscript > = v
func binaryIndexOf(data []interface{}, from int, toInclusive int, v interface{}, comparator sorting.CompareFunction) int {
for {
if from == toInclusive {
switch comparator(data[from], v) {
case sorting.LESS:
return from + 1

default:
return from
}

} else {
p := (from + toInclusive) / 2
switch comparator(data[p], v) {
case sorting.LESS:
from = min(p + 1, toInclusive)
break

case sorting.EQUAL:
return p

case sorting.GREATER:
toInclusive = max(from, p - 1)
break
}
}
}
}

func min(a, b int) int {
if a <= b {
return a
} else {
return b
}
}

func max(a, b int) int {
if a >= b {
return a
} else {
return b
}
}

var SimpleInsertSorter = newInsertSort(false)
var BinaryInsertSorter = newInsertSort(true)``````

(end)

## [hematemesis finishing] Super complete golang interview questions collection + golang Learning Guide + golang knowledge map + growth route

The brain map is constantly updated. Check the address onlineSubsequent articles and contents will be updated toGitHub projectWelcome to pay attention. Directory (Ctrl + F) Basic introduction Novice 50 mistakes that golang novices often make data type I don’t even know that nil slice is different from empty slice? Then the bat interviewer has to […]