1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-07 14:12:28 +08:00

Compare commits

...

6 Commits

Author SHA1 Message Date
dudaodong
bb23c9eef8 release v2.0.4 2022-04-14 11:51:34 +08:00
dudaodong
b4cd0750e4 fix: fix http post to support multipart/form-data header 2022-04-14 11:48:39 +08:00
dudaodong
c960841491 docs: update sort function doc 2022-04-12 14:45:22 +08:00
dudaodong
5d6f9443fd refactor: rewrite sort function 2022-04-12 14:30:43 +08:00
dudaodong
5483380066 refactor: rewrite arrayqueue 2022-04-08 17:39:54 +08:00
dudaodong
20b9e5353e fix: fix goreport issue 2022-04-06 11:33:48 +08:00
12 changed files with 303 additions and 208 deletions

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-2.0.3-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.0.4-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -35,9 +35,9 @@ English | [简体中文](./README_zh-CN.md)
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
``` ```
2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.2.7. </b> 2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.2.9. </b>
```go ```go
go get github.com/duke-git/lancet@v1.2.7 // below go1.18, install latest version of v1.x.x go get github.com/duke-git/lancet@v1.2.9 // below go1.18, install latest version of v1.x.x
``` ```
## Usage ## Usage

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-2.0.3-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.0.4-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -35,9 +35,9 @@
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
``` ```
2. <b>使用go1.18以下版本的用户必须安装v1.x.x。目前最新的v1版本是v1.2.7。</b> 2. <b>使用go1.18以下版本的用户必须安装v1.x.x。目前最新的v1版本是v1.2.9。</b>
```go ```go
go get github.com/duke-git/lancet@v1.2.7 // 使用go1.18以下版本, 必须安装v1.x.x版本 go get github.com/duke-git/lancet@v1.2.9 // 使用go1.18以下版本, 必须安装v1.x.x版本
``` ```
## 用法 ## 用法

View File

@@ -7,7 +7,7 @@ package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints" import "github.com/duke-git/lancet/v2/lancetconstraints"
// BubbleSort use bubble to sort slice. // BubbleSort use bubble to sort slice.
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T { func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) {
for i := 0; i < len(slice); i++ { for i := 0; i < len(slice); i++ {
for j := 0; j < len(slice)-1-i; j++ { for j := 0; j < len(slice)-1-i; j++ {
isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1 isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1
@@ -16,38 +16,26 @@ func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
} }
} }
} }
return slice
} }
// InsertionSort use insertion to sort slice. // InsertionSort use insertion to sort slice.
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T { func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
size := len(slice) for i := 0; i < len(slice); i++ {
if size <= 1 { for j := i; j > 0; j-- {
return slice isPreLessThanCurrent := comparator.Compare(slice[j], slice[j-1]) == -1
} if isPreLessThanCurrent {
swap(slice, j, j-1)
for i := 1; i < size; i++ { } else {
currentItem := slice[i] break
preIndex := i - 1 }
preItem := slice[preIndex]
isPreLessThanCurrent := comparator.Compare(preItem, currentItem) == -1
for preIndex >= 0 && isPreLessThanCurrent {
slice[preIndex+1] = slice[preIndex]
preIndex--
} }
slice[preIndex+1] = currentItem
} }
return slice
} }
// SelectionSort use selection to sort slice. // SelectionSort use selection to sort slice.
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T { func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
for i := 0; i < len(slice); i++ { for i := 0; i < len(slice); i++ {
min := i min := i
for j := i + 1; j < len(slice); j++ { for j := i + 1; j < len(slice); j++ {
if comparator.Compare(slice[j], slice[min]) == -1 { if comparator.Compare(slice[j], slice[min]) == -1 {
min = j min = j
@@ -55,15 +43,11 @@ func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []
} }
swap(slice, i, min) swap(slice, i, min)
} }
return slice
} }
// ShellSort shell sort slice. // ShellSort shell sort slice.
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T { func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) {
size := len(slice) size := len(slice)
if size <= 1 {
return slice
}
gap := 1 gap := 1
for gap < size/3 { for gap < size/3 {
@@ -76,21 +60,17 @@ func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
swap(slice, j, j-gap) swap(slice, j, j-gap)
} }
} }
gap /= 3 gap = gap / 3
} }
return slice
} }
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1 // QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T { func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
if lowIndex < highIndex { if lowIndex < highIndex {
p := partition(slice, lowIndex, highIndex, comparator) p := partition(slice, lowIndex, highIndex, comparator)
QuickSort(slice, lowIndex, p-1, comparator) QuickSort(slice, lowIndex, p-1, comparator)
QuickSort(slice, p+1, highIndex, comparator) QuickSort(slice, p+1, highIndex, comparator)
} }
return slice
} }
// partition split slice into two parts // partition split slice into two parts
@@ -110,7 +90,7 @@ func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconst
} }
// HeapSort use heap to sort slice // HeapSort use heap to sort slice
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T { func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) {
size := len(slice) size := len(slice)
for i := size/2 - 1; i >= 0; i-- { for i := size/2 - 1; i >= 0; i-- {
@@ -120,8 +100,6 @@ func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
swap(slice, 0, j) swap(slice, 0, j)
sift(slice, 0, j-1, comparator) sift(slice, 0, j-1, comparator)
} }
return slice
} }
func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) { func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
@@ -145,15 +123,17 @@ func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraint
} }
// MergeSort merge sorting for slice // MergeSort merge sorting for slice
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T { func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator) {
mergeSort(slice, 0, len(slice)-1, comparator)
}
func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
if lowIndex < highIndex { if lowIndex < highIndex {
mid := (lowIndex + highIndex) / 2 mid := (lowIndex + highIndex) / 2
MergeSort(slice, lowIndex, mid, comparator) mergeSort(slice, lowIndex, mid, comparator)
MergeSort(slice, mid+1, highIndex, comparator) mergeSort(slice, mid+1, highIndex, comparator)
merge(slice, lowIndex, mid, highIndex, comparator) merge(slice, lowIndex, mid, highIndex, comparator)
} }
return slice
} }
func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lancetconstraints.Comparator) { func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lancetconstraints.Comparator) {

View File

@@ -28,22 +28,15 @@ func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
return 1 return 1
} }
return 0 return 0
//decending order
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
} }
var peoples = []people{ // var peoples = []people{
{Name: "a", Age: 20}, // {Name: "a", Age: 20},
{Name: "b", Age: 10}, // {Name: "b", Age: 10},
{Name: "c", Age: 17}, // {Name: "c", Age: 17},
{Name: "d", Age: 8}, // {Name: "d", Age: 8},
{Name: "e", Age: 28}, // {Name: "e", Age: 28},
} // }
type intComparator struct{} type intComparator struct{}
@@ -60,40 +53,51 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
return 0 return 0
} }
var intSlice = []int{2, 1, 5, 3, 6, 4} // var intSlice = []int{2, 1, 5, 3, 6, 4}
func TestBubbleSortForStructSlice(t *testing.T) { func TestBubbleSortForStructSlice(t *testing.T) {
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice") asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := BubbleSort(peoples, comparator) BubbleSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]" expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge) actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual) asssert.Equal(expected, actual)
} }
func TestBubbleSortForIntSlice(t *testing.T) { func TestBubbleSortForIntSlice(t *testing.T) {
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice") asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedInt := BubbleSort(intSlice, comparator) BubbleSort(numbers, comparator)
expected := []int{1, 2, 3, 4, 5, 6}
asssert.Equal(expected, sortedInt) asssert.Equal([]int{1, 2, 3, 4, 5, 6}, numbers)
} }
func TestInsertionSort(t *testing.T) { func TestInsertionSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestInsertionSort") asssert := internal.NewAssert(t, "TestInsertionSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := InsertionSort(peoples, comparator) InsertionSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{e 28} {a 20} {c 17} {b 10} {d 8}]" expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge) actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual) asssert.Equal(expected, actual)
} }
@@ -101,12 +105,18 @@ func TestInsertionSort(t *testing.T) {
func TestSelectionSort(t *testing.T) { func TestSelectionSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestSelectionSort") asssert := internal.NewAssert(t, "TestSelectionSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := SelectionSort(peoples, comparator) SelectionSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]" expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge) actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual) asssert.Equal(expected, actual)
} }
@@ -114,12 +124,18 @@ func TestSelectionSort(t *testing.T) {
func TestShellSort(t *testing.T) { func TestShellSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestShellSort") asssert := internal.NewAssert(t, "TestShellSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := ShellSort(peoples, comparator) ShellSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]" expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge) actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual) asssert.Equal(expected, actual)
} }
@@ -127,12 +143,18 @@ func TestShellSort(t *testing.T) {
func TestQuickSort(t *testing.T) { func TestQuickSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestQuickSort") asssert := internal.NewAssert(t, "TestQuickSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := QuickSort(peoples, 0, len(peoples)-1, comparator) QuickSort(peoples, 0, len(peoples)-1, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]" expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge) actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual) asssert.Equal(expected, actual)
} }
@@ -140,12 +162,18 @@ func TestQuickSort(t *testing.T) {
func TestHeapSort(t *testing.T) { func TestHeapSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestHeapSort") asssert := internal.NewAssert(t, "TestHeapSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := HeapSort(peoples, comparator) HeapSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]" expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge) actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual) asssert.Equal(expected, actual)
} }
@@ -153,12 +181,18 @@ func TestHeapSort(t *testing.T) {
func TestMergeSort(t *testing.T) { func TestMergeSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestMergeSort") asssert := internal.NewAssert(t, "TestMergeSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := MergeSort(peoples, 0, len(peoples)-1, comparator) MergeSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]" expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge) actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual) asssert.Equal(expected, actual)
} }
@@ -166,6 +200,13 @@ func TestMergeSort(t *testing.T) {
func TestCountSort(t *testing.T) { func TestCountSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestCountSort") asssert := internal.NewAssert(t, "TestCountSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := CountSort(peoples, comparator) sortedPeopleByAge := CountSort(peoples, comparator)
t.Log(sortedPeopleByAge) t.Log(sortedPeopleByAge)

View File

@@ -1,79 +1,101 @@
package datastructure package datastructure
import ( import (
"errors"
"fmt" "fmt"
"reflect" "reflect"
) )
// ArrayQueue implements queue with slice // ArrayQueue implements queue with slice
type ArrayQueue[T any] struct { type ArrayQueue[T any] struct {
data []T items []T
length int head int
tail int
capacity int
size int
} }
// NewArrayQueue return a empty ArrayQueue pointer func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
func NewArrayQueue[T any](values ...T) *ArrayQueue[T] { return &ArrayQueue[T]{
data := make([]T, len(values)) items: make([]T, 0, capacity),
for i, v := range values { head: 0,
data[i] = v tail: 0,
capacity: capacity,
size: 0,
} }
return &ArrayQueue[T]{data: data, length: len(values)}
} }
// Data return queue data // Data return queue data
func (q *ArrayQueue[T]) Data() []T { func (q *ArrayQueue[T]) Data() []T {
return q.data items := []T{}
for i := q.head; i < q.tail; i++ {
items = append(items, q.items[i])
}
return items
} }
// Size return length of queue data // Size return length of queue data
func (q *ArrayQueue[T]) Size() int { func (q *ArrayQueue[T]) Size() int {
return q.length return q.size
} }
// IsEmpty checks if queue is empty or not // IsEmpty checks if queue is empty or not
func (q *ArrayQueue[T]) IsEmpty() bool { func (q *ArrayQueue[T]) IsEmpty() bool {
return q.length == 0 return q.size == 0
} }
// Front return front value of queue // Front return front value of queue
func (q *ArrayQueue[T]) Front() T { func (q *ArrayQueue[T]) Front() T {
return q.data[0] return q.items[0]
} }
// Back return back value of queue // Back return back value of queue
func (q *ArrayQueue[T]) Back() T { func (q *ArrayQueue[T]) Back() T {
return q.data[q.length-1] return q.items[q.size-1]
} }
// EnQueue put element into queue // EnQueue put element into queue
func (q *ArrayQueue[T]) EnQueue(value T) { func (q *ArrayQueue[T]) Enqueue(item T) bool {
q.data = append(q.data, value) if q.head == 0 && q.tail == q.capacity {
q.length++ return false
} else if q.head != 0 && q.tail == q.capacity {
for i := q.head; i < q.tail; i++ {
q.items[i-q.head] = q.items[i]
}
q.tail = q.tail - q.head
q.head = 0
}
q.items = append(q.items, item)
q.tail++
q.size++
return true
} }
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error // DeQueue remove head element of queue and return it, if queue is empty, return nil and error
func (q *ArrayQueue[T]) DeQueue() (*T, error) { func (q *ArrayQueue[T]) Dequeue() (T, bool) {
if q.IsEmpty() { var item T
return nil, errors.New("queue is empty") if q.head == q.tail {
return item, false
} }
item = q.items[q.head]
headItem := q.data[0] q.head++
q.data = q.data[1:] q.size--
q.length-- return item, true
return &headItem, nil
} }
// Clear the queue data // Clear the queue data
func (q *ArrayQueue[T]) Clear() { func (q *ArrayQueue[T]) Clear() {
q.data = []T{} capacity := q.capacity
q.length = 0 q.items = make([]T, 0, capacity)
q.head = 0
q.tail = 0
q.size = 0
q.capacity = capacity
} }
// Contain checks if the value is in queue or not // Contain checks if the value is in queue or not
func (q *ArrayQueue[T]) Contain(value T) bool { func (q *ArrayQueue[T]) Contain(value T) bool {
for _, v := range q.data { for _, v := range q.items {
if reflect.DeepEqual(v, value) { if reflect.DeepEqual(v, value) {
return true return true
} }
@@ -84,8 +106,8 @@ func (q *ArrayQueue[T]) Contain(value T) bool {
// Print queue data // Print queue data
func (q *ArrayQueue[T]) Print() { func (q *ArrayQueue[T]) Print() {
info := "[" info := "["
for _, v := range q.data { for i := q.head; i < q.tail; i++ {
info += fmt.Sprintf("%+v, ", v) info += fmt.Sprintf("%+v, ", q.items[i])
} }
info += "]" info += "]"
fmt.Println(info) fmt.Println(info)

View File

@@ -6,13 +6,13 @@ import (
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestArrayQueue_EnQueue(t *testing.T) { func TestArrayQueue_Enqueue(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_EnQueue") assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
queue := NewArrayQueue[int]() queue := NewArrayQueue[int](5)
queue.EnQueue(1) queue.Enqueue(1)
queue.EnQueue(2) queue.Enqueue(2)
queue.EnQueue(3) queue.Enqueue(3)
expected := []int{1, 2, 3} expected := []int{1, 2, 3}
data := queue.Data() data := queue.Data()
@@ -24,26 +24,30 @@ func TestArrayQueue_EnQueue(t *testing.T) {
assert.Equal(3, size) assert.Equal(3, size)
} }
func TestArrayQueue_DeQueue(t *testing.T) { func TestArrayQueue_Dequeue(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_DeQueue") assert := internal.NewAssert(t, "TestArrayQueue_Dequeue")
queue := NewArrayQueue(1, 2, 3) queue := NewArrayQueue[int](4)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
val, err := queue.DeQueue() val, ok := queue.Dequeue()
if err != nil { assert.Equal(true, ok)
t.Fail()
}
queue.Print() queue.Print()
assert.Equal(1, *val) assert.Equal(1, val)
assert.Equal([]int{2, 3}, queue.Data()) assert.Equal([]int{2, 3}, queue.Data())
} }
func TestArrayQueue_Front(t *testing.T) { func TestArrayQueue_Front(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Front") assert := internal.NewAssert(t, "TestArrayQueue_Front")
queue := NewArrayQueue(1, 2, 3) queue := NewArrayQueue[int](4)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
val := queue.Front() val := queue.Front()
queue.Print() queue.Print()
@@ -55,7 +59,11 @@ func TestArrayQueue_Front(t *testing.T) {
func TestArrayQueue_Back(t *testing.T) { func TestArrayQueue_Back(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Back") assert := internal.NewAssert(t, "TestArrayQueue_Back")
queue := NewArrayQueue(1, 2, 3) queue := NewArrayQueue[int](4)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
val := queue.Back() val := queue.Back()
queue.Print() queue.Print()
@@ -67,7 +75,10 @@ func TestArrayQueue_Back(t *testing.T) {
func TestArrayQueue_Contain(t *testing.T) { func TestArrayQueue_Contain(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Contain") assert := internal.NewAssert(t, "TestArrayQueue_Contain")
queue := NewArrayQueue(1, 2, 3) queue := NewArrayQueue[int](4)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
assert.Equal(true, queue.Contain(1)) assert.Equal(true, queue.Contain(1))
assert.Equal(false, queue.Contain(4)) assert.Equal(false, queue.Contain(4))
@@ -76,11 +87,12 @@ func TestArrayQueue_Contain(t *testing.T) {
func TestArrayQueue_Clear(t *testing.T) { func TestArrayQueue_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Clear") assert := internal.NewAssert(t, "TestArrayQueue_Clear")
queue := NewArrayQueue[int]() queue := NewArrayQueue[int](4)
assert.Equal(true, queue.IsEmpty()) assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Size()) assert.Equal(0, queue.Size())
queue.EnQueue(1) queue.Enqueue(1)
assert.Equal(false, queue.IsEmpty()) assert.Equal(false, queue.IsEmpty())
assert.Equal(1, queue.Size()) assert.Equal(1, queue.Size())

View File

@@ -21,18 +21,23 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [BubbleSort](#BubbleSort) - [Algorithm](#algorithm)
- [CountSort](#CountSort) - [Source](#source)
- [HeapSort](#HeapSort) - [Usage](#usage)
- [InsertionSort](#InsertionSort) - [Index](#index)
- [MergeSort](#MergeSort) - [Documentation](#documentation)
- [QuickSort](#QuickSort) - [<span id="BubbleSort">BubbleSort</span>](#bubblesort)
- [SelectionSort](#SelectionSort) - [<span id="InsertionSort">InsertionSort</span>](#insertionsort)
- [ShellSort](#ShellSort) - [<span id="SelectionSort">SelectionSort</span>](#selectionsort)
- [BinarySearch](#BinarySearch) - [<span id="ShellSort">ShellSort</span>](#shellsort)
- [BinaryIterativeSearch](#BinaryIterativeSearch) - [<span id="QuickSort">QuickSort</span>](#quicksort)
- [LinearSearch](#LinearSearch) - [<span id="HeapSort">HeapSort</span>](#heapsort)
- [LRUCache](#LRUCache) - [<span id="MergeSort">MergeSort</span>](#mergesort)
- [<span id="CountSort">CountSort</span>](#countsort)
- [<span id="BinarySearch">BinarySearch</span>](#binarysearch)
- [<span id="BinaryIterativeSearch">BinaryIterativeSearch</span>](#binaryiterativesearch)
- [<span id="LinearSearch">LinearSearch</span>](#linearsearch)
- [<span id="LRUCache">LRUCache</span>](#lrucache)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -46,7 +51,7 @@ import (
<b>Signature:</b> <b>Signature:</b>
```go ```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -76,9 +81,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.BubbleSort(intSlice, comparator) algorithm.BubbleSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -91,7 +96,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -141,9 +146,9 @@ func main() {
{Name: "e", Age: 28}, {Name: "e", Age: 28},
} }
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeople := algorithm.InsertionSort(peoples, comparator) algorithm.InsertionSort(peoples, comparator)
fmt.Println(sortedSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}] fmt.Println(peoples) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
} }
``` ```
@@ -156,7 +161,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -186,9 +191,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.SelectionSort(intSlice, comparator) algorithm.SelectionSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -201,7 +206,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -231,9 +236,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.ShellSort(intSlice, comparator) algorithm.ShellSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -246,7 +251,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -276,9 +281,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator) algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -291,7 +296,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -321,9 +326,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.HeapSort(intSlice, comparator) algorithm.HeapSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -336,7 +341,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -366,9 +371,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.MergeSort(intSlice, 0, len(intSlice)-1, comparator) algorithm.MergeSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```

View File

@@ -21,18 +21,23 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [BubbleSort](#BubbleSort) - [Algorithm](#algorithm)
- [CountSort](#CountSort) - [源码](#源码)
- [HeapSort](#HeapSort) - [用法](#用法)
- [InsertionSort](#InsertionSort) - [目录](#目录)
- [MergeSort](#MergeSort) - [文档](#文档)
- [QuickSort](#QuickSort) - [<span id="BubbleSort">BubbleSort</span>](#bubblesort)
- [SelectionSort](#SelectionSort) - [<span id="InsertionSort">InsertionSort</span>](#insertionsort)
- [ShellSort](#ShellSort) - [<span id="SelectionSort">SelectionSort</span>](#selectionsort)
- [BinarySearch](#BinarySearch) - [<span id="ShellSort">ShellSort</span>](#shellsort)
- [BinaryIterativeSearch](#BinaryIterativeSearch) - [<span id="QuickSort">QuickSort</span>](#quicksort)
- [LinearSearch](#LinearSearch) - [<span id="HeapSort">HeapSort</span>](#heapsort)
- [LRUCache](#LRUCache) - [<span id="MergeSort">MergeSort</span>](#mergesort)
- [<span id="CountSort">CountSort</span>](#countsort)
- [<span id="BinarySearch">BinarySearch</span>](#binarysearch)
- [<span id="BinaryIterativeSearch">BinaryIterativeSearch</span>](#binaryiterativesearch)
- [<span id="LinearSearch">LinearSearch</span>](#linearsearch)
- [<span id="LRUCache">LRUCache</span>](#lrucache)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -46,7 +51,7 @@ import (
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -76,9 +81,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.BubbleSort(intSlice, comparator) algorithm.BubbleSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -91,7 +96,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -141,9 +146,9 @@ func main() {
{Name: "e", Age: 28}, {Name: "e", Age: 28},
} }
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeople := algorithm.InsertionSort(peoples, comparator) algorithm.InsertionSort(peoples, comparator)
fmt.Println(sortedSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}] fmt.Println(intSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
} }
``` ```
@@ -156,7 +161,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -186,9 +191,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.SelectionSort(intSlice, comparator) algorithm.SelectionSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -201,7 +206,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -231,9 +236,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.ShellSort(intSlice, comparator) algorithm.ShellSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -276,9 +281,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator) algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -321,9 +326,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.HeapSort(intSlice, comparator) algorithm.HeapSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```
@@ -336,7 +341,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -366,9 +371,9 @@ func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.MergeSort(intSlice, 0, len(intSlice)-1, comparator) algorithm.MergeSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
} }
``` ```

View File

@@ -69,7 +69,7 @@ func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
return maps[0] return maps[0]
} }
res := make(map[K]V) var res map[K]V
reducer := func(m1, m2 map[K]V) map[K]V { reducer := func(m1, m2 map[K]V) map[K]V {
m := make(map[K]V) m := make(map[K]V)
@@ -93,7 +93,6 @@ func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
return res return res
} }
// Minus creates an map of whose key in mapA but not in mapB // Minus creates an map of whose key in mapA but not in mapB
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V { func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V {
res := make(map[K]V) res := make(map[K]V)

View File

@@ -6,7 +6,8 @@
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `url` is required. // HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `url` is required.
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `params` is variable, the order is: // HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `params` is variable, the order is:
// params[0] is header which type should be http.Header or map[string]string, // params[0] is header which type should be http.Header or map[string]string,
// params[1] is query param which type should be url.Values or map[string]any, // params[1] is query param which type should be url.Values or map[string]any, when content-type header is
// multipart/form-data or application/x-www-form-urlencoded, params[1] should be url.Values
// params[2] is post body which type should be []byte. // params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
package netutil package netutil

View File

@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"log" "log"
"net/url"
"testing" "testing"
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
@@ -46,6 +47,29 @@ func TestHttpPost(t *testing.T) {
t.Log("response: ", resp.StatusCode, string(body)) t.Log("response: ", resp.StatusCode, string(body))
} }
func TestHttpPostFormData(t *testing.T) {
apiUrl := "https://jsonplaceholder.typicode.com/todos"
header := map[string]string{
// "Content-Type": "application/x-www-form-urlencoded",
"Content-Type": "multipart/form-data",
}
type Todo struct {
UserId int `json:"userId"`
Title string `json:"title"`
}
postData := url.Values{}
postData.Add("userId", "1")
postData.Add("title", "TestAddToDo")
resp, err := HttpPost(apiUrl, header, postData, nil)
if err != nil {
log.Fatal(err)
t.FailNow()
}
body, _ := ioutil.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
}
func TestHttpPut(t *testing.T) { func TestHttpPut(t *testing.T) {
url := "https://jsonplaceholder.typicode.com/todos/1" url := "https://jsonplaceholder.typicode.com/todos/1"
header := map[string]string{ header := map[string]string{

View File

@@ -81,10 +81,16 @@ func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryPar
if err != nil { if err != nil {
return err return err
} }
err = setBodyByte(req, body) if req.Header.Get("Content-Type") == "multipart/form-data" || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
formData := queryParam.(url.Values)
err = setBodyByte(req, []byte(formData.Encode()))
} else {
err = setBodyByte(req, body)
}
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }