Full Code of chen3feng/stl4go for AI

master 1aa2d0c16ab8 cached
67 files
250.5 KB
82.8k tokens
599 symbols
1 requests
Download .txt
Showing preview only (270K chars total). Download the full file or copy to clipboard to get everything.
Repository: chen3feng/stl4go
Branch: master
Commit: 1aa2d0c16ab8
Files: 67
Total size: 250.5 KB

Directory structure:
gitextract_wl0h18v1/

├── .github/
│   └── workflows/
│       ├── check-markdown-links.yml
│       ├── go.yml
│       └── gosec.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_zh.md
├── binary_search.go
├── binary_search_test.go
├── builtin_set.go
├── builtin_set_test.go
├── check.bat
├── check.sh
├── compare.go
├── compare_test.go
├── compute.go
├── compute_test.go
├── container.go
├── container_test.go
├── dlist.go
├── dlist_queue.go
├── dlist_queue_test.go
├── dlist_test.go
├── doc.go
├── functor.go
├── generate.go
├── generate_test.go
├── generated_doc.md
├── go.mod
├── go.sum
├── heap.go
├── heap.md
├── heap_bench_test.go
├── heap_test.go
├── helper.go
├── iterator.go
├── lookup.go
├── lookup_test.go
├── mlc_config.json
├── pool.go
├── pool_test.go
├── priority_queue.go
├── priority_queue_test.go
├── skiplist.go
├── skiplist.md
├── skiplist_bench_test.go
├── skiplist_newnode.go
├── skiplist_newnode_generate.sh
├── skiplist_set.go
├── skiplist_set_test.go
├── skiplist_test.go
├── slist.go
├── slist_test.go
├── sort.go
├── sort_test.go
├── stack.go
├── stack_test.go
├── test_helper.go
├── transform.go
├── transform_fillzero_clear.go
├── transform_fillzero_old.go
├── transform_test.go
├── types.go
├── updatedoc.bat
├── updatedoc.sh
├── vector.go
└── vector_test.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/check-markdown-links.yml
================================================
name: Check Markdown links

on: push

jobs:
  markdown-link-check:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    - uses: gaurav-nelson/github-action-markdown-link-check@v1
      with:
        use-quiet-mode: 'yes'
        check-modified-files-only: 'yes'
        config-file: mlc_config.json


================================================
FILE: .github/workflows/go.yml
================================================
name: Go

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:

  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Go
      uses: actions/setup-go@v3
      with:
        go-version: 1.18

    - name: Build
      run: go build -v ./...

    - name: Test
      run: go test -v ./... -covermode=count -coverprofile=coverage.out.tmp

    - name: Filter out test_helper
      run: grep -E -v "/(test_helper)\.go:" coverage.out.tmp > coverage.out

    - name: Convert coverage.out to coverage.lcov
      uses: jandelgado/gcov2lcov-action@v1.0.9

    - name: Coveralls
      uses: coverallsapp/github-action@v1.1.2
      with:
        github-token: ${{ secrets.github_token }}
        path-to-lcov: coverage.lcov


================================================
FILE: .github/workflows/gosec.yml
================================================
name: Run Gosec
on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master
jobs:
  tests:
    runs-on: ubuntu-latest
    env:
      GO111MODULE: on
    steps:
      - name: Checkout Source
        uses: actions/checkout@v2
      - name: Run Gosec Security Scanner
        uses: securego/gosec@master
        with:
          args: ./...


================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
__debug_bin

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
*.tmp
*.bak
*.old

# Dependency directories (remove the comment below to include it)
# vendor/


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# stl4go -- STL for Golang

English | [简体中文](README_zh.md)

This library contains generic containers and algorithms, it is designed to be STL for Golang.

[![License Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-red.svg)](COPYING)
[![Golang](https://img.shields.io/badge/Language-go1.18+-blue.svg)](https://go.dev/)
![Build Status](https://github.com/chen3feng/stl4go/actions/workflows/go.yml/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/chen3feng/stl4go/badge.svg?branch=master)](https://coveralls.io/github/chen3feng/stl4go?branch=master)
[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/report/github.com/chen3feng/stl4go)
[![Go Reference](https://pkg.go.dev/badge/github.com/chen3feng/stl4go.svg)](https://pkg.go.dev/github.com/chen3feng/stl4go)

This library depends on go generics, which is introduced in 1.18+.

<!-- gomarkdoc:embed:start -->

<!-- Code generated by gomarkdoc. DO NOT EDIT -->

```go
import "github.com/chen3feng/stl4go"
```

Package stl4go is a generic container and algorithm library for go.

## Introduce

This library is a general container and algorithm library that attempts to learn from the C++ STL implementation after Go 1.18 began to support generics.
(Personally I's totally unacceptable for me  use to languages without generics, so I didn't try it until go 1.18).

The code quality of this library is quite high and follows the latest best practices in the industry.
Test coverage is close💯%, ✅,CI, and [gosec](https://securego.io/) check are both set up, got
[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/report/github.com/chen3feng/stl4go) score。

## Features

As we all know, C++'s STL includes containers, algorithms, and iterators relate the two.

Due to language limitations, it is impossible and unnecessary to completely imitate the interface of C++ STL in Go,
so C++ users may feel familiar, and sometimes (maybe) feel more convenient.

### Containers

There are following container interfaces:

- `Container` is the base interface for all containers
- `Map` is a key-value associative container
- `Set` is set container
- `SortedMap` is a ordered key-value associative container
- `SortedSet` is a ordered set container
- `Queue` is a FIFO Queue
- `Deque` is a double ended queue

Different interface has different methods. The `Container` interface has following methods:

- `IsEmpty() bool` returns whether the container is empty
- `Len() int` returns the number of elements in the container
- `Clear()` to clear the container

Read [source code](container.go) for details.

Currently container implementations are:

- [x] `BuiltinSet` provided a set funtionality based on Go's own `map`. It provides basic operations such as insert,
      search and remove, as well as advanced functions such as union, intersection, difference, subset, superset, and disjoint.
- [x] `Vector` is a thin encapsulation based on `slice`. It provides functions such as insertion and deletion in the middle, range deletion, etc.,
      and is still compatible with slices.
- [x] `DList` is a doubly linked list, supports push/popup at both ending.
- [x] `SList` is a singly linked list, supports push/popup at the head and push at the tail.
- [x] [SkipList](skiplist.md) is an ordered associative container that fills the gap where Go `map` only supports unordered.
      This is currently the fastest skip list I tested in GitHub, see [skiplist-survey](https://github.com/chen3feng/skiplist-survey) for performance comparison
- [x] `SkipList` is a `SortedSet` container based on the skiplist.
- [x] `Stack`, is a FILO container based on Slice implementation
- [x] `DListQueue` is a bidirectional FIFO queue, implemented based on linked list.
- [x] `PriorityQuque` is a priority queue based on heap. Much easier to use and faster than [container/heap](https://pkg.go.dev/container/heap).

### Non-Container Components

- [x] `Pool` A type safe Pool, is implemented based on `sync.Pool`.

### Iterators

Vector, DList and SkipList support iterators.

```go
// Iterator is the interface for container's iterator.
type Iterator[T any] interface {
	IsNotEnd() bool // Whether it is point to the end of the range.
	MoveToNext()    // Let it point to the next element.
	Value() T       // Return the value of current element.
}

// MutableIterator is the interface for container's mutable iterator.
type MutableIterator[T any] interface {
	Iterator[T]
	Pointer() *T // Return the pointer to the value of current element.
}
```

```go
l := stl4go.NewDListOf(Range(1, 10000)...)
sum := 0
for i := 0; i < b.N; i++ {
    for it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {
        sum += it.Value()
    }
}
```

The iterator of SkipList is `MutableMapIterator`:

```go
// MapIterator is the interface for map's iterator.
type MapIterator[K any, V any] interface {
	Iterator[V]
	Key() K // The key of the element
}

// MutableMapIterator is the interface for map's mutable iterator.
type MutableMapIterator[K any, V any] interface {
	MutableIterator[V]
	Key() K // The key of the element
}
```

SkipList also supports range iteration:

```go
sl := stl4go.NewSkipList[int, int]()
for i := 0; i < 1000; i++ {
    sl.Insert(i, 0)
}
it := sl.FindRange(120, 350)
```

Iterating over `it` only yields the keys between 120 and 349.

In many cases, it is more convenient to use the `ForEach` and `ForEachIf` methods provided by the container,
and the performance is often better:

```go
func TestSkipList_ForEach(t *testing.T) {
    sl := newSkipListN(100)
    a := []int{}
    sl.ForEach(func(k int, v int) {
        a = append(a, k)
    })
    expectEq(t, len(a), 100)
    expectTrue(t, IsSorted(a))
}
```

`ForEachIf` is used for scenarios that you want to end early during the iteration:

 ```go
func Test_DList_ForEachIf(t *testing.T) {
    l := NewDListOf(1, 2, 3)
    c := 0
    l.ForEachIf(func(n int) bool {
        c = n
        return n != 2
    })
    expectEq(t, c, 2)
}
 ```

You can use `ForEachMutable` or `ForEachMutable` to modify the value of an element during the iteration:

```go
func TestSkipList_ForEachMutable(t *testing.T) {
    sl := newSkipListN(100)
    sl.ForEachMutable(func(k int, v *int) {
        *v = -*v
    })
    for i := 0; i < sl.Len(); i++ {
        expectEq(t, *sl.Find(i), -i)
    }
}
```

### Algorithms

Due to the limitations of language, most algorithms only support Slice.
The functions name of the algorithms ends with `If` or `Func`,
indicating that a custom comparison function can be passed.

#### Generate

- `Range` returns a Slice of contains integers in the range of `[begin, end)`
- `Generate` generates a sequence with the given function to fill the Slice

#### Data manipulation

- `Copy` return a copies of specified slice
- `CopyTo` copies all elements in slice a to slice to, return the copied slice.
- `Fill` repeatedly fills a slice with the specified value
- `FillZero` fills each element in slice a with zero value.
- `FillPattern` repeatedly fills a slice with the specified pattern
- `Replace` replaces every element that equals to old with new
- `ReplaceIf` replaces every element that make preq returns true with new
- `Transform` passes the value at each position of the slice to the specified function and sets it back with its return value
- `TransformTo` passes the value at each position of slice `a` to the specified function,
  sets its return value to the corresponding position in slice `b`, and returns a slice of corresponding length of slice `b`
- `TransformCopy` passes the value at each position of the slice to the specified function,
  sets its return value to the corresponding position in a new slice and returns
- `Unique` removes adjacent duplicate elements from a slice and returns a slice with new length containing the remaining elements,
  `UniqueCopy` returns a copy without modifying the original slice
- `Remove` removes all elements in the slice equal to the specified value, `RemoveCopy` returns a copy without modifying the original slice
- `RemoveIf` removes all elements in the slice that are equivalent to making the specified function return `true`,
  `RemoveIfCopy` does not modify the original slice but returns a copy
- `Shuffle` random shuffle elements in the slice
- `Reverse` reverses a slice, `ReverseCopy` returns a copy without modifying the original slice

#### Compute

- `Sum` Sum
- `SumAs` sums and returns a result as another type (eg. use `int64` to return the sum of `[]int32`).
- `Average` finds the average value.
- `AverageAs` averages and returns the result as another type (eg. use `float64` to return the sum of `[]int`).
- `Count` returns the number equivalent to the specified value
- `CountIf` returns the number of elements for which the specified function returns `true`

#### Compare

- `Equal` checks whether two sequences are equal
- `Compare` compares two sequences and returns `-1`, `0`, and `1` in lexicographical order, respectively indicating the relationship of 2 slices.

#### Lookup

- `Min`, `Max` find the maximum and minimum
- `MinN`, `MaxN`, `MinMax` return the maximum and minimum values in the slice
- `Find` linearly finds the first specified value and returns its index
- `FindIf` linearly finds the first value that make specified function returns `true` and returns its index
- `AllOf`, `AnyOf`, `NoneOf` return whether all, any, or none of the elements in the range can make the passed function return `true` accordingly.

#### Binary Search

See C++ STL.

- `BinarySearch`
- `LowerBound`
- `UpperBound`

#### Sort

- `Sort` sorting
- `DescSort` descending sorting
- `StableSort` stable sorting
- `DescStableSort` descending stable sorting
- `IsSorted` check whether the slice is sorted
- `IsDescSorted` check whether the slice is sorted in descending order

#### heap

[Heap](heap.md) provides basic min heap algorithms:

- `MakeMinHeap` Convert a slice to a min heap
- `IsMinHeap` Check whether a slice is a min heap
- `PushMinHeap` Pushes an element in to the heap
- `PopMinHeap` Popups an element from the top of the heap
- `RemoveMinHeap` Removes an element at index from the heap

and variants with custome comparasion function:

- `MakeHeapFunc`
- `IsHeapFunc`
- `PushHeapFunc`
- `PopHeapFunc`
- `RemoveHeapFunc`

both of them are mush faster and easier to use than [container/heap](https://pkg.go.dev/container/heap).

See detailed usage and benchmark report in the [document of heap](heap.md)。

### Interface Design and Naming

The design leart much from the C++ STL. The `T` here represents `template`. Yes, Go's generic is not template. but who made C++ so influential and STL so famous?

Many libraries are designed for small code repositories or split into multiple subpackages in one repository.
For example:

```go
import (
    "github.com/someone/awesomelib/skiplist"
    "github.com/someone/awesomelib/binarysearch"
)

func main() {
    sl := skiplist.New()
}
```

This way of writing seems elegant, but because everyone likes good names, import renaming has to be introduced in use in case of package name conflict,
and different users have different renaming style, which increases the mental burden of code reading and writing.

I don't like this style, especially in a larger repository.

Therefore, this library is all under the `stl4go` package, and it is expected that it will not namesake in other people's libraries.

### TODO

See [Issue](https://github.com/chen3feng/stl4go/issues)。

And add more detailed documents.

## Go Doc

Click to view the [generated doc](generated_doc.md).

## Reference

- [C++ STL](https://en.wikipedia.org/wiki/Standard_Template_Library)
- [liyue201/gostl](https://github.com/liyue201/gostl)
- [zyedidia/generic](https://github.com/zyedidia/generic)
- [hlccd/goSTL](https://github.com/hlccd/goSTL)


================================================
FILE: README_zh.md
================================================
# stl4go -- Go 语言的 STL

[English](README.md) | 简体中文

本库包含 Go 语言实现的泛型容器和算法库,就像 C++ 中的 STL。

[![License Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-red.svg)](COPYING)
[![Golang](https://img.shields.io/badge/Language-go1.18+-blue.svg)](https://go.dev/)
![Build Status](https://github.com/chen3feng/stl4go/actions/workflows/go.yml/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/chen3feng/stl4go/badge.svg?branch=master)](https://coveralls.io/github/chen3feng/stl4go?branch=master)
[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/report/github.com/chen3feng/stl4go)
[![Go Reference](https://pkg.go.dev/badge/github.com/chen3feng/stl4go.svg)](https://pkg.go.dev/github.com/chen3feng/stl4go)

```go
import "github.com/chen3feng/stl4go"
```

## 简介

本库是在 Go 1.18 开始支持泛型后,尝试借鉴 C++ STL 实现的一个通用容器和算法库。(我个人完全无法接受没有泛型的语言,因此直到 go 1.18 才开始尝试用它)

本库代码质量高,遵循了业界最新的最佳实践。测试覆盖率接近 💯%,✅,设置了 CI、 [gosec](https://securego.io/) 检查,
[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/report/github.com/chen3feng/stl4go) 评分。

## 主要功能

众所周知,C++ 的 STL 包括容器、算法,并以迭代器关联两者。

受语言限制,在 Go 中无法也没有必要完全模仿 C++的接口,因此 C++ 用户可能会感觉似曾相识相识,有时候也会感觉更方便。

### 容器

定义了如下容器接口:

- `Container` 是所有容器的基础接口
- `Map` 定义了 key-value 关联容器的接口
- `Set` 定义了集合容器的接口
- `SortedMap` 定义了有序 key-value 关联容器的接口
- `SortedSet` 定义了有序集合容器的接口
- `Queue` 定义了先进先出的队列的接口
- `Deque` 定义了双端队列的接口

不同的容器接口支持的方法不同,下面是 `Container` 接口的方法:

- `IsEmpty() bool` 返回容器是否为空
- `Len() int` 返回容器中的元素个数
- `Clear()` 清空容器

具体请参考[源代码](container.go)。

提供的具体容器实现有:

- [x] `BuiltinSet` 是基于 Go 自己的 map 封装的集合。提供了插入查找删除等基本操作,以及并集、交集、差集、子集、超集、不交集等高级功能。
- [x] `Vector` 是基于切片封装的向量。提供了中间插入删除、区间删除等功能,依然与切片兼容。
- [x] `DList` 是双链表容器,支持两端插入删除。
- [x] `SList` 是单链表容器,支持头部插入删除及尾部插入。
- [x] [跳表(SkipList)](skiplist.md) 是一种有序的关联容器,可以填补 Go `map` 只支持无序的的空白。这是目前全 GitHub 最快的跳表,参见 [skiplist-survey](https://github.com/chen3feng/skiplist-survey)的性能比较
- [x] `SkipListSet` 是基于跳表实现的有序集合容器
- [x] `Stack`,栈基于 Slice 实现
- [x] `DListQueue` 双向进出的队列,基于双链表实现
- [x] `PriorityQuque` 优先队列,基于堆实现,比 [container/heap](https://pkg.go.dev/container/heap) 更易用而且快不少。

### 非容器组件

- [x] `Pool` 类型安全的 Pool,基于对 `sync.Pool` 的封装而实现。

### 迭代器

Vector、DList 和 SkipList 支持迭代器。

```go
// Iterator is the interface for container's iterator.
type Iterator[T any] interface {
	IsNotEnd() bool // Whether it is point to the end of the range.
	MoveToNext()    // Let it point to the next element.
	Value() T       // Return the value of current element.
}

// MutableIterator is the interface for container's mutable iterator.
type MutableIterator[T any] interface {
	Iterator[T]
	Pointer() *T // Return the pointer to the value of current element.
}
```

```go
l := stl4go.NewDListOf(Range(1, 10000)...)
sum := 0
for i := 0; i < b.N; i++ {
    for it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {
        sum += it.Value()
    }
}
```

SkipList 的迭代器是 `MutableMapIterator`:

```go
// MapIterator is the interface for map's iterator.
type MapIterator[K any, V any] interface {
	Iterator[V]
	Key() K // The key of the element
}

// MutableMapIterator is the interface for map's mutable iterator.
type MutableMapIterator[K any, V any] interface {
	MutableIterator[V]
	Key() K // The key of the element
}
```

SkipList 还支持区间迭代:

```go
sl := stl4go.NewSkipList[int, int]()
for i := 0; i < 1000; i++ {
    sl.Insert(i, 0)
}
it := sl.FindRange(120, 350)
```

对 `it` 迭代可以只会得到 120~349 之间的数。

更多时候,使用容器提供的 `ForEach` 和 `ForEachIf` 更方便,往往性能也更好一些:

```go
func TestSkipList_ForEach(t *testing.T) {
    sl := newSkipListN(100)
    a := []int{}
    sl.ForEach(func(k int, v int) {
        a = append(a, k)
    })
    expectEq(t, len(a), 100)
    expectTrue(t, IsSorted(a))
}
```

 `ForEachIf` 用于遍历时候提前结束的场景:

 ```go
func Test_DList_ForEachIf(t *testing.T) {
    l := NewDListOf(1, 2, 3)
    c := 0
    l.ForEachIf(func(n int) bool {
        c = n
        return n != 2
    })
    expectEq(t, c, 2)
}
 ```

使用 `ForEachMutable` 或 `ForEachMutable` 可以在遍历时候修改元素的值:

```go
func TestSkipList_ForEachMutable(t *testing.T) {
    sl := newSkipListN(100)
    sl.ForEachMutable(func(k int, v *int) {
        *v = -*v
    })
    for i := 0; i < sl.Len(); i++ {
        expectEq(t, *sl.Find(i), -i)
    }
}
```

### 算法

受语言功能限制,绝大部分算法只支持 Slice。算法的函数名以 `If`、`Func` 结尾的,表示可以传递一个自定义的比较函数。

#### 生成型

- Range 返回一个 [begin, end) 的整数构成的 Slice
- Generate 用给定的函数生成一个序列填充到 Slice 中

#### 数据操作

- `Copy` 返回切片的拷贝
- `CopyTo` 拷贝切片的内容到另一个切片
- `Fill` 用指定的值重复填充一个切片
- `FillZero` 用类型的零值重复填充一个切片
- `FillPattern` 用指定的模式重复填充一个切片
- `Replace` 替换所有等于指定值的元素为新值
- `ReplaceIf` 替换所有让函数返回 `true` 的元素为新值
- `Transform` 把切片的每个位置的值传给指定的函数,用其返回值设置回去
- `TransformTo` 把切片 a 的每个位置的值传给指定的函数,将其返回值设置到切片 b 中相应的位置,并返回 b 的相应长度的切片
- `TransformCopy` 把切片的每个位置的值传给指定的函数,将其返回值设置到一个新的切片中相应的位置并返回
- `Unique` 去除切片中相邻的重复元素,返回包含剩余元素的新长度的切片,`UniqueCopy` 则不修改原切片而是返回一个拷贝
- `Remove` 去除切片中等于指定值的所有元素,`RemoveCopy` 则不修改原切片而是返回一个拷贝
- `RemoveIf` 去除切片中等于让指定函数返回 `true` 的所有元素,`RemoveIfCopy` 则不修改原切片而是返回一个拷贝
- `Shuffle` 随机洗牌
- `Reverse` 反转一个切片,`ReverseCopy` 则不修改原切片而是返回一个拷贝

#### 计算型

- `Sum` 求和
- `SumAs` 求和并以另一种类型的结果返回(比如以 `int64` 类型返回 `[]int32` 的和)
- `Average` 求平均值。
- `AverageAs` 求平均值并以另一种类型的结果返回(比如 `float64` 返回 `[]int` 的和)
- `Count` 返回和指定值相当的个数
- `CountIf` 返回让指定函数返回 `true` 的元素的个数

#### 比较

- `Equal` 判断两个序列是否相等
- `Compare` 比较两个序列,按字典序返回 -1、0、1 分别表示起大小关系

#### 查找

- `Min`, `Max` 求最大最小值
- `MinN`、`MaxN`、`MinMax` 返回 slice 中的最大和最小值
- `Find` 线性查找第一个指定的值,返回其下标
- `FindIf` 线性查找指定函数返回 `true` 的值,返回其下标
- `AllOf`、`AnyOf`、`NoneOf` 返回区间中是否全部、任何一个、没有一个元素能使传入的函数返回 `true`

#### 二分查找

参考 C++STL。

- `BinarySearch`
- `LowerBound`
- `UpperBound`

#### 排序

- `Sort` 升序排序
- `DescSort` 降序排序
- `StableSort` 升序稳定排序
- `DescStableSort` 降序稳定排序
- `IsSorted` 是否是升序排序的
- `IsDescSorted` 是否是降序排序的

#### 堆

提供基本的堆算法:

- `MakeMinHeap` 在一个切片上构造出一个最小堆
- `IsMinHeap` 判断一个切片是不是一个最小堆
- `PushMinHeap` 把一个元素压入最小堆
- `PopMinHeap` 弹出堆顶的元素
- `RemoveMinHeap` 从切片的指定位置删除一个元素

以及相应的自定义比较函数的版本:

- `MakeHeapFunc`
- `IsHeapFunc`
- `PushHeapFunc`
- `PopHeapFunc`
- `RemoveHeapFunc`

都比 go 标准库 [container/heap](https://pkg.go.dev/container/heap) 更容易使用且更快。

用法和测试详情参见[heap的文档](heap.md)。

### 接口设计和命名

较多地参考了 C++ STL。T 表示模板。是的,Go 的泛型不是模板,但是谁让 C++ 那么影响力,而 STL 又那么有名呢。

很多库的设计采用小的代码仓库或者一个仓库中拆分成多个子包。

比如

```go
import (
    "github.com/someone/awesomelib/skiplist"
    "github.com/someone/awesomelib/binarysearch"
)

func main() {
    sl := skiplist.New()
}
```

这种写法看似优雅,但是由于好的名字大家都喜欢,在使用中又不得不引入 import 重命名,而不同的使用者别名不一样,增加代码读写的心智负担。

我不太喜欢这种风格。

因此本库全部在 `stl4go` 包下,期望不会和别人的库重名。

### TODO

参见 [Issue](https://github.com/chen3feng/stl4go/issues)。

以及更详细的文档。

## Go Doc

点击查看[生成的文档](generated_doc.md).

## Reference

- [C++ STL](https://en.wikipedia.org/wiki/Standard_Template_Library)
- [liyue201/gostl](https://github.com/liyue201/gostl)
- [zyedidia/generic](https://github.com/zyedidia/generic)
- [hlccd/goSTL](https://github.com/hlccd/goSTL)


================================================
FILE: binary_search.go
================================================
package stl4go

// LowerBound returns an index to the first element in the ascending ordered slice a that
// does not satisfy element < value (i.e. greater or equal to),
// or len(a) if no such element is found.
//
// Complexity: O(log(len(a))).
func LowerBound[T Ordered](a []T, value T) int {
	loc := 0
	count := len(a)
	for count > 0 {
		i := loc
		step := count / 2
		i += step
		if a[i] < value {
			i++
			loc = i
			count -= step + 1
		} else {
			count = step
		}
	}
	return loc
}

// LowerBoundFunc returns an index to the first element in the ordered slice a that
// does not satisfy less(element, value)), or len(a) if no such element is found.
//
// The elements in the slice a should sorted according with compare func less.
//
// Complexity: O(log(len(a))).
func LowerBoundFunc[T any](a []T, value T, less LessFn[T]) int {
	loc := 0
	count := len(a)
	for count > 0 {
		i := loc
		step := count / 2
		i += step
		if less(a[i], value) {
			i++
			loc = i
			count -= step + 1
		} else {
			count = step
		}
	}
	return loc
}

// UpperBound returns an index to the first element in the ascending ordered slice a such that
// value < element (i.e. strictly greater), or len(a) if no such element is found.
//
// Complexity: O(log(len(a))).
func UpperBound[T Ordered](a []T, value T) int {
	loc := 0
	count := len(a)
	for count > 0 {
		i := loc
		step := count / 2
		i += step
		if !(value < a[i]) {
			i++
			loc = i
			count -= step + 1
		} else {
			count = step
		}
	}
	return loc
}

// UpperBoundFunc returns an index to the first element in the ordered slice a such that
// less(value, element)) is true (i.e. strictly greater), or len(a) if no such element is found.
//
// The elements in the slice a should sorted according with compare func less.
//
// Complexity: O(log(len(a))).
func UpperBoundFunc[T any](a []T, value T, less LessFn[T]) int {
	loc := 0
	count := len(a)
	for count > 0 {
		i := loc
		step := count / 2
		i += step
		if !less(value, a[i]) {
			i++
			loc = i
			count -= step + 1
		} else {
			count = step
		}
	}
	return loc
}

// BinarySearch returns the (index, true) to the first element in the ascending ordered slice a
// such that element == value, or (-1, false) if no such element is found.
//
// Complexity: O(log(len(a))).
func BinarySearch[T Ordered](a []T, value T) (index int, ok bool) {
	loc := LowerBound(a, value)
	if loc < len(a) && a[loc] == value {
		return loc, true
	}
	return -1, false
}

// BinarySearchFunc returns the (index, true) to the first element in the ordered slice a such that
// less(element, value) and less(value, element) are both false,
// or (-1, false) if no such element is found.
//
// The elements in the slice a should sorted according with compare func less.
//
// Complexity: O(log(len(a))).
func BinarySearchFunc[T any](a []T, value T, less LessFn[T]) (index int, ok bool) {
	loc := LowerBoundFunc(a, value, less)
	if loc < len(a) && !less(value, a[loc]) {
		return loc, true
	}
	return -1, false
}


================================================
FILE: binary_search_test.go
================================================
package stl4go

import "testing"

func TestLowerBound(t *testing.T) {
	a := []int{1, 2, 4, 5, 5, 6}
	expectEq(t, LowerBound(a, 1), 0)
	expectEq(t, LowerBound(a, 5), 3)
	expectEq(t, LowerBound(a, 7), len(a))
}

func TestLowerBoundFunc(t *testing.T) {
	a := []int{1, 2, 4, 5, 5, 6}
	expectEq(t, LowerBoundFunc(a, 1, Less[int]), 0)
	expectEq(t, LowerBoundFunc(a, 5, Less[int]), 3)
	expectEq(t, LowerBoundFunc(a, 7, Less[int]), len(a))
}

func TestUpperBound(t *testing.T) {
	a := []int{1, 2, 4, 5, 5, 6}
	expectEq(t, UpperBound(a, 1), 1)
	expectEq(t, UpperBound(a, 5), 5)
	expectEq(t, UpperBound(a, 7), len(a))
}

func TestUpperBoundFunc(t *testing.T) {
	a := []int{1, 2, 4, 5, 5, 6}
	expectEq(t, UpperBoundFunc(a, 1, Less[int]), 1)
	expectEq(t, UpperBoundFunc(a, 5, Less[int]), 5)
	expectEq(t, UpperBoundFunc(a, 7, Less[int]), len(a))
}

func TestBinarySearch(t *testing.T) {
	a := []int{1, 2, 4, 5, 5, 6}

	i, ok := BinarySearch(a, 4)
	expectTrue(t, ok)
	expectEq(t, i, 2)

	i, ok = BinarySearch(a, 5)
	expectTrue(t, ok)
	expectEq(t, i, 3)

	i, ok = BinarySearch(a, 3)
	expectFalse(t, ok)
}

func TestBinarySearchFunc(t *testing.T) {
	a := []int{1, 2, 4, 5, 5, 6}

	i, ok := BinarySearchFunc(a, 4, Less[int])
	expectTrue(t, ok)
	expectEq(t, i, 2)

	i, ok = BinarySearchFunc(a, 5, Less[int])
	expectTrue(t, ok)
	expectEq(t, i, 3)

	i, ok = BinarySearchFunc(a, 3, Less[int])
	expectFalse(t, ok)
}


================================================
FILE: builtin_set.go
================================================
package stl4go

import (
	"fmt"
)

// BuiltinSet is an associative container that contains an unordered set of unique objects of type K.
type BuiltinSet[K comparable] map[K]struct{}

// SetOf creates a new BuiltinSet object with the initial content from ks.
func SetOf[K comparable](ks ...K) BuiltinSet[K] {
	s := make(BuiltinSet[K])
	s.InsertN(ks...)
	return s
}

// IsEmpty implements the Container interface.
func (s BuiltinSet[K]) IsEmpty() bool {
	return len(s) == 0
}

// Len implements the Container interface.
func (s BuiltinSet[K]) Len() int {
	return len(s)
}

// Clear implements the Container interface.
func (s BuiltinSet[K]) Clear() {
	for k := range s {
		delete(s, k)
	}
}

// Has implements the Set interface.
func (s BuiltinSet[K]) Has(k K) bool {
	_, ok := s[k]
	return ok
}

// Insert implements the Set interface.
func (s BuiltinSet[K]) Insert(k K) bool {
	oldLen := len(s)
	s[k] = struct{}{}
	return len(s) > oldLen
}

// InsertN implements the Set interface.
func (s BuiltinSet[K]) InsertN(ks ...K) int {
	oldLen := len(s)
	for _, key := range ks {
		s[key] = struct{}{}
	}
	return len(s) - oldLen
}

// Remove implements the Set interface.
func (s BuiltinSet[K]) Remove(k K) bool {
	_, ok := s[k]
	delete(s, k)
	return ok
}

// Delete deletes an element from the set.
// It returns nothing, so it's faster than Remove.
func (s BuiltinSet[K]) Delete(k K) {
	delete(s, k)
}

// RemoveN implements the Set interface.
func (s BuiltinSet[K]) RemoveN(ks ...K) int {
	oldLen := len(s)
	for _, k := range ks {
		delete(s, k)
	}
	return oldLen - len(s)
}

// Keys return a copy of all keys as a slice.
func (s BuiltinSet[K]) Keys() []K {
	keys := make([]K, 0, len(s))
	for k := range s {
		keys = append(keys, k)
	}
	return keys
}

// ForEach implements the Set interface.
func (s BuiltinSet[K]) ForEach(cb func(k K)) {
	for k := range s {
		cb(k)
	}
}

// ForEachIf implements the Container interface.
func (s BuiltinSet[K]) ForEachIf(cb func(k K) bool) {
	for k := range s {
		if !cb(k) {
			break
		}
	}
}

// String implements the fmt.Stringer interface.
func (s BuiltinSet[K]) String() string {
	return fmt.Sprintf("BuiltinSet[%s]%v", nameOfType[K](), s.Keys())
}

// Update adds all elements from other to set. set |= other.
func (s BuiltinSet[K]) Update(other BuiltinSet[K]) {
	for k := range other {
		s[k] = struct{}{}
	}
}

// Union returns a new set with elements from the set and other.
func (s BuiltinSet[K]) Union(other BuiltinSet[K]) BuiltinSet[K] {
	result := BuiltinSet[K]{}
	result.Update(s)
	result.Update(other)
	return result
}

func orderSet[K comparable](a, b BuiltinSet[K]) (small, large BuiltinSet[K]) {
	if a.Len() < b.Len() {
		return a, b
	}
	return b, a
}

// Intersection returns a new set with elements common to the set and other.
func (s BuiltinSet[K]) Intersection(other BuiltinSet[K]) BuiltinSet[K] {
	result := BuiltinSet[K]{}
	small, large := orderSet(s, other)
	for k := range small {
		if large.Has(k) {
			result.Insert(k)
		}
	}
	return result
}

// Difference returns a new set with elements in the set that are not in other.
func (s BuiltinSet[K]) Difference(other BuiltinSet[K]) BuiltinSet[K] {
	result := BuiltinSet[K]{}
	for k := range s {
		if !other.Has(k) {
			result.Insert(k)
		}
	}
	return result
}

// IsDisjointOf return True if the set has no elements in common with other.
// Sets are disjoint if and only if their intersection is the empty set.
func (s BuiltinSet[K]) IsDisjointOf(other BuiltinSet[K]) bool {
	small, large := orderSet(s, other)
	for k := range small {
		if large.Has(k) {
			return false
		}
	}
	return true
}

// IsSubsetOf tests whether every element in the set is in other.
func (s BuiltinSet[K]) IsSubsetOf(other BuiltinSet[K]) bool {
	if s.Len() > other.Len() {
		return false
	}
	for k := range s {
		if !other.Has(k) {
			return false
		}
	}
	return true
}

// IsSupersetOf tests whether every element in other is in the set.
func (s BuiltinSet[K]) IsSupersetOf(other BuiltinSet[K]) bool {
	return other.IsSubsetOf(s)
}


================================================
FILE: builtin_set_test.go
================================================
package stl4go

import (
	"fmt"
	"strings"
	"testing"
)

func Test_BuiltinSet_Interface(t *testing.T) {
	s := make(BuiltinSet[int])
	_ = Set[int](&s)
}

func Test_MakeBuiltinSet(t *testing.T) {
	s := make(BuiltinSet[string])
	expectEq(t, s.Len(), 0)
	expectEq(t, s.IsEmpty(), true)
}

func Test_MakeBuiltinSet2(t *testing.T) {
	s := BuiltinSet[string]{}
	expectEq(t, s.Len(), 0)
	expectEq(t, s.IsEmpty(), true)
}

func Test_SetOf(t *testing.T) {
	s := SetOf("hello", "world")
	expectEq(t, s.Len(), 2)
}

func Test_BuiltinSet_IsEmpty(t *testing.T) {
	s := make(BuiltinSet[string])
	expectEq(t, s.IsEmpty(), true)
	s.Insert("hello")
	expectEq(t, s.IsEmpty(), false)
}

func Test_BuiltinSet_Clear(t *testing.T) {
	s := SetOf("hello", "world")
	s.Clear()
	expectTrue(t, s.IsEmpty())
}

func Test_BuiltinSet_String(t *testing.T) {
	s := SetOf("hello", "world")
	expectTrue(t, strings.HasPrefix(fmt.Sprintf("%v", s), "BuiltinSet[string]"))
}

func Test_BuiltinSet_Has(t *testing.T) {
	s := SetOf("hello", "world")
	expectTrue(t, s.Has("hello"))
	expectTrue(t, s.Has("world"))
	expectFalse(t, s.Has("!"))
}

func Test_BuiltinSet_Insert(t *testing.T) {
	s := make(BuiltinSet[string])
	expectTrue(t, s.Insert("hello"))
	expectFalse(t, s.Insert("hello"))
	expectEq(t, s.Has("world"), false)
	expectTrue(t, s.Insert("world"))
	expectEq(t, s.Has("hello"), true)
	expectEq(t, s.Len(), 2)
}

func Test_BuiltinSet_InsertN(t *testing.T) {
	s := make(BuiltinSet[string])
	expectEq(t, s.InsertN("hello", "world"), 2)
	expectEq(t, s.Len(), 2)
}

func Test_BuiltinSet_Remove(t *testing.T) {
	s := SetOf("hello", "world")
	expectTrue(t, s.Remove("hello"))
	expectEq(t, s.Len(), 1)
	expectFalse(t, s.Remove("hello"))
	expectEq(t, s.Len(), 1)
	expectTrue(t, s.Remove("world"))
	expectEq(t, s.Len(), 0)
}

func Test_BuiltinSet_Delete(t *testing.T) {
	s := SetOf("hello", "world")
	s.Delete("hello")
	expectEq(t, s.Len(), 1)
	s.Delete("hello")
	expectEq(t, s.Len(), 1)
	s.Delete("world")
	expectEq(t, s.Len(), 0)
}

func Test_BuiltinSet_RemoveN(t *testing.T) {
	s := SetOf("hello", "world")
	expectEq(t, s.RemoveN("hello", "world"), 2)
	expectFalse(t, s.Remove("world"))
	expectTrue(t, s.IsEmpty())
}

func Test_BuiltinSet_Keys(t *testing.T) {
	s := SetOf("hello", "world")
	ks := s.Keys()
	expectEq(t, 2, len(ks))
}

func Test_BuiltinSet_For(t *testing.T) {
	s := SetOf("hello", "world")
	for v := range s {
		expectTrue(t, v == "hello" || v == "world")
	}
}

func Test_BuiltinSet_ForEach(t *testing.T) {
	s := SetOf("hello", "world")
	c := 0
	s.ForEach(func(string) {
		c++
	})
	expectEq(t, c, 2)
}

func Test_BuiltinSet_ForEachIf(t *testing.T) {
	s := SetOf("hello", "world")
	c := 0
	s.ForEachIf(func(string) bool {
		c++
		return false
	})
	expectLt(t, c, 2)
}

func Test_BuiltinSet_Update(t *testing.T) {
	s := SetOf(1, 2, 3)
	s.Update(SetOf(3, 4))
	expectEq(t, s.Len(), 4)
	expectTrue(t, s.Has(4))
}

func Test_BuiltinSet_Union(t *testing.T) {
	s := SetOf(1, 2, 3)
	s2 := s.Union(SetOf(3, 4))
	expectEq(t, s2.Len(), 4)
	expectTrue(t, s2.Has(4))
}

func Test_BuiltinSet_Intersection(t *testing.T) {
	s := SetOf(1, 2, 3).Intersection(SetOf(3, 4))
	expectEq(t, s.Len(), 1)
	expectTrue(t, s.Has(3))
	s = SetOf(3, 4).Intersection(SetOf(1, 2, 3))
	expectEq(t, s.Len(), 1)
	expectTrue(t, s.Has(3))
}

func Test_BuiltinSet_Difference(t *testing.T) {
	s := SetOf(1, 2, 3).Difference(SetOf(3, 4))
	expectEq(t, s.Len(), 2)
	expectTrue(t, s.Has(1))
	expectTrue(t, s.Has(2))
	s = SetOf(1, 2).Difference(SetOf(3, 4))
	expectEq(t, s.Len(), 2)
	expectTrue(t, s.Has(1))
	expectTrue(t, s.Has(2))
}

func Test_BuiltinSet_IsDisjointOf(t *testing.T) {
	s1 := SetOf(1, 2, 3)
	s2 := SetOf(3, 4)
	expectFalse(t, s1.IsDisjointOf(s2))
	expectTrue(t, s1.IsDisjointOf(SetOf(4, 5)))
}

func Test_BuiltinSet_IsSubsetOf(t *testing.T) {
	expectTrue(t, SetOf[int]().IsSubsetOf(SetOf[int]()))
	expectTrue(t, SetOf[int]().IsSubsetOf(SetOf(1)))
	expectTrue(t, SetOf(1, 2, 3).IsSubsetOf(SetOf(1, 2, 3)))
	expectTrue(t, SetOf(1, 2).IsSubsetOf(SetOf(1, 2, 3)))
	expectFalse(t, SetOf(1, 2, 3).IsSubsetOf(SetOf(1, 2)))
	expectFalse(t, SetOf(1, 2).IsSubsetOf(SetOf(2, 3)))
}

func Test_BuiltinSet_IsSupersetOf(t *testing.T) {
	expectTrue(t, SetOf[int]().IsSupersetOf(SetOf[int]()))
	expectTrue(t, SetOf(1).IsSupersetOf(SetOf[int]()))
	expectTrue(t, SetOf(1, 2, 3).IsSupersetOf(SetOf(1, 2, 3)))
	expectTrue(t, SetOf(1, 2, 3).IsSupersetOf(SetOf(1, 2)))
	expectFalse(t, SetOf(1, 2).IsSupersetOf(SetOf(1, 2, 3)))
	expectFalse(t, SetOf(1, 2).IsSupersetOf(SetOf(2, 3)))
}


================================================
FILE: check.bat
================================================
go build

go test ./... -coverprofile=coverage.out

golint

gosec .

go tool cover -html=coverage.out


================================================
FILE: check.sh
================================================
#!/bin/bash

set -e

go build

go test ./... -coverprofile=coverage.out

golint

gosec .

go tool cover -html=coverage.out


================================================
FILE: compare.go
================================================
package stl4go

// Equal returns whether two slices are equal.
// Return true if they are the same length and all elements are equal.
//
// Complexity: O(min(len(a), len(b))).
func Equal[T comparable](a, b []T) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

// Compare compares each elements in a and b.
//
// return 0 if they are equals,
// return 1 if a > b,
// return -1 if a < b.
//
// Complexity: O(min(len(a), len(b))).
func Compare[E Ordered](a, b []E) int {
	bl := len(b)
	for i, v1 := range a {
		if i >= bl {
			return 1
		}
		v2 := b[i]
		switch {
		case v1 < v2:
			return -1
		case v1 > v2:
			return 1
		}
	}
	if len(a) < bl {
		return -1
	}
	return 0
}


================================================
FILE: compare_test.go
================================================
package stl4go

import "testing"

func Test_Equal(t *testing.T) {
	expectTrue(t, Equal([]int{}, []int{}))
	expectTrue(t, Equal([]int{1, 2, 3}, []int{1, 2, 3}))
	expectFalse(t, Equal([]int{1, 2}, []int{1, 2, 3}))
	expectFalse(t, Equal([]int{1, 2, 2}, []int{1, 2, 3}))
}

func Test_Compare(t *testing.T) {
	expectEq(t, Compare([]int{}, []int{}), 0)
	expectEq(t, Compare([]int{1, 2, 3}, []int{1, 2, 3}), 0)
	expectEq(t, Compare([]int{1, 2, 2}, []int{1, 2, 3}), -1)
	expectEq(t, Compare([]int{1, 2, 4}, []int{1, 2, 3}), 1)
	expectEq(t, Compare([]int{1, 2}, []int{1, 2, 3}), -1)
	expectEq(t, Compare([]int{1, 2, 3}, []int{1, 2}), 1)
}


================================================
FILE: compute.go
================================================
package stl4go

// SumAs summarize all elements in a.
// returns the result as type R, this is useful when T is too small to hold the result.
// Complexity: O(len(a)).
func SumAs[R, T Numeric](a []T) R {
	switch zero := T(0); any(zero).(type) {
	case int8, int16, int32, int, int64:
		var total int64
		for _, v := range a {
			total += int64(v)
		}
		return R(total)
	case uint8, uint16, uint32, uint, uint64, uintptr:
		var total uint64
		for _, v := range a {
			total += uint64(v)
		}
		return R(total)
	default:
		var total float64
		for _, v := range a {
			total += float64(v)
		}
		return R(total)
	}
}

// Sum summarize all elements in a.
// returns the result as type R, you should use SumAs if T can't hold the result.
// Complexity: O(len(a)).
func Sum[T Numeric](a []T) T {
	return SumAs[T](a)
}

// AverageAs returns the average value of a as type R.
func AverageAs[R, T Numeric](a []T) R {
	return SumAs[R](a) / R(len(a))
}

// Average returns the average value of a.
func Average[T Numeric](a []T) T {
	var zero T // NOTE: convert 0 to interface have no malloc
	switch any(zero).(type) {
	case int, int8, uint8, int16, uint16, int32, uint32:
		return T(AverageAs[int64](a))
	case uint64:
		return T(AverageAs[uint64](a))
	case float32, float64:
		return T(AverageAs[float64](a))
	}
	// int64, uint64, uintptr ...
	return AverageAs[T](a)
}

// Count returns the number of elements in the slice equals to x.
//
// Complexity: O(len(a)).
func Count[T comparable](a []T, x T) int {
	c := 0
	for _, v := range a {
		if v == x {
			c++
		}
	}
	return c
}

// CountIf returns the number of elements in the slice which pred returns true.
//
// Complexity: O(len(a)).
func CountIf[T comparable](a []T, pred func(T) bool) int {
	c := 0
	for _, v := range a {
		if pred(v) {
			c++
		}
	}
	return c
}


================================================
FILE: compute_test.go
================================================
package stl4go

import (
	"testing"
)

func Test_SumAs(t *testing.T) {
	t.Run("sum uint8 to int", func(t *testing.T) {
		a := Range[uint8](1, 101)
		expectEq(t, SumAs[int](a), 5050)
	})

	t.Run("sum int to uint8", func(t *testing.T) {
		a := Range[int](1, 101)
		expectEq(t, SumAs[uint8](a), uint8(5050%256))
	})

	t.Run("sum int64 to float64", func(t *testing.T) {
		a := Range[int64](1, 101)
		expectEq(t, SumAs[float64](a), 5050.)
	})

	t.Run("sum float64 to int64", func(t *testing.T) {
		a := Range[float64](1.1, 101.1)
		expectEq(t, SumAs[int](a), 101.2*50) // 5060
	})
}

func Test_Sum(t *testing.T) {
	a := Range(1, 101)
	expectEq(t, Sum(a), 5050)
}

func Test_Average(t *testing.T) {
	a := Range(1, 101)
	expectEq(t, Average(a), 50)
}

func Test_AverageAs(t *testing.T) {
	a := []int{1, 0}
	expectEq(t, AverageAs[float64](a), 0.5)
}

func Test_Average_U64(t *testing.T) {
	a := Range[uint64](0, 101)
	expectEq(t, Average(a), 50)
}

func Test_Average_Float(t *testing.T) {
	a := Range(0.0, 101.0)
	expectEq(t, Average(a), 50.0)
}

func Test_Average_SmallType(t *testing.T) {
	a := Range[uint8](0, 101)
	expectEq(t, Average(a), 50)
}

func Test_Average_UintPtr(t *testing.T) {
	a := Range[uintptr](0, 101)
	expectEq(t, Average(a), 50)
}

func Test_Average_Signed(t *testing.T) {
	a := []int{-2, 1, -1, 2, 1, -1, 0}
	expectEq(t, Average(a), 0)
}

func Test_Count(t *testing.T) {
	a := []int{1, 2, 3, 4, 3}
	expectEq(t, Count(a, 3), 2)
	expectEq(t, CountIf(pos, isNegative), 0)
	expectEq(t, CountIf(neg, isNegative), 5)
	expectEq(t, CountIf(mix, isNegative), 2)
}


================================================
FILE: container.go
================================================
package stl4go

// Container is a holder object that stores a collection of other objects.
type Container interface {
	IsEmpty() bool // IsEmpty checks if the container has no elements.
	Len() int      // Len returns the number of elements in the container.
	Clear()        // Clear erases all elements from the container. After this call, Len() returns zero.
}

// Map is a associative container that contains key-value pairs with unique keys.
type Map[K any, V any] interface {
	Container
	Has(K) bool                        // Checks whether the container contains element with specific key.
	Find(K) *V                         // Finds element with specific key.
	Insert(K, V)                       // Inserts a key-value pair in to the container or replace existing value.
	Remove(K) bool                     // Remove element with specific key.
	ForEach(func(K, V))                // Iterate the container.
	ForEachIf(func(K, V) bool)         // Iterate the container, stops when the callback returns false.
	ForEachMutable(func(K, *V))        // Iterate the container, *V is mutable.
	ForEachMutableIf(func(K, *V) bool) // Iterate the container, *V is mutable, stops when the callback returns false.
}

// Set is a containers that store unique elements.
type Set[K any] interface {
	Container
	Has(K) bool             // Checks whether the container contains element with specific key.
	Insert(K) bool          // Inserts a element in to the container or replace existing value.
	InsertN(...K) int       // Inserts multiple elements in to the container or replace existing value.
	Remove(K) bool          // Remove specific element, return true if element was in the container.
	RemoveN(...K) int       // Remove multiple elements, return the number of removed elements.
	ForEach(func(K))        // Iterate the container.
	ForEachIf(func(K) bool) // Iterate the container, stops when the callback returns false.
}

// SortedMap is a Map that provides a total ordering on its keys.
type SortedMap[K any, V any] interface {
	Map[K, V]
	// LowerBound returns an iterator to the first element in the container that
	// does not satisfy element.key < value (i.e. greater or equal to),
	// or a end iterator if no such element is found.
	LowerBound(K) MutableMapIterator[K, V]

	// UpperBound returns an iterator to the first element in the container that
	// does not satisfy value < element.key (i.e. strictly greater),
	// or a end iterator if no such element is found.
	UpperBound(K) MutableMapIterator[K, V]

	// FindRange returns an iterator in range [first, last) (last is not included).
	FindRange(K, K) MutableMapIterator[K, V]
}

// SortedSet is a Set that provides a total ordering on its elements.
type SortedSet[K any] interface {
	Set[K]

	// LowerBound returns an iterator to the first element in the container that
	// does not satisfy element < value (i.e. greater or equal to),
	// or a end iterator if no such element is found.
	LowerBound(K) Iterator[K]

	// UpperBound returns an iterator to the first element in the container that
	// does not satisfy value < element (i.e. strictly greater),
	// or a end iterator if no such element is found.
	UpperBound(K) Iterator[K]

	// FindRange returns an iterator in range [first, last) (last is not included).
	FindRange(K, K) Iterator[K]
}

// Queue is a container that can add elements to one end and remove elements from the other end.
type Queue[T any] interface {
	Container
	Front()            // Front returns the first element in the container.
	Back()             // Back returns the last element in the container.
	Push(T)            // Push pushes an element at the back of the container.
	Pop() T            // Pop popups a front from the back of the container.
	TryPop() (T, bool) // TryPop tries to popup a element from the front of the container.
}

// Deque is a container that can add and remove elements from both ends.
type Deque[T any] interface {
	Container
	Front() T               // Front returns the first element in the container.
	Back() T                // Back returns the last element in the container.
	PushFront(T)            // PushBack pushes an element at the front of the container.
	PushBack(T)             // PushBack pushes an element at the back of the container.
	PopFront() T            // PopBack popups a front from the back of the container.
	PopBack() T             // PopBack popups a element from the back of the container.
	TryPopFront() (T, bool) // TryPopFront tries to popup a element from the front of the container.
	TryPopBack() (T, bool)  // TryPopBack tries to popup a element from the back of the container.
}


================================================
FILE: container_test.go
================================================
package stl4go


================================================
FILE: dlist.go
================================================
package stl4go

import "fmt"

// DList is a doubly linked list.
type DList[T any] struct {
	head   *dListNode[T]
	length int
}

type dListNode[T any] struct {
	prev, next *dListNode[T]
	value      T
}

// DListOf make a new DList from a serial of values.
func DListOf[T any](vs ...T) DList[T] {
	l := DList[T]{}
	for _, v := range vs {
		l.PushBack(v)
	}
	return l
}

// Clear cleanup the list.
func (l *DList[T]) Clear() {
	if l.head != nil {
		l.head.prev = l.head
		l.head.next = l.head
	}
	l.length = 0
}

// Len return the length of the list.
func (l *DList[T]) Len() int {
	return l.length
}

// IsEmpty return whether the list is empty.
func (l *DList[T]) IsEmpty() bool {
	return l.length == 0
}

// String convert the list to string.
func (l *DList[T]) String() string {
	return fmt.Sprintf("DList[%v]", nameOfType[T]())
}

type dlistIterator[T any] struct {
	dl   *DList[T]
	node *dListNode[T]
}

func (it *dlistIterator[T]) IsNotEnd() bool {
	return it.node != it.dl.head
}

func (it *dlistIterator[T]) MoveToNext() {
	it.node = it.node.next
}

func (it *dlistIterator[T]) Value() T {
	return it.node.value
}

func (it *dlistIterator[T]) Pointer() *T {
	return &it.node.value
}

// Iterate returns an iterator to the first element in the list.
func (l *DList[T]) Iterate() MutableIterator[T] {
	node := l.head
	if node != nil {
		node = node.next
	}
	return &dlistIterator[T]{l, node}
}

// Front returns the first element in the container.
func (l *DList[T]) Front() T {
	if l.IsEmpty() {
		panic("!IsEmpty")
	}
	return l.head.next.value
}

// Back returns the last element in the container.
func (l *DList[T]) Back() T {
	if l.IsEmpty() {
		panic("!IsEmpty")
	}
	return l.head.prev.value
}

// PushFront pushes an element at the front of the list.
func (l *DList[T]) PushFront(val T) {
	l.ensureHead()
	n := dListNode[T]{l.head, l.head.next, val}
	l.head.next.prev = &n
	l.head.next = &n
	l.length++
}

// PushBack pushes an element at the back of the list.
func (l *DList[T]) PushBack(val T) {
	l.ensureHead()
	n := dListNode[T]{l.head.prev, l.head, val}
	l.head.prev.next = &n
	l.head.prev = &n
	l.length++
}

// PopFront popups an element from the front of the list.
func (l *DList[T]) PopFront() T {
	r, ok := l.TryPopFront()
	if !ok {
		panic("DList.PopFront: empty list")
	}
	return r
}

// PopBack popups an element from the back of the list.
func (l *DList[T]) PopBack() T {
	r, ok := l.TryPopBack()
	if !ok {
		panic("DList.PopBack: empty list")
	}
	return r
}

// TryPopFront tries to pop up an element from the front of the list.
func (l *DList[T]) TryPopFront() (T, bool) {
	var val T
	if l.IsEmpty() {
		return val, false
	}
	node := l.head.next
	val = node.value
	l.head.next = node.next
	l.head.next.prev = l.head
	node.prev = nil
	node.next = nil
	l.length--
	return val, true
}

// TryPopBack tries to pop up an element from the back of the list.
func (l *DList[T]) TryPopBack() (T, bool) {
	var val T
	if l.IsEmpty() {
		return val, false
	}
	node := l.head.prev
	val = node.value
	l.head.prev = l.head.prev.prev
	l.head.prev.next = l.head
	node.prev = nil
	node.next = nil
	l.length--
	return val, true
}

// ForEach iterate the list, apply each element to the cb callback function.
func (l *DList[T]) ForEach(cb func(val T)) {
	if l.IsEmpty() {
		return
	}
	for n := l.head.next; n != l.head; n = n.next {
		cb(n.value)
	}
}

// ForEachIf iterate the list, apply each element to the cb callback function,
// stop if cb returns false.
func (l *DList[T]) ForEachIf(cb func(val T) bool) {
	if l.IsEmpty() {
		return
	}
	for n := l.head.next; n != l.head; n = n.next {
		if !cb(n.value) {
			break
		}
	}
}

// ForEachMutable iterate the list, apply pointer of each element to the cb callback function.
func (l *DList[T]) ForEachMutable(cb func(val *T)) {
	if l.IsEmpty() {
		return
	}
	for n := l.head.next; n != l.head; n = n.next {
		cb(&n.value)
	}
}

// ForEachMutableIf iterate the list, apply pointer of each element to the cb callback function,
// stop if cb returns false.
func (l *DList[T]) ForEachMutableIf(cb func(val *T) bool) {
	if l.IsEmpty() {
		return
	}
	for n := l.head.next; n != l.head; n = n.next {
		if !cb(&n.value) {
			break
		}
	}
}

// ensureHead ensure head is valid.
func (l *DList[T]) ensureHead() {
	if l.head == nil {
		l.head = &dListNode[T]{}
		l.head.prev = l.head
		l.head.next = l.head
	}
}


================================================
FILE: dlist_queue.go
================================================
package stl4go

import (
	"fmt"
)

// DListQueue is a FIFO container
type DListQueue[T any] struct {
	list DList[T]
}

// NewDListQueue create a new Queue object.
func NewDListQueue[T any]() *DListQueue[T] {
	q := DListQueue[T]{}
	return &q
}

// Len implements the Container interface.
func (q *DListQueue[T]) Len() int {
	return q.list.Len()
}

// IsEmpty implements the Container interface.
func (q *DListQueue[T]) IsEmpty() bool {
	return q.list.IsEmpty()
}

// Clear implements the Container interface.
func (q *DListQueue[T]) Clear() {
	q.list.Clear()
}

// Len implements the fmt.Stringer interface.
func (q *DListQueue[T]) String() string {
	return fmt.Sprintf("Queue[%v]", nameOfType[T]())
}

// Front returns the first element in the container.
func (q *DListQueue[T]) Front() T {
	return q.list.Front()
}

// Back returns the last element in the container.
func (q *DListQueue[T]) Back() T {
	return q.list.Back()
}

// PushFront pushed an element to the front of the queue.
func (q *DListQueue[T]) PushFront(val T) {
	q.list.PushFront(val)
}

// PushBack pushed an element to the back of the queue.
func (q *DListQueue[T]) PushBack(val T) {
	q.list.PushBack(val)
}

// PopFront popups an element from the front of the queue.
func (q *DListQueue[T]) PopFront() T {
	return q.list.PopFront()
}

// PopBack popups an element from the back of the queue.
func (q *DListQueue[T]) PopBack() T {
	return q.list.PopBack()
}

// TryPopFront tries popuping an element from the front of the queue.
func (q *DListQueue[T]) TryPopFront() (T, bool) {
	return q.list.TryPopFront()
}

// TryPopBack tries popuping an element from the back of the queue.
func (q *DListQueue[T]) TryPopBack() (T, bool) {
	return q.list.TryPopBack()
}


================================================
FILE: dlist_queue_test.go
================================================
package stl4go

import (
	"testing"
)

func Test_Queue_Interface(t *testing.T) {
	q := NewDListQueue[int]()
	_ = Deque[int](q)
}

func Test_Queue_New(t *testing.T) {
	q := NewDListQueue[int]()
	expectTrue(t, q.IsEmpty())
	expectEq(t, q.Len(), 0)
}

func Test_Queue_Clear(t *testing.T) {
	q := NewDListQueue[int]()
	q.PushBack(1)
	q.Clear()
	expectTrue(t, q.IsEmpty())
	expectEq(t, q.Len(), 0)
}

func Test_Queue_String(t *testing.T) {
	q := NewDListQueue[int]()
	expectEq(t, q.String(), "Queue[int]")
}

func Test_Queue_Front_Back(t *testing.T) {
	q := NewDListQueue[int]()
	expectPanic(t, func() { q.Front() })
	expectPanic(t, func() { q.Back() })
	q.PushBack(1)
	q.PushBack(2)
	expectEq(t, q.Front(), 1)
	expectEq(t, q.Back(), 2)
}

func Test_Queue_PushFront(t *testing.T) {
	q := NewDListQueue[int]()
	q.PushFront(1)
	expectFalse(t, q.IsEmpty())
	expectEq(t, q.Len(), 1)
}

func Test_Queue_PushBack(t *testing.T) {
	q := NewDListQueue[int]()
	q.PushBack(1)
	expectFalse(t, q.IsEmpty())
	expectEq(t, q.Len(), 1)
}

func Test_Queue_TryPopFront(t *testing.T) {
	q := NewDListQueue[int]()
	_, ok := q.TryPopFront()
	expectFalse(t, ok)
}
func Test_Queue_TryPopBack(t *testing.T) {
	q := NewDListQueue[int]()
	_, ok := q.TryPopBack()
	expectFalse(t, ok)
}

func Test_Queue_PushFront_PopFront(t *testing.T) {
	q := NewDListQueue[int]()
	q.PushFront(1)
	q.PushFront(2)
	expectEq(t, q.PopFront(), 2)
	expectEq(t, q.PopFront(), 1)
}

func Test_Queue_PushFront_PopBack(t *testing.T) {
	q := NewDListQueue[int]()
	q.PushFront(1)
	expectEq(t, q.PopBack(), 1)
}

func Test_Queue_PushBack_PopFront(t *testing.T) {
	q := NewDListQueue[int]()
	q.PushBack(1)
	expectEq(t, q.PopFront(), 1)
}

func Test_Queue_PushBack_PopBack(t *testing.T) {
	q := NewDListQueue[int]()
	q.PushBack(1)
	expectEq(t, q.PopBack(), 1)
}


================================================
FILE: dlist_test.go
================================================
package stl4go

import (
	"testing"
)

func Test_Dlist_Interface(t *testing.T) {
	_ = Container(&DList[int]{})
}

func Test_DList_New(t *testing.T) {
	l := DList[int]{}
	expectTrue(t, l.IsEmpty())
	expectEq(t, l.Len(), 0)
}

func Test_DListOf(t *testing.T) {
	l := DListOf(1, 2, 3)
	expectFalse(t, l.IsEmpty())
	expectEq(t, l.Len(), 3)
}

func Test_DList_String(t *testing.T) {
	l := DList[int]{}
	expectEq(t, l.String(), "DList[int]")
}

func Test_DList_Iterate(t *testing.T) {
	l := DListOf(1, 2, 3)
	i := 1
	for it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {
		expectEq(t, it.Value(), i)
		expectEq(t, *it.Pointer(), i)
		i++
	}
	expectEq(t, i, 4)
}

func Test_DList_Iterate_Empty(t *testing.T) {
	l := DList[int]{}
	i := 0
	for it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {
		i++
	}
	expectEq(t, i, 0)
}

func Test_DList_FrontBack(t *testing.T) {
	l := DListOf(1, 2, 3)
	expectEq(t, l.Front(), 1)
	expectEq(t, l.Back(), 3)
}

func Test_DList_PushFront(t *testing.T) {
	l := DList[int]{}
	l.PushFront(1)
	expectFalse(t, l.IsEmpty())
	expectEq(t, l.Len(), 1)
}

func Test_DList_PushBack(t *testing.T) {
	l := DList[int]{}
	l.PushBack(1)
	expectFalse(t, l.IsEmpty())
	expectEq(t, l.Len(), 1)
}

func Test_DList_PopFront(t *testing.T) {
	l := DListOf(1, 2, 3, 4)
	expectEq(t, l.PopFront(), 1)
	expectEq(t, l.PopFront(), 2)

	n, ok := l.TryPopFront()
	expectEq(t, n, 3)
	expectTrue(t, ok)

	n, ok = l.TryPopBack()
	expectEq(t, n, 4)
	expectTrue(t, ok)

	n, ok = l.TryPopFront()
	expectFalse(t, ok)
	expectPanic(t, func() { l.PopFront() })
}

func Test_DList_PopBack(t *testing.T) {
	l := DListOf(1, 2, 3, 4)
	expectEq(t, l.PopBack(), 4)
	expectEq(t, l.PopBack(), 3)

	n, ok := l.TryPopBack()
	expectTrue(t, ok)
	expectEq(t, n, 2)

	n, ok = l.TryPopFront()
	expectTrue(t, ok)
	expectEq(t, n, 1)

	n, ok = l.TryPopBack()
	expectFalse(t, ok)
	expectPanic(t, func() { l.PopBack() })
}

func Test_DList_PushBack_PopFront(t *testing.T) {
	l := DList[int]{}
	l.PushBack(1)
	l.PushBack(2)

	v := l.PopFront()
	expectEq(t, v, 1)
	expectEq(t, l.PopFront(), 2)
}

func Test_DList_PushBack_PopBack(t *testing.T) {
	l := DList[int]{}
	l.PushBack(1)
	v := l.PopBack()
	expectEq(t, v, 1)
}

func Test_DList_PushFront_PopBack(t *testing.T) {
	l := DList[int]{}
	l.PushFront(1)
	v := l.PopBack()
	expectEq(t, v, 1)
}

func Test_DList_PushFront_PopFront(t *testing.T) {
	l := DList[int]{}
	l.PushFront(1)
	v := l.PopFront()
	expectEq(t, v, 1)
}

func Test_DList_ForEach(t *testing.T) {
	a := []int{1, 2, 3}
	l := DListOf(a...)
	var b []int
	l.ForEach(func(n int) {
		b = append(b, n)
	})
	expectEq(t, len(b), 3)
	expectTrue(t, Equal(a, b))
}

func Test_DList_ForEachIf(t *testing.T) {
	l := DListOf(1, 2, 3)
	c := 0
	l.ForEachIf(func(n int) bool {
		c = n
		return n != 2
	})
	expectEq(t, c, 2)
}

func Test_DList_ForEachMutable(t *testing.T) {
	a := []int{1, 2, 3}
	l := DListOf(a...)
	l.ForEachMutable(func(n *int) {
		*n = -*n
	})
	var b []int
	l.ForEach(func(n int) {
		b = append(b, n)
	})
	expectEq(t, len(b), 3)
	for i := range b {
		expectEq(t, a[i], -b[i])
	}
}

func Test_DList_ForEachMutableIf(t *testing.T) {
	l := DListOf(1, 2, 3)
	c := 0
	l.ForEachMutableIf(func(n *int) bool {
		c = *n
		return *n != 2
	})
	expectEq(t, c, 2)
}

func Test_DList_ForEach_EmptyOK(t *testing.T) {
	l := DList[int]{}
	l.ForEach(func(n int) {})
	l.ForEachIf(func(n int) bool { return true })
	l.ForEachMutable(func(n *int) {})
	l.ForEachMutableIf(func(n *int) bool { return true })
}

func Benchmark_DList_Iterate(b *testing.B) {
	l := DListOf(Range(1, 10000)...)
	b.Run("Iterator", func(b *testing.B) {
		sum := 0
		for i := 0; i < b.N; i++ {
			for it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {
				sum += it.Value()
			}
		}
	})
	b.Run("ForEach", func(b *testing.B) {
		sum := 0
		for i := 0; i < b.N; i++ {
			l.ForEach(func(val int) { sum += val })
		}
	})
}


================================================
FILE: doc.go
================================================
// Package stl4go is a generic container and algorithm library for go.
package stl4go


================================================
FILE: functor.go
================================================
package stl4go

// Less wraps the '<' operator for ordered types.
func Less[T Ordered](a, b T) bool {
	return a < b
}

// Greater wraps the '>' operator for ordered types.
func Greater[T Ordered](a, b T) bool {
	return a > b
}

// OrderedCompare provide default CompareFn for ordered types.
func OrderedCompare[T Ordered](a, b T) int {
	if a < b {
		return -1
	}
	if a > b {
		return 1
	}
	return 0
}


================================================
FILE: generate.go
================================================
package stl4go

// Range make a []T filled with values in the `[first, last)` sequence.
// NOTE: the last is not included in the result.
//
// Complexity: O(last-first).
func Range[T Numeric](first, last T) []T {
	a := make([]T, 0, int(last-first))
	for v := first; v < last; v++ {
		a = append(a, v)
	}
	return a
}

// Generate fill each element of `a`` with `gen()`.
//
// Complexity: O(len(a)).
func Generate[T any](a []T, gen func() T) {
	for i := range a {
		a[i] = gen()
	}
}


================================================
FILE: generate_test.go
================================================
package stl4go

import "testing"

func Test_Range(t *testing.T) {
	a := Range(0, 100)
	expectEq(t, len(a), 100)
	expectEq(t, a[0], 0)
	expectEq(t, a[99], 99)
}

func Test_Generate(t *testing.T) {
	a := make([]int, 100)
	i := -1
	Generate(a, func() int { i++; return i })
	for i, v := range a {
		expectEq(t, v, i)
	}
}


================================================
FILE: generated_doc.md
================================================
<!-- markdownlint-disable -->
<!-- gomarkdoc:embed:start -->

<!-- Code generated by gomarkdoc. DO NOT EDIT -->

# stl4go

```go
import "github.com/chen3feng/stl4go"
```

Package stl4go is a generic container and algorithm library for go.

## Index

- [func AllOf\[T any\]\(a \[\]T, pred func\(T\) bool\) bool](<#AllOf>)
- [func AnyOf\[T any\]\(a \[\]T, pred func\(T\) bool\) bool](<#AnyOf>)
- [func Average\[T Numeric\]\(a \[\]T\) T](<#Average>)
- [func AverageAs\[R, T Numeric\]\(a \[\]T\) R](<#AverageAs>)
- [func BinarySearch\[T Ordered\]\(a \[\]T, value T\) \(index int, ok bool\)](<#BinarySearch>)
- [func BinarySearchFunc\[T any\]\(a \[\]T, value T, less LessFn\[T\]\) \(index int, ok bool\)](<#BinarySearchFunc>)
- [func Compare\[E Ordered\]\(a, b \[\]E\) int](<#Compare>)
- [func Copy\[T any\]\(a \[\]T\) \[\]T](<#Copy>)
- [func CopyTo\[T any\]\(a \[\]T, to \[\]T\) \[\]T](<#CopyTo>)
- [func Count\[T comparable\]\(a \[\]T, x T\) int](<#Count>)
- [func CountIf\[T comparable\]\(a \[\]T, pred func\(T\) bool\) int](<#CountIf>)
- [func DescSort\[T Ordered\]\(a \[\]T\)](<#DescSort>)
- [func DescStableSort\[T Ordered\]\(a \[\]T\)](<#DescStableSort>)
- [func Equal\[T comparable\]\(a, b \[\]T\) bool](<#Equal>)
- [func Fill\[T any\]\(a \[\]T, v T\)](<#Fill>)
- [func FillPattern\[T any\]\(a \[\]T, pattern \[\]T\)](<#FillPattern>)
- [func FillZero\[T any\]\(a \[\]T\)](<#FillZero>)
- [func Find\[T comparable\]\(a \[\]T, x T\) \(index int, ok bool\)](<#Find>)
- [func FindIf\[T any\]\(a \[\]T, cond func\(T\) bool\) \(index int, ok bool\)](<#FindIf>)
- [func Generate\[T any\]\(a \[\]T, gen func\(\) T\)](<#Generate>)
- [func Greater\[T Ordered\]\(a, b T\) bool](<#Greater>)
- [func Index\[T comparable\]\(a \[\]T, x T\) int](<#Index>)
- [func IsDescSorted\[T Ordered\]\(a \[\]T\) bool](<#IsDescSorted>)
- [func IsHeapFunc\[T any\]\(array \[\]T, less LessFn\[T\]\) bool](<#IsHeapFunc>)
- [func IsMinHeap\[T Ordered\]\(array \[\]T\) bool](<#IsMinHeap>)
- [func IsSorted\[T Ordered\]\(a \[\]T\) bool](<#IsSorted>)
- [func Less\[T Ordered\]\(a, b T\) bool](<#Less>)
- [func LowerBound\[T Ordered\]\(a \[\]T, value T\) int](<#LowerBound>)
- [func LowerBoundFunc\[T any\]\(a \[\]T, value T, less LessFn\[T\]\) int](<#LowerBoundFunc>)
- [func MakeHeapFunc\[T any\]\(array \[\]T, less LessFn\[T\]\)](<#MakeHeapFunc>)
- [func MakeMinHeap\[T Ordered\]\(array \[\]T\)](<#MakeMinHeap>)
- [func Max\[T Ordered\]\(a, b T\) T](<#Max>)
- [func MaxN\[T Ordered\]\(a ...T\) T](<#MaxN>)
- [func Min\[T Ordered\]\(a, b T\) T](<#Min>)
- [func MinMax\[T Ordered\]\(a, b T\) \(min, max T\)](<#MinMax>)
- [func MinMaxN\[T Ordered\]\(a ...T\) \(min, max T\)](<#MinMaxN>)
- [func MinN\[T Ordered\]\(a ...T\) T](<#MinN>)
- [func NoneOf\[T any\]\(a \[\]T, pred func\(T\) bool\) bool](<#NoneOf>)
- [func OrderedCompare\[T Ordered\]\(a, b T\) int](<#OrderedCompare>)
- [func PopHeapFunc\[T any\]\(heap \*\[\]T, less LessFn\[T\]\) T](<#PopHeapFunc>)
- [func PopMinHeap\[T Ordered\]\(heap \*\[\]T\) T](<#PopMinHeap>)
- [func PushHeapFunc\[T any\]\(heap \*\[\]T, v T, less LessFn\[T\]\)](<#PushHeapFunc>)
- [func PushMinHeap\[T Ordered\]\(heap \*\[\]T, v T\)](<#PushMinHeap>)
- [func Range\[T Numeric\]\(first, last T\) \[\]T](<#Range>)
- [func Remove\[T comparable\]\(a \[\]T, x T\) \[\]T](<#Remove>)
- [func RemoveCopy\[T comparable\]\(a \[\]T, x T\) \[\]T](<#RemoveCopy>)
- [func RemoveHeapFunc\[T any\]\(heap \*\[\]T, i int, less LessFn\[T\]\) T](<#RemoveHeapFunc>)
- [func RemoveIf\[T any\]\(a \[\]T, cond func\(T\) bool\) \[\]T](<#RemoveIf>)
- [func RemoveIfCopy\[T any\]\(a \[\]T, cond func\(T\) bool\) \[\]T](<#RemoveIfCopy>)
- [func RemoveMinHeap\[T Ordered\]\(heap \*\[\]T, i int\) T](<#RemoveMinHeap>)
- [func Replace\[T comparable\]\(a \[\]T, old, new T\)](<#Replace>)
- [func ReplaceIf\[T any\]\(a \[\]T, pred func\(v T\) bool, new T\)](<#ReplaceIf>)
- [func Reverse\[T any\]\(a \[\]T\)](<#Reverse>)
- [func ReverseCopy\[T any\]\(a \[\]T\) \[\]T](<#ReverseCopy>)
- [func Shuffle\[T any\]\(a \[\]T\)](<#Shuffle>)
- [func Sort\[T Ordered\]\(a \[\]T\)](<#Sort>)
- [func SortFunc\[T any\]\(a \[\]T, less func\(x, y T\) bool\)](<#SortFunc>)
- [func StableSort\[T Ordered\]\(a \[\]T\)](<#StableSort>)
- [func StableSortFunc\[T any\]\(a \[\]T, less func\(x, y T\) bool\)](<#StableSortFunc>)
- [func Sum\[T Numeric\]\(a \[\]T\) T](<#Sum>)
- [func SumAs\[R, T Numeric\]\(a \[\]T\) R](<#SumAs>)
- [func Transform\[T any\]\(a \[\]T, op func\(T\) T\)](<#Transform>)
- [func TransformCopy\[R any, T any\]\(a \[\]T, op func\(T\) R\) \[\]R](<#TransformCopy>)
- [func TransformTo\[R any, T any\]\(a \[\]T, op func\(T\) R, b \[\]R\) \[\]R](<#TransformTo>)
- [func Unique\[T comparable\]\(a \[\]T\) \[\]T](<#Unique>)
- [func UniqueCopy\[T comparable\]\(a \[\]T\) \[\]T](<#UniqueCopy>)
- [func UpperBound\[T Ordered\]\(a \[\]T, value T\) int](<#UpperBound>)
- [func UpperBoundFunc\[T any\]\(a \[\]T, value T, less LessFn\[T\]\) int](<#UpperBoundFunc>)
- [type BuiltinSet](<#BuiltinSet>)
  - [func SetOf\[K comparable\]\(ks ...K\) BuiltinSet\[K\]](<#SetOf>)
  - [func \(s BuiltinSet\[K\]\) Clear\(\)](<#BuiltinSet[K].Clear>)
  - [func \(s BuiltinSet\[K\]\) Delete\(k K\)](<#BuiltinSet[K].Delete>)
  - [func \(s BuiltinSet\[K\]\) Difference\(other BuiltinSet\[K\]\) BuiltinSet\[K\]](<#BuiltinSet[K].Difference>)
  - [func \(s BuiltinSet\[K\]\) ForEach\(cb func\(k K\)\)](<#BuiltinSet[K].ForEach>)
  - [func \(s BuiltinSet\[K\]\) ForEachIf\(cb func\(k K\) bool\)](<#BuiltinSet[K].ForEachIf>)
  - [func \(s BuiltinSet\[K\]\) Has\(k K\) bool](<#BuiltinSet[K].Has>)
  - [func \(s BuiltinSet\[K\]\) Insert\(k K\) bool](<#BuiltinSet[K].Insert>)
  - [func \(s BuiltinSet\[K\]\) InsertN\(ks ...K\) int](<#BuiltinSet[K].InsertN>)
  - [func \(s BuiltinSet\[K\]\) Intersection\(other BuiltinSet\[K\]\) BuiltinSet\[K\]](<#BuiltinSet[K].Intersection>)
  - [func \(s BuiltinSet\[K\]\) IsDisjointOf\(other BuiltinSet\[K\]\) bool](<#BuiltinSet[K].IsDisjointOf>)
  - [func \(s BuiltinSet\[K\]\) IsEmpty\(\) bool](<#BuiltinSet[K].IsEmpty>)
  - [func \(s BuiltinSet\[K\]\) IsSubsetOf\(other BuiltinSet\[K\]\) bool](<#BuiltinSet[K].IsSubsetOf>)
  - [func \(s BuiltinSet\[K\]\) IsSupersetOf\(other BuiltinSet\[K\]\) bool](<#BuiltinSet[K].IsSupersetOf>)
  - [func \(s BuiltinSet\[K\]\) Keys\(\) \[\]K](<#BuiltinSet[K].Keys>)
  - [func \(s BuiltinSet\[K\]\) Len\(\) int](<#BuiltinSet[K].Len>)
  - [func \(s BuiltinSet\[K\]\) Remove\(k K\) bool](<#BuiltinSet[K].Remove>)
  - [func \(s BuiltinSet\[K\]\) RemoveN\(ks ...K\) int](<#BuiltinSet[K].RemoveN>)
  - [func \(s BuiltinSet\[K\]\) String\(\) string](<#BuiltinSet[K].String>)
  - [func \(s BuiltinSet\[K\]\) Union\(other BuiltinSet\[K\]\) BuiltinSet\[K\]](<#BuiltinSet[K].Union>)
  - [func \(s BuiltinSet\[K\]\) Update\(other BuiltinSet\[K\]\)](<#BuiltinSet[K].Update>)
- [type CompareFn](<#CompareFn>)
- [type Container](<#Container>)
- [type DList](<#DList>)
  - [func DListOf\[T any\]\(vs ...T\) DList\[T\]](<#DListOf>)
  - [func \(l \*DList\[T\]\) Back\(\) T](<#DList[T].Back>)
  - [func \(l \*DList\[T\]\) Clear\(\)](<#DList[T].Clear>)
  - [func \(l \*DList\[T\]\) ForEach\(cb func\(val T\)\)](<#DList[T].ForEach>)
  - [func \(l \*DList\[T\]\) ForEachIf\(cb func\(val T\) bool\)](<#DList[T].ForEachIf>)
  - [func \(l \*DList\[T\]\) ForEachMutable\(cb func\(val \*T\)\)](<#DList[T].ForEachMutable>)
  - [func \(l \*DList\[T\]\) ForEachMutableIf\(cb func\(val \*T\) bool\)](<#DList[T].ForEachMutableIf>)
  - [func \(l \*DList\[T\]\) Front\(\) T](<#DList[T].Front>)
  - [func \(l \*DList\[T\]\) IsEmpty\(\) bool](<#DList[T].IsEmpty>)
  - [func \(l \*DList\[T\]\) Iterate\(\) MutableIterator\[T\]](<#DList[T].Iterate>)
  - [func \(l \*DList\[T\]\) Len\(\) int](<#DList[T].Len>)
  - [func \(l \*DList\[T\]\) PopBack\(\) T](<#DList[T].PopBack>)
  - [func \(l \*DList\[T\]\) PopFront\(\) T](<#DList[T].PopFront>)
  - [func \(l \*DList\[T\]\) PushBack\(val T\)](<#DList[T].PushBack>)
  - [func \(l \*DList\[T\]\) PushFront\(val T\)](<#DList[T].PushFront>)
  - [func \(l \*DList\[T\]\) String\(\) string](<#DList[T].String>)
  - [func \(l \*DList\[T\]\) TryPopBack\(\) \(T, bool\)](<#DList[T].TryPopBack>)
  - [func \(l \*DList\[T\]\) TryPopFront\(\) \(T, bool\)](<#DList[T].TryPopFront>)
- [type DListQueue](<#DListQueue>)
  - [func NewDListQueue\[T any\]\(\) \*DListQueue\[T\]](<#NewDListQueue>)
  - [func \(q \*DListQueue\[T\]\) Back\(\) T](<#DListQueue[T].Back>)
  - [func \(q \*DListQueue\[T\]\) Clear\(\)](<#DListQueue[T].Clear>)
  - [func \(q \*DListQueue\[T\]\) Front\(\) T](<#DListQueue[T].Front>)
  - [func \(q \*DListQueue\[T\]\) IsEmpty\(\) bool](<#DListQueue[T].IsEmpty>)
  - [func \(q \*DListQueue\[T\]\) Len\(\) int](<#DListQueue[T].Len>)
  - [func \(q \*DListQueue\[T\]\) PopBack\(\) T](<#DListQueue[T].PopBack>)
  - [func \(q \*DListQueue\[T\]\) PopFront\(\) T](<#DListQueue[T].PopFront>)
  - [func \(q \*DListQueue\[T\]\) PushBack\(val T\)](<#DListQueue[T].PushBack>)
  - [func \(q \*DListQueue\[T\]\) PushFront\(val T\)](<#DListQueue[T].PushFront>)
  - [func \(q \*DListQueue\[T\]\) String\(\) string](<#DListQueue[T].String>)
  - [func \(q \*DListQueue\[T\]\) TryPopBack\(\) \(T, bool\)](<#DListQueue[T].TryPopBack>)
  - [func \(q \*DListQueue\[T\]\) TryPopFront\(\) \(T, bool\)](<#DListQueue[T].TryPopFront>)
- [type Deque](<#Deque>)
- [type Float](<#Float>)
- [type HashFn](<#HashFn>)
- [type Integer](<#Integer>)
- [type Iterator](<#Iterator>)
- [type LessFn](<#LessFn>)
- [type Map](<#Map>)
- [type MapIterator](<#MapIterator>)
- [type MutableIterator](<#MutableIterator>)
- [type MutableMapIterator](<#MutableMapIterator>)
- [type Numeric](<#Numeric>)
- [type Ordered](<#Ordered>)
- [type Pool](<#Pool>)
  - [func MakePool\[T any\]\(\) Pool\[T\]](<#MakePool>)
  - [func MakePoolWithNew\[T any\]\(new func\(\) \*T\) Pool\[T\]](<#MakePoolWithNew>)
  - [func \(pool \*Pool\[T\]\) Get\(\) \*T](<#Pool[T].Get>)
  - [func \(pool \*Pool\[T\]\) Put\(x \*T\)](<#Pool[T].Put>)
- [type PriorityQueue](<#PriorityQueue>)
  - [func NewPriorityQueue\[T Ordered\]\(\) \*PriorityQueue\[T\]](<#NewPriorityQueue>)
  - [func NewPriorityQueueFunc\[T any\]\(less LessFn\[T\]\) \*PriorityQueue\[T\]](<#NewPriorityQueueFunc>)
  - [func NewPriorityQueueOf\[T Ordered\]\(elements ...T\) \*PriorityQueue\[T\]](<#NewPriorityQueueOf>)
  - [func NewPriorityQueueOn\[T Ordered\]\(slice \[\]T\) \*PriorityQueue\[T\]](<#NewPriorityQueueOn>)
  - [func \(pq \*PriorityQueue\[T\]\) Clear\(\)](<#PriorityQueue[T].Clear>)
  - [func \(pq \*PriorityQueue\[T\]\) IsEmpty\(\) bool](<#PriorityQueue[T].IsEmpty>)
  - [func \(pq \*PriorityQueue\[T\]\) Len\(\) int](<#PriorityQueue[T].Len>)
  - [func \(pq \*PriorityQueue\[T\]\) Pop\(\) T](<#PriorityQueue[T].Pop>)
  - [func \(pq \*PriorityQueue\[T\]\) Push\(v T\)](<#PriorityQueue[T].Push>)
  - [func \(pq \*PriorityQueue\[T\]\) Top\(\) T](<#PriorityQueue[T].Top>)
- [type Queue](<#Queue>)
- [type SList](<#SList>)
  - [func SListOf\[T any\]\(values ...T\) SList\[T\]](<#SListOf>)
  - [func \(l \*SList\[T\]\) Back\(\) T](<#SList[T].Back>)
  - [func \(l \*SList\[T\]\) Clear\(\)](<#SList[T].Clear>)
  - [func \(l \*SList\[T\]\) ForEach\(cb func\(T\)\)](<#SList[T].ForEach>)
  - [func \(l \*SList\[T\]\) ForEachIf\(cb func\(T\) bool\)](<#SList[T].ForEachIf>)
  - [func \(l \*SList\[T\]\) ForEachMutable\(cb func\(\*T\)\)](<#SList[T].ForEachMutable>)
  - [func \(l \*SList\[T\]\) ForEachMutableIf\(cb func\(\*T\) bool\)](<#SList[T].ForEachMutableIf>)
  - [func \(l \*SList\[T\]\) Front\(\) T](<#SList[T].Front>)
  - [func \(l \*SList\[T\]\) IsEmpty\(\) bool](<#SList[T].IsEmpty>)
  - [func \(l \*SList\[T\]\) Iterate\(\) MutableIterator\[T\]](<#SList[T].Iterate>)
  - [func \(l \*SList\[T\]\) Len\(\) int](<#SList[T].Len>)
  - [func \(l \*SList\[T\]\) PopFront\(\) T](<#SList[T].PopFront>)
  - [func \(l \*SList\[T\]\) PushBack\(v T\)](<#SList[T].PushBack>)
  - [func \(l \*SList\[T\]\) PushFront\(v T\)](<#SList[T].PushFront>)
  - [func \(l \*SList\[T\]\) Reverse\(\)](<#SList[T].Reverse>)
  - [func \(l \*SList\[T\]\) Values\(\) \[\]T](<#SList[T].Values>)
- [type Set](<#Set>)
- [type Signed](<#Signed>)
- [type SkipList](<#SkipList>)
  - [func NewSkipList\[K Ordered, V any\]\(\) \*SkipList\[K, V\]](<#NewSkipList>)
  - [func NewSkipListFromMap\[K Ordered, V any\]\(m map\[K\]V\) \*SkipList\[K, V\]](<#NewSkipListFromMap>)
  - [func NewSkipListFunc\[K any, V any\]\(keyCmp CompareFn\[K\]\) \*SkipList\[K, V\]](<#NewSkipListFunc>)
  - [func \(sl \*SkipList\[K, V\]\) Clear\(\)](<#SkipList[K, V].Clear>)
  - [func \(sl \*SkipList\[K, V\]\) Find\(key K\) \*V](<#SkipList[K, V].Find>)
  - [func \(sl \*SkipList\[K, V\]\) FindRange\(first, last K\) MutableMapIterator\[K, V\]](<#SkipList[K, V].FindRange>)
  - [func \(sl \*SkipList\[K, V\]\) ForEach\(op func\(K, V\)\)](<#SkipList[K, V].ForEach>)
  - [func \(sl \*SkipList\[K, V\]\) ForEachIf\(op func\(K, V\) bool\)](<#SkipList[K, V].ForEachIf>)
  - [func \(sl \*SkipList\[K, V\]\) ForEachMutable\(op func\(K, \*V\)\)](<#SkipList[K, V].ForEachMutable>)
  - [func \(sl \*SkipList\[K, V\]\) ForEachMutableIf\(op func\(K, \*V\) bool\)](<#SkipList[K, V].ForEachMutableIf>)
  - [func \(sl \*SkipList\[K, V\]\) Has\(key K\) bool](<#SkipList[K, V].Has>)
  - [func \(sl \*SkipList\[K, V\]\) Insert\(key K, value V\)](<#SkipList[K, V].Insert>)
  - [func \(sl \*SkipList\[K, V\]\) IsEmpty\(\) bool](<#SkipList[K, V].IsEmpty>)
  - [func \(sl \*SkipList\[K, V\]\) Iterate\(\) MutableMapIterator\[K, V\]](<#SkipList[K, V].Iterate>)
  - [func \(sl \*SkipList\[K, V\]\) Len\(\) int](<#SkipList[K, V].Len>)
  - [func \(sl \*SkipList\[K, V\]\) LowerBound\(key K\) MutableMapIterator\[K, V\]](<#SkipList[K, V].LowerBound>)
  - [func \(sl \*SkipList\[K, V\]\) Remove\(key K\) bool](<#SkipList[K, V].Remove>)
  - [func \(sl \*SkipList\[K, V\]\) UpperBound\(key K\) MutableMapIterator\[K, V\]](<#SkipList[K, V].UpperBound>)
- [type SkipListSet](<#SkipListSet>)
  - [func NewSkipListSet\[K Ordered\]\(\) \*SkipListSet\[K\]](<#NewSkipListSet>)
  - [func NewSkipListSetFunc\[K any\]\(cmp CompareFn\[K\]\) \*SkipListSet\[K\]](<#NewSkipListSetFunc>)
  - [func NewSkipListSetOf\[K Ordered\]\(elements ...K\) \*SkipListSet\[K\]](<#NewSkipListSetOf>)
  - [func \(s \*SkipListSet\[K\]\) Clear\(\)](<#SkipListSet[K].Clear>)
  - [func \(s \*SkipListSet\[K\]\) FindRange\(first, last K\) Iterator\[K\]](<#SkipListSet[K].FindRange>)
  - [func \(s \*SkipListSet\[K\]\) ForEach\(f func\(K\)\)](<#SkipListSet[K].ForEach>)
  - [func \(s \*SkipListSet\[K\]\) ForEachIf\(f func\(K\) bool\)](<#SkipListSet[K].ForEachIf>)
  - [func \(s \*SkipListSet\[K\]\) Has\(key K\) bool](<#SkipListSet[K].Has>)
  - [func \(s \*SkipListSet\[K\]\) Insert\(key K\) bool](<#SkipListSet[K].Insert>)
  - [func \(s \*SkipListSet\[K\]\) InsertN\(keys ...K\) int](<#SkipListSet[K].InsertN>)
  - [func \(s \*SkipListSet\[K\]\) IsEmpty\(\) bool](<#SkipListSet[K].IsEmpty>)
  - [func \(s \*SkipListSet\[K\]\) Keys\(\) \[\]K](<#SkipListSet[K].Keys>)
  - [func \(s \*SkipListSet\[K\]\) Len\(\) int](<#SkipListSet[K].Len>)
  - [func \(s \*SkipListSet\[K\]\) LowerBound\(key K\) Iterator\[K\]](<#SkipListSet[K].LowerBound>)
  - [func \(s \*SkipListSet\[K\]\) Remove\(key K\) bool](<#SkipListSet[K].Remove>)
  - [func \(s \*SkipListSet\[K\]\) RemoveN\(keys ...K\) int](<#SkipListSet[K].RemoveN>)
  - [func \(s \*SkipListSet\[K\]\) UpperBound\(key K\) Iterator\[K\]](<#SkipListSet[K].UpperBound>)
- [type SortedMap](<#SortedMap>)
- [type SortedSet](<#SortedSet>)
- [type Stack](<#Stack>)
  - [func NewStack\[T any\]\(\) \*Stack\[T\]](<#NewStack>)
  - [func NewStackCap\[T any\]\(capicity int\) \*Stack\[T\]](<#NewStackCap>)
  - [func \(s Stack\[T\]\) Cap\(\) int](<#Stack[T].Cap>)
  - [func \(s \*Stack\[T\]\) Clear\(\)](<#Stack[T].Clear>)
  - [func \(s Stack\[T\]\) IsEmpty\(\) bool](<#Stack[T].IsEmpty>)
  - [func \(s Stack\[T\]\) Len\(\) int](<#Stack[T].Len>)
  - [func \(s \*Stack\[T\]\) Pop\(\) T](<#Stack[T].Pop>)
  - [func \(s \*Stack\[T\]\) Push\(t T\)](<#Stack[T].Push>)
  - [func \(s Stack\[T\]\) Top\(\) T](<#Stack[T].Top>)
  - [func \(s \*Stack\[T\]\) TryPop\(\) \(val T, ok bool\)](<#Stack[T].TryPop>)
- [type Unsigned](<#Unsigned>)
- [type Vector](<#Vector>)
  - [func AsVector\[T any\]\(s \[\]T\) Vector\[T\]](<#AsVector>)
  - [func MakeVector\[T any\]\(\) Vector\[T\]](<#MakeVector>)
  - [func MakeVectorCap\[T any\]\(c int\) Vector\[T\]](<#MakeVectorCap>)
  - [func VectorOf\[T any\]\(v ...T\) Vector\[T\]](<#VectorOf>)
  - [func \(v \*Vector\[T\]\) Append\(x ...T\)](<#Vector[T].Append>)
  - [func \(v \*Vector\[T\]\) At\(i int\) T](<#Vector[T].At>)
  - [func \(v Vector\[T\]\) Back\(\) T](<#Vector[T].Back>)
  - [func \(v \*Vector\[T\]\) Cap\(\) int](<#Vector[T].Cap>)
  - [func \(v \*Vector\[T\]\) Clear\(\)](<#Vector[T].Clear>)
  - [func \(v Vector\[T\]\) ForEach\(cb func\(val T\)\)](<#Vector[T].ForEach>)
  - [func \(v Vector\[T\]\) ForEachIf\(cb func\(val T\) bool\)](<#Vector[T].ForEachIf>)
  - [func \(v Vector\[T\]\) ForEachMutable\(cb func\(val \*T\)\)](<#Vector[T].ForEachMutable>)
  - [func \(v Vector\[T\]\) ForEachMutableIf\(cb func\(val \*T\) bool\)](<#Vector[T].ForEachMutableIf>)
  - [func \(v \*Vector\[T\]\) Insert\(i int, x ...T\)](<#Vector[T].Insert>)
  - [func \(v \*Vector\[T\]\) IsEmpty\(\) bool](<#Vector[T].IsEmpty>)
  - [func \(v Vector\[T\]\) Iterate\(\) MutableIterator\[T\]](<#Vector[T].Iterate>)
  - [func \(v Vector\[T\]\) IterateRange\(i, j int\) MutableIterator\[T\]](<#Vector[T].IterateRange>)
  - [func \(v \*Vector\[T\]\) Len\(\) int](<#Vector[T].Len>)
  - [func \(v \*Vector\[T\]\) PopBack\(\) T](<#Vector[T].PopBack>)
  - [func \(v \*Vector\[T\]\) PushBack\(x T\)](<#Vector[T].PushBack>)
  - [func \(v \*Vector\[T\]\) Remove\(i int\)](<#Vector[T].Remove>)
  - [func \(v \*Vector\[T\]\) RemoveIf\(cond func\(T\) bool\)](<#Vector[T].RemoveIf>)
  - [func \(v \*Vector\[T\]\) RemoveLength\(i int, len int\)](<#Vector[T].RemoveLength>)
  - [func \(v \*Vector\[T\]\) RemoveRange\(i, j int\)](<#Vector[T].RemoveRange>)
  - [func \(v \*Vector\[T\]\) Reserve\(l int\)](<#Vector[T].Reserve>)
  - [func \(v \*Vector\[T\]\) Set\(i int, x T\)](<#Vector[T].Set>)
  - [func \(v \*Vector\[T\]\) Shrink\(\)](<#Vector[T].Shrink>)
  - [func \(v \*Vector\[T\]\) TryPopBack\(\) \(T, bool\)](<#Vector[T].TryPopBack>)


<a name="AllOf"></a>
## func [AllOf](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L130>)

```go
func AllOf[T any](a []T, pred func(T) bool) bool
```

AllOf return true if pred\(e\) returns true for all elements e in a.

Complexity: O\(len\(a\)\).

<a name="AnyOf"></a>
## func [AnyOf](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L142>)

```go
func AnyOf[T any](a []T, pred func(T) bool) bool
```

AnyOf return true if pred\(e\) returns true for any elements e in a.

Complexity: O\(len\(a\)\).

<a name="Average"></a>
## func [Average](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L42>)

```go
func Average[T Numeric](a []T) T
```

Average returns the average value of a.

<a name="AverageAs"></a>
## func [AverageAs](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L37>)

```go
func AverageAs[R, T Numeric](a []T) R
```

AverageAs returns the average value of a as type R.

<a name="BinarySearch"></a>
## func [BinarySearch](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L100>)

```go
func BinarySearch[T Ordered](a []T, value T) (index int, ok bool)
```

BinarySearch returns the \(index, true\) to the first element in the ascending ordered slice a such that element == value, or \(\-1, false\) if no such element is found.

Complexity: O\(log\(len\(a\)\)\).

<a name="BinarySearchFunc"></a>
## func [BinarySearchFunc](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L115>)

```go
func BinarySearchFunc[T any](a []T, value T, less LessFn[T]) (index int, ok bool)
```

BinarySearchFunc returns the \(index, true\) to the first element in the ordered slice a such that less\(element, value\) and less\(value, element\) are both false, or \(\-1, false\) if no such element is found.

The elements in the slice a should sorted according with compare func less.

Complexity: O\(log\(len\(a\)\)\).

<a name="Compare"></a>
## func [Compare](<https://github.com/chen3feng/stl4go/blob/master/compare.go#L26>)

```go
func Compare[E Ordered](a, b []E) int
```

Compare compares each elements in a and b.

return 0 if they are equals, return 1 if a \> b, return \-1 if a \< b.

Complexity: O\(min\(len\(a\), len\(b\)\)\).

<a name="Copy"></a>
## func [Copy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L8>)

```go
func Copy[T any](a []T) []T
```

Copy make a copy of slice a.

Complexity: O\(len\(a\)\).

<a name="CopyTo"></a>
## func [CopyTo](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L16>)

```go
func CopyTo[T any](a []T, to []T) []T
```

CopyTo copies all elements in slice a to slice to, return the copied slice. if slice to is large enough, no memory allocation occurs.

Complexity: O\(len\(a\)\).

<a name="Count"></a>
## func [Count](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L59>)

```go
func Count[T comparable](a []T, x T) int
```

Count returns the number of elements in the slice equals to x.

Complexity: O\(len\(a\)\).

<a name="CountIf"></a>
## func [CountIf](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L72>)

```go
func CountIf[T comparable](a []T, pred func(T) bool) int
```

CountIf returns the number of elements in the slice which pred returns true.

Complexity: O\(len\(a\)\).

<a name="DescSort"></a>
## func [DescSort](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L73>)

```go
func DescSort[T Ordered](a []T)
```

DescSort sorts data in descending order. The order of equal elements is not guaranteed to be preserved.

Complexity: O\(N\*log\(N\)\), N=len\(a\).

<a name="DescStableSort"></a>
## func [DescStableSort](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L81>)

```go
func DescStableSort[T Ordered](a []T)
```

DescStableSort sorts data in descending order stably. The order of equivalent elements is guaranteed to be preserved.

Complexity: O\(N\*log\(N\)\), N=len\(a\).

<a name="Equal"></a>
## func [Equal](<https://github.com/chen3feng/stl4go/blob/master/compare.go#L7>)

```go
func Equal[T comparable](a, b []T) bool
```

Equal returns whether two slices are equal. Return true if they are the same length and all elements are equal.

Complexity: O\(min\(len\(a\), len\(b\)\)\).

<a name="Fill"></a>
## func [Fill](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L24>)

```go
func Fill[T any](a []T, v T)
```

Fill fills each element in slice a with new value v.

Complexity: O\(len\(a\)\).

<a name="FillPattern"></a>
## func [FillPattern](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L42>)

```go
func FillPattern[T any](a []T, pattern []T)
```

FillPattern fills elements in slice a with specified pattern.

Complexity: O\(len\(a\)\).

<a name="FillZero"></a>
## func [FillZero](<https://github.com/chen3feng/stl4go/blob/master/transform_fillzero_clear.go#L9>)

```go
func FillZero[T any](a []T)
```

FillZero fills each element in slice a with zero value.

Complexity: O\(len\(a\)\).

<a name="Find"></a>
## func [Find](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L90>)

```go
func Find[T comparable](a []T, x T) (index int, ok bool)
```

Find find the first value x in the given slice a linearly. return \(index, true\) if found, return \(\_, false\) if not found.

Complexity: O\(len\(a\)\).

<a name="FindIf"></a>
## func [FindIf](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L104>)

```go
func FindIf[T any](a []T, cond func(T) bool) (index int, ok bool)
```

FindIf find the first value x satisfying function cond in the given slice a linearly. return \(index, true\) if found, return \(\_, false\) if not found.

Complexity: O\(len\(a\)\).

<a name="Generate"></a>
## func [Generate](<https://github.com/chen3feng/stl4go/blob/master/generate.go#L18>)

```go
func Generate[T any](a []T, gen func() T)
```

Generate fill each element of \`a“ with \`gen\(\)\`.

Complexity: O\(len\(a\)\).

<a name="Greater"></a>
## func [Greater](<https://github.com/chen3feng/stl4go/blob/master/functor.go#L9>)

```go
func Greater[T Ordered](a, b T) bool
```

Greater wraps the '\>' operator for ordered types.

<a name="Index"></a>
## func [Index](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L118>)

```go
func Index[T comparable](a []T, x T) int
```

Index find the value x in the given slice a linearly.

Return index if found, \-1 if not found.

Complexity: O\(len\(a\)\).

<a name="IsDescSorted"></a>
## func [IsDescSorted](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L27>)

```go
func IsDescSorted[T Ordered](a []T) bool
```

IsDescSorted returns whether the slice a is sorted in descending order.

Complexity: O\(len\(a\)\).

<a name="IsHeapFunc"></a>
## func [IsHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L118>)

```go
func IsHeapFunc[T any](array []T, less LessFn[T]) bool
```

IsHeapFunc checks whether the elements in slice array are a min heap \(accord to less\).

Complexity: O\(len\(array\)\).

<a name="IsMinHeap"></a>
## func [IsMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L19>)

```go
func IsMinHeap[T Ordered](array []T) bool
```

IsMinHeap checks whether the elements in slice array are a min heap.

Complexity: O\(len\(array\)\).

<a name="IsSorted"></a>
## func [IsSorted](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L10>)

```go
func IsSorted[T Ordered](a []T) bool
```

IsSorted returns whether the slice a is sorted in ascending order.

Complexity: O\(len\(a\)\).

<a name="Less"></a>
## func [Less](<https://github.com/chen3feng/stl4go/blob/master/functor.go#L4>)

```go
func Less[T Ordered](a, b T) bool
```

Less wraps the '\<' operator for ordered types.

<a name="LowerBound"></a>
## func [LowerBound](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L8>)

```go
func LowerBound[T Ordered](a []T, value T) int
```

LowerBound returns an index to the first element in the ascending ordered slice a that does not satisfy element \< value \(i.e. greater or equal to\), or len\(a\) if no such element is found.

Complexity: O\(log\(len\(a\)\)\).

<a name="LowerBoundFunc"></a>
## func [LowerBoundFunc](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L32>)

```go
func LowerBoundFunc[T any](a []T, value T, less LessFn[T]) int
```

LowerBoundFunc returns an index to the first element in the ordered slice a that does not satisfy less\(element, value\)\), or len\(a\) if no such element is found.

The elements in the slice a should sorted according with compare func less.

Complexity: O\(log\(len\(a\)\)\).

<a name="MakeHeapFunc"></a>
## func [MakeHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L107>)

```go
func MakeHeapFunc[T any](array []T, less LessFn[T])
```

MakeHeapFunc build a min\-heap on slice array with compare function less.

Complexity: O\(len\(array\)\)

<a name="MakeMinHeap"></a>
## func [MakeMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L8>)

```go
func MakeMinHeap[T Ordered](array []T)
```

MakeMinHeap build a min\-heap on slice array.

Complexity: O\(len\(array\)\)

<a name="Max"></a>
## func [Max](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L6>)

```go
func Max[T Ordered](a, b T) T
```

Max return the larger value between \`a\` and \`b\`.

Complexity: O\(1\).

<a name="MaxN"></a>
## func [MaxN](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L26>)

```go
func MaxN[T Ordered](a ...T) T
```

MaxN return the maximum value in the sequence \`a\`.

Complexity: O\(len\(a\)\).

<a name="Min"></a>
## func [Min](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L16>)

```go
func Min[T Ordered](a, b T) T
```

Min return the smaller value between \`a\` and \`b\`.

Complexity: O\(1\).

<a name="MinMax"></a>
## func [MinMax](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L58>)

```go
func MinMax[T Ordered](a, b T) (min, max T)
```

MinMax returns both min and max between a and b.

Complexity: O\(1\).

<a name="MinMaxN"></a>
## func [MinMaxN](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L68>)

```go
func MinMaxN[T Ordered](a ...T) (min, max T)
```

MinMaxN returns both min and max in slice a.

Complexity: O\(len\(a\)\)

<a name="MinN"></a>
## func [MinN](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L42>)

```go
func MinN[T Ordered](a ...T) T
```

MinN return the minimum value in the sequence \`a\`.

Complexity: O\(len\(a\)\).

<a name="NoneOf"></a>
## func [NoneOf](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L154>)

```go
func NoneOf[T any](a []T, pred func(T) bool) bool
```

NoneOf return true pred\(e\) returns true for none elements e in a.

Complexity: O\(len\(a\)\).

<a name="OrderedCompare"></a>
## func [OrderedCompare](<https://github.com/chen3feng/stl4go/blob/master/functor.go#L14>)

```go
func OrderedCompare[T Ordered](a, b T) int
```

OrderedCompare provide default CompareFn for ordered types.

<a name="PopHeapFunc"></a>
## func [PopHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L144>)

```go
func PopHeapFunc[T any](heap *[]T, less LessFn[T]) T
```

PopHeapFunc removes and returns the minimum \(according to less\) element from the heap.

Complexity: O\(log n\) where n = len\(\*heap\).

<a name="PopMinHeap"></a>
## func [PopMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L44>)

```go
func PopMinHeap[T Ordered](heap *[]T) T
```

PopMinHeap removes and returns the minimum element from the heap.

Complexity: O\(log n\) where n = len\(\*heap\).

<a name="PushHeapFunc"></a>
## func [PushHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L136>)

```go
func PushHeapFunc[T any](heap *[]T, v T, less LessFn[T])
```

PushHeapFunc pushes a element v into the heap.

Complexity: O\(log\(len\(\*heap\)\)\).

<a name="PushMinHeap"></a>
## func [PushMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L36>)

```go
func PushMinHeap[T Ordered](heap *[]T, v T)
```

PushMinHeap pushes a element v into the min heap.

Complexity: O\(log\(len\(\*heap\)\)\).

<a name="Range"></a>
## func [Range](<https://github.com/chen3feng/stl4go/blob/master/generate.go#L7>)

```go
func Range[T Numeric](first, last T) []T
```

Range make a \[\]T filled with values in the \`\[first, last\)\` sequence. NOTE: the last is not included in the result.

Complexity: O\(last\-first\).

<a name="Remove"></a>
## func [Remove](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L154>)

```go
func Remove[T comparable](a []T, x T) []T
```

Remove remove the elements which equals to x from the input slice. return the processed slice with new length.

Complexity: O\(len\(a\)\).

<a name="RemoveCopy"></a>
## func [RemoveCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L169>)

```go
func RemoveCopy[T comparable](a []T, x T) []T
```

RemoveCopy remove all elements which equals to x from the input slice. return a new slice with processed results. The input slice is kept unchanged.

Complexity: O\(len\(a\)\).

<a name="RemoveHeapFunc"></a>
## func [RemoveHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L156>)

```go
func RemoveHeapFunc[T any](heap *[]T, i int, less LessFn[T]) T
```

RemoveHeapFunc removes and returns the element at index i from the heap.

Complexity: is O\(log\(n\)\) where n = len\(\*heap\).

<a name="RemoveIf"></a>
## func [RemoveIf](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L183>)

```go
func RemoveIf[T any](a []T, cond func(T) bool) []T
```

RemoveIf remove each element which make cond\(x\) returns true from the input slice, copy other elements to a new slice and return it.

Complexity: O\(len\(a\)\).

<a name="RemoveIfCopy"></a>
## func [RemoveIfCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L198>)

```go
func RemoveIfCopy[T any](a []T, cond func(T) bool) []T
```

RemoveIfCopy drops each element which make cond\(x\) returns true from the input slice, copy other elements to a new slice and return it. The input slice is kept unchanged.

Complexity: O\(len\(a\)\).

<a name="RemoveMinHeap"></a>
## func [RemoveMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L56>)

```go
func RemoveMinHeap[T Ordered](heap *[]T, i int) T
```

RemoveMinHeap removes and returns the element at index i from the min heap.

Complexity: is O\(log\(n\)\) where n = len\(\*heap\).

<a name="Replace"></a>
## func [Replace](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L91>)

```go
func Replace[T comparable](a []T, old, new T)
```

Replace replaces every element that equals to old with new.

Complexity: O\(len\(a\)\).

<a name="ReplaceIf"></a>
## func [ReplaceIf](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L102>)

```go
func ReplaceIf[T any](a []T, pred func(v T) bool, new T)
```

ReplaceIf replaces every element that make preq returns true with new.

Complexity: O\(len\(a\)\).

<a name="Reverse"></a>
## func [Reverse](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L220>)

```go
func Reverse[T any](a []T)
```

Reverse reverses the order of the elements in the slice a.

Complexity: O\(len\(a\)\).

<a name="ReverseCopy"></a>
## func [ReverseCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L229>)

```go
func ReverseCopy[T any](a []T) []T
```

ReverseCopy returns a reversed copy of slice a.

Complexity: O\(len\(a\)\).

<a name="Shuffle"></a>
## func [Shuffle](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L211>)

```go
func Shuffle[T any](a []T)
```

Shuffle pseudo\-randomizes the order of elements.

Complexity: O\(len\(a\)\).

<a name="Sort"></a>
## func [Sort](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L51>)

```go
func Sort[T Ordered](a []T)
```

Sort sorts data in ascending order. The order of equal elements is not guaranteed to be preserved.

Complexity: O\(N\*log\(N\)\), where N=len\(a\).

<a name="SortFunc"></a>
## func [SortFunc](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L98>)

```go
func SortFunc[T any](a []T, less func(x, y T) bool)
```

SortFunc sorts data in ascending order with compare func less. The order of equal elements is not guaranteed to be preserved.

Complexity: O\(N\*log\(N\)\), N=len\(a\).

<a name="StableSort"></a>
## func [StableSort](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L59>)

```go
func StableSort[T Ordered](a []T)
```

StableSort sorts data in ascending order stably. The order of equivalent elements is guaranteed to be preserved.

Complexity: O\(N\*log\(N\)^2\), where N=len\(a\).

<a name="StableSortFunc"></a>
## func [StableSortFunc](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L106>)

```go
func StableSortFunc[T any](a []T, less func(x, y T) bool)
```

StableSortFunc sorts data in ascending order with compare func less stably. The order of equivalent elements is guaranteed to be preserved.

Complexity: O\(N\*log\(N\)\), N=len\(a\).

<a name="Sum"></a>
## func [Sum](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L32>)

```go
func Sum[T Numeric](a []T) T
```

Sum summarize all elements in a. returns the result as type R, you should use SumAs if T can't hold the result. Complexity: O\(len\(a\)\).

<a name="SumAs"></a>
## func [SumAs](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L6>)

```go
func SumAs[R, T Numeric](a []T) R
```

SumAs summarize all elements in a. returns the result as type R, this is useful when T is too small to hold the result. Complexity: O\(len\(a\)\).

<a name="Transform"></a>
## func [Transform](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L71>)

```go
func Transform[T any](a []T, op func(T) T)
```

Transform applies the function op to each element in slice a and set it back to the same place in a.

Complexity: O\(len\(a\)\).

<a name="TransformCopy"></a>
## func [TransformCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L80>)

```go
func TransformCopy[R any, T any](a []T, op func(T) R) []R
```

TransformCopy applies the function op to each element in slice a and return all the result as a slice.

Complexity: O\(len\(a\)\).

<a name="TransformTo"></a>
## func [TransformTo](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L60>)

```go
func TransformTo[R any, T any](a []T, op func(T) R, b []R) []R
```

TransformTo applies the function op to each element in slice a and fill it to slice b, return the transformed slice. If cap\(b\) \>= len\(a\), no memory allocation.

Complexity: O\(len\(a\)\).

<a name="Unique"></a>
## func [Unique](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L114>)

```go
func Unique[T comparable](a []T) []T
```

Unique remove adjacent repeated elements from the input slice. return the processed slice with new length.

Complexity: O\(len\(a\)\).

<a name="UniqueCopy"></a>
## func [UniqueCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L134>)

```go
func UniqueCopy[T comparable](a []T) []T
```

UniqueCopy remove adjacent repeated elements from the input slice. return the result slice, and the input slice is kept unchanged.

Complexity: O\(len\(a\)\).

<a name="UpperBound"></a>
## func [UpperBound](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L54>)

```go
func UpperBound[T Ordered](a []T, value T) int
```

UpperBound returns an index to the first element in the ascending ordered slice a such that value \< element \(i.e. strictly greater\), or len\(a\) if no such element is found.

Complexity: O\(log\(len\(a\)\)\).

<a name="UpperBoundFunc"></a>
## func [UpperBoundFunc](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L78>)

```go
func UpperBoundFunc[T any](a []T, value T, less LessFn[T]) int
```

UpperBoundFunc returns an index to the first element in the ordered slice a such that less\(value, element\)\) is true \(i.e. strictly greater\), or len\(a\) if no such element is found.

The elements in the slice a should sorted according with compare func less.

Complexity: O\(log\(len\(a\)\)\).

<a name="BuiltinSet"></a>
## type [BuiltinSet](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L8>)

BuiltinSet is an associative container that contains an unordered set of unique objects of type K.

```go
type BuiltinSet[K comparable] map[K]struct{}
```

<a name="SetOf"></a>
### func [SetOf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L11>)

```go
func SetOf[K comparable](ks ...K) BuiltinSet[K]
```

SetOf creates a new BuiltinSet object with the initial content from ks.

<a name="BuiltinSet[K].Clear"></a>
### func \(BuiltinSet\[K\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L28>)

```go
func (s BuiltinSet[K]) Clear()
```

Clear implements the Container interface.

<a name="BuiltinSet[K].Delete"></a>
### func \(BuiltinSet\[K\]\) [Delete](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L65>)

```go
func (s BuiltinSet[K]) Delete(k K)
```

Delete deletes an element from the set. It returns nothing, so it's faster than Remove.

<a name="BuiltinSet[K].Difference"></a>
### func \(BuiltinSet\[K\]\) [Difference](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L143>)

```go
func (s BuiltinSet[K]) Difference(other BuiltinSet[K]) BuiltinSet[K]
```

Difference returns a new set with elements in the set that are not in other.

<a name="BuiltinSet[K].ForEach"></a>
### func \(BuiltinSet\[K\]\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L88>)

```go
func (s BuiltinSet[K]) ForEach(cb func(k K))
```

ForEach implements the Set interface.

<a name="BuiltinSet[K].ForEachIf"></a>
### func \(BuiltinSet\[K\]\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L95>)

```go
func (s BuiltinSet[K]) ForEachIf(cb func(k K) bool)
```

ForEachIf implements the Container interface.

<a name="BuiltinSet[K].Has"></a>
### func \(BuiltinSet\[K\]\) [Has](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L35>)

```go
func (s BuiltinSet[K]) Has(k K) bool
```

Has implements the Set interface.

<a name="BuiltinSet[K].Insert"></a>
### func \(BuiltinSet\[K\]\) [Insert](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L41>)

```go
func (s BuiltinSet[K]) Insert(k K) bool
```

Insert implements the Set interface.

<a name="BuiltinSet[K].InsertN"></a>
### func \(BuiltinSet\[K\]\) [InsertN](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L48>)

```go
func (s BuiltinSet[K]) InsertN(ks ...K) int
```

InsertN implements the Set interface.

<a name="BuiltinSet[K].Intersection"></a>
### func \(BuiltinSet\[K\]\) [Intersection](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L131>)

```go
func (s BuiltinSet[K]) Intersection(other BuiltinSet[K]) BuiltinSet[K]
```

Intersection returns a new set with elements common to the set and other.

<a name="BuiltinSet[K].IsDisjointOf"></a>
### func \(BuiltinSet\[K\]\) [IsDisjointOf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L155>)

```go
func (s BuiltinSet[K]) IsDisjointOf(other BuiltinSet[K]) bool
```

IsDisjointOf return True if the set has no elements in common with other. Sets are disjoint if and only if their intersection is the empty set.

<a name="BuiltinSet[K].IsEmpty"></a>
### func \(BuiltinSet\[K\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L18>)

```go
func (s BuiltinSet[K]) IsEmpty() bool
```

IsEmpty implements the Container interface.

<a name="BuiltinSet[K].IsSubsetOf"></a>
### func \(BuiltinSet\[K\]\) [IsSubsetOf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L166>)

```go
func (s BuiltinSet[K]) IsSubsetOf(other BuiltinSet[K]) bool
```

IsSubsetOf tests whether every element in the set is in other.

<a name="BuiltinSet[K].IsSupersetOf"></a>
### func \(BuiltinSet\[K\]\) [IsSupersetOf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L179>)

```go
func (s BuiltinSet[K]) IsSupersetOf(other BuiltinSet[K]) bool
```

IsSupersetOf tests whether every element in other is in the set.

<a name="BuiltinSet[K].Keys"></a>
### func \(BuiltinSet\[K\]\) [Keys](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L79>)

```go
func (s BuiltinSet[K]) Keys() []K
```

Keys return a copy of all keys as a slice.

<a name="BuiltinSet[K].Len"></a>
### func \(BuiltinSet\[K\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L23>)

```go
func (s BuiltinSet[K]) Len() int
```

Len implements the Container interface.

<a name="BuiltinSet[K].Remove"></a>
### func \(BuiltinSet\[K\]\) [Remove](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L57>)

```go
func (s BuiltinSet[K]) Remove(k K) bool
```

Remove implements the Set interface.

<a name="BuiltinSet[K].RemoveN"></a>
### func \(BuiltinSet\[K\]\) [RemoveN](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L70>)

```go
func (s BuiltinSet[K]) RemoveN(ks ...K) int
```

RemoveN implements the Set interface.

<a name="BuiltinSet[K].String"></a>
### func \(BuiltinSet\[K\]\) [String](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L104>)

```go
func (s BuiltinSet[K]) String() string
```

String implements the fmt.Stringer interface.

<a name="BuiltinSet[K].Union"></a>
### func \(BuiltinSet\[K\]\) [Union](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L116>)

```go
func (s BuiltinSet[K]) Union(other BuiltinSet[K]) BuiltinSet[K]
```

Union returns a new set with elements from the set and other.

<a name="BuiltinSet[K].Update"></a>
### func \(BuiltinSet\[K\]\) [Update](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L109>)

```go
func (s BuiltinSet[K]) Update(other BuiltinSet[K])
```

Update adds all elements from other to set. set |= other.

<a name="CompareFn"></a>
## type [CompareFn](<https://github.com/chen3feng/stl4go/blob/master/types.go#L51>)

CompareFn is a 3 way compare function that returns 1 if a \> b, returns 0 if a == b, returns \-1 if a \< b.

```go
type CompareFn[T any] func(a, b T) int
```

<a name="Container"></a>
## type [Container](<https://github.com/chen3feng/stl4go/blob/master/container.go#L4-L8>)

Container is a holder object that stores a collection of other objects.

```go
type Container interface {
    IsEmpty() bool // IsEmpty checks if the container has no elements.
    Len() int      // Len returns the number of elements in the container.
    Clear()        // Clear erases all elements from the container. After this call, Len() returns zero.
}
```

<a name="DList"></a>
## type [DList](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L6-L9>)

DList is a doubly linked list.

```go
type DList[T any] struct {
    // contains filtered or unexported fields
}
```

<a name="DListOf"></a>
### func [DListOf](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L17>)

```go
func DListOf[T any](vs ...T) DList[T]
```

DListOf make a new DList from a serial of values.

<a name="DList[T].Back"></a>
### func \(\*DList\[T\]\) [Back](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L88>)

```go
func (l *DList[T]) Back() T
```

Back returns the last element in the container.

<a name="DList[T].Clear"></a>
### func \(\*DList\[T\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L26>)

```go
func (l *DList[T]) Clear()
```

Clear cleanup the list.

<a name="DList[T].ForEach"></a>
### func \(\*DList\[T\]\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L164>)

```go
func (l *DList[T]) ForEach(cb func(val T))
```

ForEach iterate the list, apply each element to the cb callback function.

<a name="DList[T].ForEachIf"></a>
### func \(\*DList\[T\]\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L175>)

```go
func (l *DList[T]) ForEachIf(cb func(val T) bool)
```

ForEachIf iterate the list, apply each element to the cb callback function, stop if cb returns false.

<a name="DList[T].ForEachMutable"></a>
### func \(\*DList\[T\]\) [ForEachMutable](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L187>)

```go
func (l *DList[T]) ForEachMutable(cb func(val *T))
```

ForEachMutable iterate the list, apply pointer of each element to the cb callback function.

<a name="DList[T].ForEachMutableIf"></a>
### func \(\*DList\[T\]\) [ForEachMutableIf](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L198>)

```go
func (l *DList[T]) ForEachMutableIf(cb func(val *T) bool)
```

ForEachMutableIf iterate the list, apply pointer of each element to the cb callback function, stop if cb returns false.

<a name="DList[T].Front"></a>
### func \(\*DList\[T\]\) [Front](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L80>)

```go
func (l *DList[T]) Front() T
```

Front returns the first element in the container.

<a name="DList[T].IsEmpty"></a>
### func \(\*DList\[T\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L40>)

```go
func (l *DList[T]) IsEmpty() bool
```

IsEmpty return whether the list is empty.

<a name="DList[T].Iterate"></a>
### func \(\*DList\[T\]\) [Iterate](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L71>)

```go
func (l *DList[T]) Iterate() MutableIterator[T]
```

Iterate returns an iterator to the first element in the list.

<a name="DList[T].Len"></a>
### func \(\*DList\[T\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L35>)

```go
func (l *DList[T]) Len() int
```

Len return the length of the list.

<a name="DList[T].PopBack"></a>
### func \(\*DList\[T\]\) [PopBack](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L123>)

```go
func (l *DList[T]) PopBack() T
```

PopBack popups an element from the back of the list.

<a name="DList[T].PopFront"></a>
### func \(\*DList\[T\]\) [PopFront](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L114>)

```go
func (l *DList[T]) PopFront() T
```

PopFront popups an element from the front of the list.

<a name="DList[T].PushBack"></a>
### func \(\*DList\[T\]\) [PushBack](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L105>)

```go
func (l *DList[T]) PushBack(val T)
```

PushBack pushes an element at the back of the list.

<a name="DList[T].PushFront"></a>
### func \(\*DList\[T\]\) [PushFront](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L96>)

```go
func (l *DList[T]) PushFront(val T)
```

PushFront pushes an element at the front of the list.

<a name="DList[T].String"></a>
### func \(\*DList\[T\]\) [String](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L45>)

```go
func (l *DList[T]) String() string
```

String convert the list to string.

<a name="DList[T].TryPopBack"></a>
### func \(\*DList\[T\]\) [TryPopBack](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L148>)

```go
func (l *DList[T]) TryPopBack() (T, bool)
```

TryPopBack tries to pop up an element from the back of the list.

<a name="DList[T].TryPopFront"></a>
### func \(\*DList\[T\]\) [TryPopFront](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L132>)

```go
func (l *DList[T]) TryPopFront() (T, bool)
```

TryPopFront tries to pop up an element from the front of the list.

<a name="DListQueue"></a>
## type [DListQueue](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L8-L10>)

DListQueue is a FIFO container

```go
type DListQueue[T any] struct {
    // contains filtered or unexported fields
}
```

<a name="NewDListQueue"></a>
### func [NewDListQueue](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L13>)

```go
func NewDListQueue[T any]() *DListQueue[T]
```

NewDListQueue create a new Queue object.

<a name="DListQueue[T].Back"></a>
### func \(\*DListQueue\[T\]\) [Back](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L44>)

```go
func (q *DListQueue[T]) Back() T
```

Back returns the last element in the container.

<a name="DListQueue[T].Clear"></a>
### func \(\*DListQueue\[T\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L29>)

```go
func (q *DListQueue[T]) Clear()
```

Clear implements the Container interface.

<a name="DListQueue[T].Front"></a>
### func \(\*DListQueue\[T\]\) [Front](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L39>)

```go
func (q *DListQueue[T]) Front() T
```

Front returns the first element in the container.

<a name="DListQueue[T].IsEmpty"></a>
### func \(\*DListQueue\[T\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L24>)

```go
func (q *DListQueue[T]) IsEmpty() bool
```

IsEmpty implements the Container interface.

<a name="DListQueue[T].Len"></a>
### func \(\*DListQueue\[T\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L19>)

```go
func (q *DListQueue[T]) Len() int
```

Len implements the Container interface.

<a name="DListQueue[T].PopBack"></a>
### func \(\*DListQueue\[T\]\) [PopBack](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L64>)

```go
func (q *DListQueue[T]) PopBack() T
```

PopBack popups an element from the back of the queue.

<a name="DListQueue[T].PopFront"></a>
### func \(\*DListQueue\[T\]\) [PopFront](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L59>)

```go
func (q *DListQueue[T]) PopFront() T
```

PopFront popups an element from the front of the queue.

<a name="DListQueue[T].PushBack"></a>
### func \(\*DListQueue\[T\]\) [PushBack](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L54>)

```go
func (q *DListQueue[T]) PushBack(val T)
```

PushBack pushed an element to the back of the queue.

<a name="DListQueue[T].PushFront"></a>
### func \(\*DListQueue\[T\]\) [PushFront](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L49>)

```go
func (q *DListQueue[T]) PushFront(val T)
```

PushFront pushed an element to the front of the queue.

<a name="DListQueue[T].String"></a>
### func \(\*DListQueue\[T\]\) [String](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L34>)

```go
func (q *DListQueue[T]) String() string
```

Len implements the fmt.Stringer interface.

<a name="DListQueue[T].TryPopBack"></a>
### func \(\*DListQueue\[T\]\) [TryPopBack](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L74>)

```go
func (q *DListQueue[T]) TryPopBack() (T, bool)
```

TryPopBack tries popuping an element from the back of the queue.

<a name="DListQueue[T].TryPopFront"></a>
### func \(\*DListQueue\[T\]\) [TryPopFront](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L69>)

```go
func (q *DListQueue[T]) TryPopFront() (T, bool)
```

TryPopFront tries popuping an element from the front of the queue.

<a name="Deque"></a>
## type [Deque](<https://github.com/chen3feng/stl4go/blob/master/container.go#L81-L91>)

Deque is a container that can add and remove elements from both ends.

```go
type Deque[T any] interface {
    Container
    Front() T               // Front returns the first element in the container.
    Back() T                // Back returns the last element in the container.
    PushFront(T)            // PushBack pushes an element at the front of the container.
    PushBack(T)             // PushBack pushes an element at the back of the container.
    PopFront() T            // PopBack popups a front from the back of the container.
    PopBack() T             // PopBack popups a element from the back of the container.
    TryPopFront() (T, bool) // TryPopFront tries to popup a element from the front of the container.
    TryPopBack() (T, bool)  // TryPopBack tries to popup a element from the back of the container.
}
```

<a name="Float"></a>
## type [Float](<https://github.com/chen3feng/stl4go/blob/master/types.go#L27-L29>)

Float is a constraint that permits any floating\-point type. If future releases of Go add new predeclared floating\-point types, this constraint will be modified to include them.

```go
type Float interface {
    // contains filtered or unexported methods
}
```

<a name="HashFn"></a>
## type [HashFn](<https://github.com/chen3feng/stl4go/blob/master/types.go#L54>)

HashFn is a function that returns the hash of 't'.

```go
type HashFn[T any] func(t T) uint64
```

<a name="Integer"></a>
## type [Integer](<https://github.com/chen3feng/stl4go/blob/master/types.go#L20-L22>)

Integer is a constraint that permits any integer type. If future releases of Go add new predeclared integer types, this constraint will be modified to include them.

```go
type Integer interface {
    // contains filtered or unexported methods
}
```

<a name="Iterator"></a>
## type [Iterator](<https://github.com/chen3feng/stl4go/blob/master/iterator.go#L4-L8>)

Iterator is the interface for container's iterator.

```go
type Iterator[T any] interface {
    IsNotEnd() bool // Whether it is point to the end of the range.
    MoveToNext()    // Let it point to the next element.
    Value() T       // Return the value of current element.
}
```

<a name="LessFn"></a>
## type [LessFn](<https://github.com/chen3feng/stl4go/blob/master/types.go#L45>)

LessFn is a function that returns whether 'a' is less than 'b'.

```go
type LessFn[T any] func(a, b T) bool
```

<a name="Map"></a>
## type [Map](<https://github.com/chen3feng/stl4go/blob/master/container.go#L11-L21>)

Map is a associative container that contains key\-value pairs with unique keys.

```go
type Map[K any, V any] interface {
    Container
    Has(K) bool                        // Checks whether the container contains element with specific key.
    Find(K) *V                         // Finds element with specific key.
    Insert(K, V)                       // Inserts a key-value pair in to the container or replace existing value.
    Remove(K) bool                     // Remove element with specific key.
    ForEach(func(K, V))                // Iterate the container.
    ForEachIf(func(K, V) bool)         // Iterate the container, stops when the callback returns false.
    ForEachMutable(func(K, *V))        // Iterate the container, *V is mutable.
    ForEachMutableIf(func(K, *V) bool) // Iterate the container, *V is mutable, stops when the callback returns false.
}
```

<a name="MapIterator"></a>
## type [MapIterator](<https://github.com/chen3feng/stl4go/blob/master/iterator.go#L17-L20>)

MapIterator is the interface for map's iterator.

```go
type MapIterator[K any, V any] interface {
    Key() K // The key of the element
    // contains filtered or unexported methods
}
```

<a name="MutableIterator"></a>
## type [MutableIterator](<https://github.com/chen3feng/stl4go/blob/master/iterator.go#L11-L14>)

MutableIterator is the interface for container's mutable iterator.

```go
type MutableIterator[T any] interface {
    Pointer() *T // Return the pointer to the value of current element.
    // contains filtered or unexported methods
}
```

<a name="MutableMapIterator"></a>
## type [MutableMapIterator](<https://github.com/chen3feng/stl4go/blob/master/iterator.go#L23-L26>)

MutableMapIterator is the interface for map's mutable iterator.

```go
type MutableMapIterator[K any, V any] interface {
    Key() K // The key of the element
    // contains filtered or unexported methods
}
```

<a name="Numeric"></a>
## type [Numeric](<https://github.com/chen3feng/stl4go/blob/master/types.go#L40-L42>)

Numeric is a constraint that permits any numeric type.

```go
type Numeric interface {
    // contains filtered or unexported methods
}
```

<a name="Ordered"></a>
## type [Ordered](<https://github.com/chen3feng/stl4go/blob/master/types.go#L35-L37>)

Ordered is a constraint that permits any ordered type: any type that supports the operators \< \<= \>= \>. If future releases of Go add new ordered types, this constraint will be modified to include them.

```go
type Ordered interface {
    // contains filtered or unexported methods
}
```

<a name="Pool"></a>
## type [Pool](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L6>)

Pool is a type safed sync.Pool.

```go
type Pool[T any] sync.Pool
```

<a name="MakePool"></a>
### func [MakePool](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L9>)

```go
func MakePool[T any]() Pool[T]
```

MakePool returns a Pool object

<a name="MakePoolWithNew"></a>
### func [MakePoolWithNew](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L14>)

```go
func MakePoolWithNew[T any](new func() *T) Pool[T]
```

MakePoolWithNew returns a Pool object with specified new function.

<a name="Pool[T].Get"></a>
### func \(\*Pool\[T\]\) [Get](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L22>)

```go
func (pool *Pool[T]) Get() *T
```

Get selects an arbitrary item from the Pool, removes it from the Pool, and returns it to the caller.

<a name="Pool[T].Put"></a>
### func \(\*Pool\[T\]\) [Put](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L31>)

```go
func (pool *Pool[T]) Put(x *T)
```

Put puts x to the pool.

<a name="PriorityQueue"></a>
## type [PriorityQueue](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L6-L9>)

PriorityQueue is an queue with priority. The elements of the priority queue are ordered according to their natural ordering, or by a less function provided at construction time, depending on which constructor is used.

```go
type PriorityQueue[T any] struct {
    // contains filtered or unexported fields
}
```

<details><summary>Example</summary>
<p>

This example inserts several ints into an IntHeap, checks the minimum, and removes them in order of priority.

```go
h := NewPriorityQueue[int]()
h.Push(3)
h.Push(2)
h.Push(1)
h.Push(5)
fmt.Printf("minimum: %d\n", h.Top())

for h.Len() > 0 {
	fmt.Printf("%d ", h.Pop())
}
// Output:
// minimum: 1
// 1 2 3 5
```

#### Output

```
minimum: 1
1 2 3 5
```

</p>
</details>

<a name="NewPriorityQueue"></a>
### func [NewPriorityQueue](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L12>)

```go
func NewPriorityQueue[T Ordered]() *PriorityQueue[T]
```

NewPriorityQueue creates an empty priority object.

<a name="NewPriorityQueueFunc"></a>
### func [NewPriorityQueueFunc](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L34>)

```go
func NewPriorityQueueFunc[T any](less LessFn[T]) *PriorityQueue[T]
```

NewPriorityQueueFunc creates an empty priority object with specified compare function less.

<a name="NewPriorityQueueOf"></a>
### func [NewPriorityQueueOf](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L29>)

```go
func NewPriorityQueueOf[T Ordered](elements ...T) *PriorityQueue[T]
```

NewPriorityQueueOf creates a new priority object with specified initial elements.

<a name="NewPriorityQueueOn"></a>
### func [NewPriorityQueueOn](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L20>)

```go
func NewPriorityQueueOn[T Ordered](slice []T) *PriorityQueue[T]
```

NewPriorityQueueOn creates a new priority object on the specified slices. The slice become a heap after the call.

<a name="PriorityQueue[T].Clear"></a>
### func \(\*PriorityQueue\[T\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L52>)

```go
func (pq *PriorityQueue[T]) Clear()
```

Clear clear the priority queue.

<a name="PriorityQueue[T].IsEmpty"></a>
### func \(\*PriorityQueue\[T\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L47>)

```go
func (pq *PriorityQueue[T]) IsEmpty() bool
```

IsEmpty checks whether priority queue has no elements.

<a name="PriorityQueue[T].Len"></a>
### func \(\*PriorityQueue\[T\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L42>)

```go
func (pq *PriorityQueue[T]) Len() int
```

Len returns the number of elements in the priority queue.

<a name="PriorityQueue[T].Pop"></a>
### func \(\*PriorityQueue\[T\]\) [Pop](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L67>)

```go
func (pq *PriorityQueue[T]) Pop() T
```

Pop removes the top element in the priority queue.

<a name="PriorityQueue[T].Push"></a>
### func \(\*PriorityQueue\[T\]\) [Push](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L62>)

```go
func (pq *PriorityQueue[T]) Push(v T)
```

Push pushes the given element v to the priority queue.

<a name="PriorityQueue[T].Top"></a>
### func \(\*PriorityQueue\[T\]\) [Top](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L57>)

```go
func (pq *PriorityQueue[T]) Top() T
```

Top returns the top element in the priority queue.

<a name="Queue"></a>
## type [Queue](<https://github.com/chen3feng/stl4go/blob/master/container.go#L71-L78>)

Queue is a container that can add elements to one end and remove elements from the other end.

```go
type Queue[T any] interface {
    Container
    Front()            // Front returns the first element in the container.
    Back()             // Back returns the last element in the container.
    Push(T)            // Push pushes an element at the back of the container.
    Pop() T            // Pop popups a front from the back of the container.
    TryPop() (T, bool) // TryPop tries to popup a element from the front of the container.
}
```

<a name="SList"></a>
## type [SList](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L4-L8>)

SList is a singly linked list.

```go
type SList[T any] struct {
    // contains filtered or unexported fields
}
```

<a name="SListOf"></a>
### func [SListOf](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L16>)

```go
func SListOf[T any](values ...T) SList[T]
```

SListOf return a SList that contains values.

<a name="SList[T].Back"></a>
### func \(\*SList\[T\]\) [Back](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L50>)

```go
func (l *SList[T]) Back() T
```

Back returns the last element in the list.

<a name="SList[T].Clear"></a>
### func \(\*SList\[T\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L35>)

```go
func (l *SList[T]) Clear()
```

Clear erases all elements from the container. After this call, Len\(\) returns zero.

<a name="SList[T].ForEach"></a>
### func \(\*SList\[T\]\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L134>)

```go
func (l *SList[T]) ForEach(cb func(T))
```

ForEach iterate the list, apply each element to the cb callback function.

<a name="SList[T].ForEachIf"></a>
### func \(\*SList\[T\]\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L142>)

```go
func (l *SList[T]) ForEachIf(cb func(T) bool)
```

ForEachIf iterate the container, apply each element to the cb callback function, stop if cb returns false.

<a name="SList[T].ForEachMutable"></a>
### func \(\*SList\[T\]\) [ForEachMutable](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L151>)

```go
func (l *SList[T]) ForEachMutable(cb func(*T))
```

ForEachMutable iterate the container, apply pointer of each element to the cb callback function.

<a name="SList[T].ForEachMutableIf"></a>
### func \(\*SList\[T\]\) [ForEachMutableIf](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L159>)

```go
func (l *SList[T]) ForEachMutableIf(cb func(*T) bool)
```

ForEachMutableIf iterate the container, apply pointer of each element to the cb callback function, stop if cb returns false.

<a name="SList[T].Front"></a>
### func \(\*SList\[T\]\) [Front](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L42>)

```go
func (l *SList[T]) Front() T
```

Front returns the first element in the list.

<a name="SList[T].IsEmpty"></a>
### func \(\*SList\[T\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L25>)

```go
func (l *SList[T]) IsEmpty() bool
```

IsEmpty checks if the container has no elements.

<a name="SList[T].Iterate"></a>
### func \(\*SList\[T\]\) [Iterate](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L168>)

```go
func (l *SList[T]) Iterate() MutableIterator[T]
```

Iterate returns an iterator to the whole container.

<a name="SList[T].Len"></a>
### func \(\*SList\[T\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L30>)

```go
func (l *SList[T]) Len() int
```

Len returns the number of elements in the container.

<a name="SList[T].PopFront"></a>
### func \(\*SList\[T\]\) [PopFront](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L82>)

```go
func (l *SList[T]) PopFront() T
```

PopFront popups an element from the front of the list. The list must be non\-empty\!

<a name="SList[T].PushBack"></a>
### func \(\*SList\[T\]\) [PushBack](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L68>)

```go
func (l *SList[T]) PushBack(v T)
```

PushBack pushed an element to the tail of the list.

<a name="SList[T].PushFront"></a>
### func \(\*SList\[T\]\) [PushFront](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L58>)

```go
func (l *SList[T]) PushFront(v T)
```

PushFront pushed an element to the front of the list.

<a name="SList[T].Reverse"></a>
### func \(\*SList\[T\]\) [Reverse](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L97>)

```go
func (l *SList[T]) Reverse()
```

Reverse reverses the order of all elements in the container.

<a name="SList[T].Values"></a>
### func \(\*SList\[T\]\) [Values](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L113>)

```go
func (l *SList[T]) Values() []T
```

Values copies all elements in the container to a slice and return it.

<a name="Set"></a>
## type [Set](<https://github.com/chen3feng/stl4go/blob/master/container.go#L24-L33>)

Set is a containers that store unique elements.

```go
type Set[K any] interface {
    Container
    Has(K) bool             // Checks whether the container contains element with specific key.
    Insert(K) bool          // Inserts a element in to the container or replace existing value.
    InsertN(...K) int       // Inserts multiple elements in to the container or replace existing value.
    Remove(K) bool          // Remove specific element, return true if element was in the container.
    RemoveN(...K) int       // Remove multiple elements, return the number of removed elements.
    ForEach(func(K))        // Iterate the container.
    ForEachIf(func(K) bool) // Iterate the container, stops when the callback returns false.
}
```

<a name="Signed"></a>
## type [Signed](<https://github.com/chen3feng/stl4go/blob/master/types.go#L6-L8>)

Signed is a constraint that permits any signed integer type. If future releases of Go add new predeclared signed integer types, this constraint will be modified to include them.

```go
type Signed interface {
    // contains filtered or unexported methods
}
```

<a name="SkipList"></a>
## type [SkipList](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L28-L37>)

SkipList is a probabilistic data structure that seem likely to supplant balanced trees as the implementation method of choice for many applications. Skip list algorithms have the same asymptotic expected time bounds as balanced trees and are simpler, faster and use less space.

See https://en.wikipedia.org/wiki/Skip_list for more details.

```go
type SkipList[K any, V any] struct {
    // contains filtered or unexported fields
}
```

<a name="NewSkipList"></a>
### func [NewSkipList](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L40>)

```go
func NewSkipList[K Ordered, V any]() *SkipList[K, V]
```

NewSkipList creates a new SkipList for Ordered key type.

<a name="NewSkipListFromMap"></a>
### func [NewSkipListFromMap](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L48>)

```go
func NewSkipListFromMap[K Ordered, V any](m map[K]V) *SkipList[K, V]
```

NewSkipListFromMap creates a new SkipList from a map.

<a name="NewSkipListFunc"></a>
### func [NewSkipListFunc](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L57>)

```go
func NewSkipListFunc[K any, V any](keyCmp CompareFn[K]) *SkipList[K, V]
```

NewSkipListFunc creates a new SkipList with specified compare function keyCmp.

<a name="SkipList[K, V].Clear"></a>
### func \(\*SkipList\[K, V\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L76>)

```go
func (sl *SkipList[K, V]) Clear()
```

Clear implements the Container interface.

<a name="SkipList[K, V].Find"></a>
### func \(\*SkipList\[K, V\]\) [Find](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L122>)

```go
func (sl *SkipList[K, V]) Find(key K) *V
```

Find returns the value associated with the passed key if the key is in the skiplist, otherwise returns nil.

<a name="SkipList[K, V].FindRange"></a>
### func \(\*SkipList\[K, V\]\) [FindRange](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L150>)

```go
func (sl *SkipList[K, V]) FindRange(first, last K) MutableMapIterator[K, V]
```

FindRange returns an iterator in range \[first, last\) \(last is not included\).

<a name="SkipList[K, V].ForEach"></a>
### func \(\*SkipList\[K, V\]\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L173>)

```go
func (sl *SkipList[K, V]) ForEach(op func(K, V))
```

ForEach implements the Map interface.

<a name="SkipList[K, V].ForEachIf"></a>
### func \(\*SkipList\[K, V\]\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L187>)

```go
func (sl *SkipList[K, V]) ForEachIf(op func(K, V) bool)
```

ForEachIf implements the Map interface.

<a name="SkipList[K, V].ForEachMutable"></a>
### func \(\*SkipList\[K, V\]\) [ForEachMutable](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L180>)

```go
func (sl *SkipList[K, V]) ForEachMutable(op func(K, *V))
```

ForEachMutable implements the Map interface.

<a name="SkipList[K, V].ForEachMutableIf"></a>
### func \(\*SkipList\[K, V\]\) [ForEachMutableIf](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L196>)

```go
func (sl *SkipList[K, V]) ForEachMutableIf(op func(K, *V) bool)
```

ForEachMutableIf implements the Map interface.

<a name="SkipList[K, V].Has"></a>
### func \(\*SkipList\[K, V\]\) [Has](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L131>)

```go
func (sl *SkipList[K, V]) Has(key K) bool
```

Has implement the Map interface.

<a name="SkipList[K, V].Insert"></a>
### func \(\*SkipList\[K, V\]\) [Insert](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L91>)

```go
func (sl *SkipList[K, V]) Insert(key K, value V)
```

Insert inserts a key\-value pair into the skiplist. If the key is already in the skip list, it's value will be updated.

<a name="SkipList[K, V].IsEmpty"></a>
### func \(\*SkipList\[K, V\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L66>)

```go
func (sl *SkipList[K, V]) IsEmpty() bool
```

IsEmpty implements the Container interface.

<a name="SkipList[K, V].Iterate"></a>
### func \(\*SkipList\[K, V\]\) [Iterate](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L85>)

```go
func (sl *SkipList[K, V]) Iterate() MutableMapIterator[K, V]
```

Iterate return an iterator to the skiplist.

<a name="SkipList[K, V].Len"></a>
### func \(\*SkipList\[K, V\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L71>)

```go
func (sl *SkipList[K, V]) Len() int
```

Len implements the Container interface.

<a name="SkipList[K, V].LowerBound"></a>
### func \(\*SkipList\[K, V\]\) [LowerBound](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L138>)

```go
func (sl *SkipList[K, V]) LowerBound(key K) MutableMapIterator[K, V]
```

LowerBound returns an iterator to the first element in the skiplist that does not satisfy element \< value \(i.e. greater or equal to\), or a end iterator if no such element is found.

<a name="SkipList[K, V].Remove"></a>
### func \(\*SkipList\[K, V\]\) [Remove](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L156>)

```go
func (sl *SkipList[K, V]) Remove(key K) bool
```

Remove removes the key\-value pair associated with the passed key and returns true if the key is in the skiplist, otherwise returns false.

<a name="SkipList[K, V].UpperBound"></a>
### func \(\*SkipList\[K, V\]\) [UpperBound](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L145>)

```go
func (sl *SkipList[K, V]) UpperBound(key K) MutableMapIterator[K, V]
```

UpperBound returns an iterator to the first element in the skiplist that does not satisfy value \< element \(i.e. strictly greater\), or a end iterator if no such element is found.

<a name="SkipListSet"></a>
## type [SkipListSet](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L4>)

SkipListSet is a SortedSet implemented with skiplist.

```go
type SkipListSet[K any] SkipList[K, struct{}]
```

<a name="NewSkipListSet"></a>
### func [NewSkipListSet](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L7>)

```go
func NewSkipListSet[K Ordered]() *SkipListSet[K]
```

NewSkipListSet creates a new SkipListSet object.

<a name="NewSkipListSetFunc"></a>
### func [NewSkipListSetFunc](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L12>)

```go
func NewSkipListSetFunc[K any](cmp CompareFn[K]) *SkipListSet[K]
```

NewSkipListSetFunc creates a new SkipListSet object with specified compare function.

<a name="NewSkipListSetOf"></a>
### func [NewSkipListSetOf](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L17>)

```go
func NewSkipListSetOf[K Ordered](elements ...K) *SkipListSet[K]
```

NewSkipListSetOf creates a new SkipListSet object with specified elements.

<a name="SkipListSet[K].Clear"></a>
### func \(\*SkipListSet\[K\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L36>)

```go
func (s *SkipListSet[K]) Clear()
```

Clear implements the SortedSet interface.

<a name="SkipListSet[K].FindRange"></a>
### func \(\*SkipListSet\[K\]\) [FindRange](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L103>)

```go
func (s *SkipListSet[K]) FindRange(first, last K) Iterator[K]
```

FindRange implements the SortedSet interface.

<a name="SkipListSet[K].ForEach"></a>
### func \(\*SkipListSet\[K\]\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L83>)

```go
func (s *SkipListSet[K]) ForEach(f func(K))
```

ForEach implements the SortedSet interface.

<a name="SkipListSet[K].ForEachIf"></a>
### func \(\*SkipListSet\[K\]\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L88>)

```go
func (s *SkipListSet[K]) ForEachIf(f func(K) bool)
```

ForEachIf implements the SortedSet interface.

<a name="SkipListSet[K].Has"></a>
### func \(\*SkipListSet\[K\]\) [Has](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L41>)

```go
func (s *SkipListSet[K]) Has(key K) bool
```

Has implements the SortedSet interface.

<a name="SkipListSet[K].Insert"></a>
### func \(\*SkipListSet\[K\]\) [Insert](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L46>)

```go
func (s *SkipListSet[K]) Insert(key K) bool
```

Insert implements the SortedSet interface.

<a name="SkipListSet[K].InsertN"></a>
### func \(\*SkipListSet\[K\]\) [InsertN](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L53>)

```go
func (s *SkipListSet[K]) InsertN(keys ...K) int
```

InsertN implements the SortedSet interface.

<a name="SkipListSet[K].IsEmpty"></a>
### func \(\*SkipListSet\[K\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L26>)

```go
func (s *SkipListSet[K]) IsEmpty() bool
```

IsEmpty implements the SortedSet interface.

<a name="SkipListSet[K].Keys"></a>
### func \(\*SkipListSet\[K\]\) [Keys](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L76>)

```go
func (s *SkipListSet[K]) Keys() []K
```

Keys return a copy of sorted keys as slice.

<a name="SkipListSet[K].Len"></a>
### func \(\*SkipListSet\[K\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L31>)

```go
func (s *SkipListSet[K]) Len() int
```

Len implements the SortedSet interface.

<a name="SkipListSet[K].LowerBound"></a>
### func \(\*SkipListSet\[K\]\) [LowerBound](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L93>)

```go
func (s *SkipListSet[K]) LowerBound(key K) Iterator[K]
```

LowerBound implements the SortedSet interface.

<a name="SkipListSet[K].Remove"></a>
### func \(\*SkipListSet\[K\]\) [Remove](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L62>)

```go
func (s *SkipListSet[K]) Remove(key K) bool
```

Remove implements the SortedSet interface.

<a name="SkipListSet[K].RemoveN"></a>
### func \(\*SkipListSet\[K\]\) [RemoveN](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L67>)

```go
func (s *SkipListSet[K]) RemoveN(keys ...K) int
```

RemoveN implements the SortedSet interface.

<a name="SkipListSet[K].UpperBound"></a>
### func \(\*SkipListSet\[K\]\) [UpperBound](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L98>)

```go
func (s *SkipListSet[K]) UpperBound(key K) Iterator[K]
```

UpperBound implements the SortedSet interface.

<a name="SortedMap"></a>
## type [SortedMap](<https://github.com/chen3feng/stl4go/blob/master/container.go#L36-L50>)

SortedMap is a Map that provides a total ordering on its keys.

```go
type SortedMap[K any, V any] interface {

    // LowerBound returns an iterator to the first element in the container that
    // does not satisfy element.key < value (i.e. greater or equal to),
    // or a end iterator if no such element is found.
    LowerBound(K) MutableMapIterator[K, V]

    // UpperBound returns an iterator to the first element in the container that
    // does not satisfy value < element.key (i.e. strictly greater),
    // or a end iterator if no such element is found.
    UpperBound(K) MutableMapIterator[K, V]

    // FindRange returns an iterator in range [first, last) (last is not included).
    FindRange(K, K) MutableMapIterator[K, V]
    // contains filtered or unexported methods
}
```

<a name="SortedSet"></a>
## type [SortedSet](<https://github.com/chen3feng/stl4go/blob/master/container.go#L53-L68>)

SortedSet is a Set that provides a total ordering on its elements.

```go
type SortedSet[K any] interface {

    // LowerBound returns an iterator to the first element in the container that
    // does not satisfy element < value (i.e. greater or equal to),
    // or a end iterator if no such element is found.
    LowerBound(K) Iterator[K]

    // UpperBound returns an iterator to the first element in the container that
    // does not satisfy value < element (i.e. strictly greater),
    // or a end iterator if no such element is found.
    UpperBound(K) Iterator[K]

    // FindRange returns an iterator in range [first, last) (last is not included).
    FindRange(K, K) Iterator[K]
    // contains filtered or unexported methods
}
```

<a name="Stack"></a>
## type [Stack](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L5-L7>)

Stack s is a container adaptor that provides the functionality of a stack, a LIFO \(last\-in, first\-out\) data structure.

```go
type Stack[T any] struct {
    // contains filtered or unexported fields
}
```

<a name="NewStack"></a>
### func [NewStack](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L10>)

```go
func NewStack[T any]() *Stack[T]
```

NewStack creates a new Stack object.

<a name="NewStackCap"></a>
### func [NewStackCap](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L15>)

```go
func NewStackCap[T any](capicity int) *Stack[T]
```

NewStackCap creates a new Stack object with the specified capicity.

<a name="Stack[T].Cap"></a>
### func \(Stack\[T\]\) [Cap](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L30>)

```go
func (s Stack[T]) Cap() int
```

Cap returns the capacity of the stack.

<a name="Stack[T].Clear"></a>
### func \(\*Stack\[T\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L35>)

```go
func (s *Stack[T]) Clear()
```

Clear implements the Container interface.

<a name="Stack[T].IsEmpty"></a>
### func \(Stack\[T\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L20>)

```go
func (s Stack[T]) IsEmpty() bool
```

IsEmpty implements the Container interface.

<a name="Stack[T].Len"></a>
### func \(Stack\[T\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L25>)

```go
func (s Stack[T]) Len() int
```

Len implements the Container interface.

<a name="Stack[T].Pop"></a>
### func \(\*Stack\[T\]\) [Pop](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L58>)

```go
func (s *Stack[T]) Pop() T
```

Pop popups an element from the top of the stack. It must be called when IsEmpty\(\) returned false, otherwise it will panic.

<a name="Stack[T].Push"></a>
### func \(\*Stack\[T\]\) [Push](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L40>)

```go
func (s *Stack[T]) Push(t T)
```

Push pushes the element to the top of the stack.

<a name="Stack[T].Top"></a>
### func \(Stack\[T\]\) [Top](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L67>)

```go
func (s Stack[T]) Top() T
```

Top returns the top element in the stack. It must be called when s.IsEmpty\(\) returned false, otherwise it will panic.

<a name="Stack[T].TryPop"></a>
### func \(\*Stack\[T\]\) [TryPop](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L45>)

```go
func (s *Stack[T]) TryPop() (val T, ok bool)
```

TryPop tries to popup an element from the top of the stack.

<a name="Unsigned"></a>
## type [Unsigned](<https://github.com/chen3feng/stl4go/blob/master/types.go#L13-L15>)

Unsigned is a constraint that permits any unsigned integer type. If future releases of Go add new predeclared unsigned integer types, this constraint will be modified to include them.

```go
type Unsigned interface {
    // contains filtered or unexported methods
}
```

<a name="Vector"></a>
## type [Vector](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L7>)

Vector is a sequence container representing array that can change in size.

```go
type Vector[T any] []T
```

<a name="AsVector"></a>
### func [AsVector](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L26>)

```go
func AsVector[T any](s []T) Vector[T]
```

AsVector casts a slice as a Vector object.

<a name="MakeVector"></a>
### func [MakeVector](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L10>)

```go
func MakeVector[T any]() Vector[T]
```

MakeVector creates an empty Vector object.

<a name="MakeVectorCap"></a>
### func [MakeVectorCap](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L15>)

```go
func MakeVectorCap[T any](c int) Vector[T]
```

MakeVectorCap creates an empty Vector object with specified capacity.

<a name="VectorOf"></a>
### func [VectorOf](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L21>)

```go
func VectorOf[T any](v ...T) Vector[T]
```

VectorOf creates a Vector object with initial values.

<a name="Vector[T].Append"></a>
### func \(\*Vector\[T\]\) [Append](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L120>)

```go
func (v *Vector[T]) Append(x ...T)
```

Append appends the values x... to the tail of the vector.

<a name="Vector[T].At"></a>
### func \(\*Vector\[T\]\) [At](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L75>)

```go
func (v *Vector[T]) At(i int) T
```

At returns the element value at the index i. You can also use the \[\] operator, and it's better.

<a name="Vector[T].Back"></a>
### func \(Vector\[T\]\) [Back](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L115>)

```go
func (v Vector[T]) Back() T
```

Back returns the element at the end of the vector. It must be called when IsEmpty\(\) returned false, otherwise it will panic.

<a name="Vector[T].Cap"></a>
### func \(\*Vector\[T\]\) [Cap](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L41>)

```go
func (v *Vector[T]) Cap() int
```

Cap returns the capacity of the vector.

<a name="Vector[T].Clear"></a>
### func \(\*Vector\[T\]\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L47>)

```go
func (v *Vector[T]) Clear()
```

Clear erases all elements from the vector. After this call, Len\(\) returns zero. Leaves the Cap\(\) of the vector unchanged.

<a name="Vector[T].ForEach"></a>
### func \(Vector\[T\]\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L166>)

```go
func (v Vector[T]) ForEach(cb func(val T))
```

ForEach iterate the container, apply each element to the cb callback function.

<a name="Vector[T].ForEachIf"></a>
### func \(Vector\[T\]\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L174>)

```go
func (v Vector[T]) ForEachIf(cb func(val T) bool)
```

ForEachIf iterate the container, apply each element to the cb callback function, stop if cb returns false.

<a name="Vector[T].ForEachMutable"></a>
### func \(Vector\[T\]\) [ForEachMutable](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L183>)

```go
func (v Vector[T]) ForEachMutable(cb func(val *T))
```

ForEachMutable iterate the container, apply pointer of each element to the cb callback function.

<a name="Vector[T].ForEachMutableIf"></a>
### func \(Vector\[T\]\) [ForEachMutableIf](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L191>)

```go
func (v Vector[T]) ForEachMutableIf(cb func(val *T) bool)
```

ForEachMutableIf iterate the container, apply pointer of each element to the cb callback function, stop if cb returns false.

<a name="Vector[T].Insert"></a>
### func \(\*Vector\[T\]\) [Insert](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L129>)

```go
func (v *Vector[T]) Insert(i int, x ...T)
```

Insert inserts the values x... into the vector at index i. After the insertion, \(\*v\)\[i\] == x\[0\]. Insert panics if i is out of range.

Complexity: O\(len\(s\) \+ len\(v\)\).

<a name="Vector[T].IsEmpty"></a>
### func \(\*Vector\[T\]\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L31>)

```go
func (v *Vector[T]) IsEmpty() bool
```

IsEmpty implements the Container interface.

<a name="Vector[T].Iterate"></a>
### func \(Vector\[T\]\) [Iterate](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L200>)

```go
func (v Vector[T]) Iterate() MutableIterator[T]
```

Iterate returns an iterator to the whole container.

<a name="Vector[T].IterateRange"></a>
### func \(Vector\[T\]\) [IterateRange](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L205>)

```go
func (v Vector[T]) IterateRange(i, j int) MutableIterator[T]
```

IterateRange returns an iterator to the range \[i, j\) of the container.

<a name="Vector[T].Len"></a>
### func \(\*Vector\[T\]\) [Len](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L36>)

```go
func (v *Vector[T]) Len() int
```

Len implements the Container interface.

<a name="Vector[T].PopBack"></a>
### func \(\*Vector\[T\]\) [PopBack](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L95>)

```go
func (v *Vector[T]) PopBack() T
```

PopBack popups an element from the end of the vector. It must be called when IsEmpty\(\) returned false, otherwise it will panic.

<a name="Vector[T].PushBack"></a>
### func \(\*Vector\[T\]\) [PushBack](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L88>)

```go
func (v *Vector[T]) PushBack(x T)
```

PushBack pushs an element to the end of the vector.

Complexity: O\(1\) if v.Len\(\) \< v.Cap\(\), therwise O\(len\(v\)\).

<a name="Vector[T].Remove"></a>
### func \(\*Vector\[T\]\) [Remove](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L149>)

```go
func (v *Vector[T]) Remove(i int)
```

Remove removes 1 element in the vector.

Complexity: O\(len\(s\) \- i\).

<a name="Vector[T].RemoveLength"></a>
### func \(\*Vector\[T\]\) [RemoveLength](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L161>)

```go
func (v *Vector[T]) RemoveLength(i int, len int)
```

RemoveLength removes the elements in the range\[i, i\+len\) from the vector.

<a name="Vector[T].RemoveRange"></a>
### func \(\*Vector\[T\]\) [RemoveRange](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L154>)

```go
func (v *Vector[T]) RemoveRange(i, j int)
```

RemoveRange removes the elements in the range\[i, j\) from the vector.

<a name="Vector[T].Reserve"></a>
### func \(\*Vector\[T\]\) [Reserve](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L58>)

```go
func (v *Vector[T]) Reserve(l int)
```

Reserve increases the capacity of the vector \(the total number of elements that the vector can hold without requiring reallocation\)to a value that's greater or equal to l. If l is greater than the current Cap\(\), new storage is allocated, otherwise the function does nothing.

Reserve\(\) does not change the size of the vector.

<a name="Vector[T].Set"></a>
### func \(\*Vector\[T\]\) [Set](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L81>)

```go
func (v *Vector[T]) Set(i int, x T)
```

Set sets the value of the element at the index i. You can also use the \[\] operator, and it's better.

<a name="Vector[T].Shrink"></a>
### func \(\*Vector\[T\]\) [Shrink](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L67>)

```go
func (v *Vector[T]) Shrink()
```

Shrink removes unused capacity from the vector.

<a name="Vector[T].TryPopBack"></a>
### func \(\*Vector\[T\]\) [TryPopBack](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L104>)

```go
func (v *Vector[T]) TryPopBack() (T, bool)
```

TryPopBack popups an element from the end of the vector.

Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)


<!-- gomarkdoc:embed:end -->


================================================
FILE: go.mod
================================================
module github.com/chen3feng/stl4go

go 1.18


================================================
FILE: go.sum
================================================


================================================
FILE: heap.go
================================================
// Fast generic heap algorithms, faster than [container/heap]

package stl4go

// MakeMinHeap build a min-heap on slice array.
//
// Complexity: O(len(array))
func MakeMinHeap[T Ordered](array []T) {
	// heapify
	n := len(array)
	for i := n/2 - 1; i >= 0; i-- {
		heapDown(array, i, n)
	}
}

// IsMinHeap checks whether the elements in slice array are a min heap.
//
// Complexity: O(len(array)).
func IsMinHeap[T Ordered](array []T) bool {
	parent := 0
	for child := 1; child < len(array); child++ {
		if array[parent] > array[child] {
			return false
		}

		if (child & 1) == 0 {
			parent++
		}
	}
	return true
}

// PushMinHeap pushes a element v into the min heap.
//
// Complexity: O(log(len(*heap))).
func PushMinHeap[T Ordered](heap *[]T, v T) {
	*heap = append(*heap, v)
	heapUp(*heap, len(*heap)-1)
}

// PopMinHeap removes and returns the minimum element from the heap.
//
// Complexity: O(log n) where n = len(*heap).
func PopMinHeap[T Ordered](heap *[]T) T {
	h := *heap
	n := len(h) - 1
	heapSwap(h, 0, n)
	heapDown(h, 0, n)
	*heap = h[0:n]
	return h[n]
}

// RemoveMinHeap removes and returns the element at index i from the min heap.
//
// Complexity: is O(log(n)) where n = len(*heap).
func RemoveMinHeap[T Ordered](heap *[]T, i int) T {
	h := *heap
	n := len(h) - 1
	if n != i {
		heapSwap(h, i, n)
		if !heapDown(h, i, n) {
			heapUp(h, i)
		}
	}
	*heap = h[0:n]
	return h[n]
}

func heapSwap[T any](heap []T, i, j int) {
	heap[i], heap[j] = heap[j], heap[i]
}

func heapUp[T Ordered](heap []T, j int) {
	for {
		i := (j - 1) / 2 // parent
		if i == j || !(heap[j] < heap[i]) {
			break
		}
		heapSwap(heap, i, j)
		j = i
	}
}

func heapDown[T Ordered](heap []T, i0, n int) bool {
	i := i0
	for {
		j1 := 2*i + 1
		if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
			break
		}
		j := j1 // left child
		if j2 := j1 + 1; j2 < n && heap[j2] < heap[j1] {
			j = j2 // = 2*i + 2  // right child
		}
		if !(heap[j] < heap[i]) {
			break
		}
		heapSwap(heap, i, j)
		i = j
	}
	return i > i0
}

// MakeHeapFunc build a min-heap on slice array with compare function less.
//
// Complexity: O(len(array))
func MakeHeapFunc[T any](array []T, less LessFn[T]) {
	// heapify
	n := len(array)
	for i := n/2 - 1; i >= 0; i-- {
		heapDownFunc(array, i, n, less)
	}
}

// IsHeapFunc checks whether the elements in slice array are a min heap (accord to less).
//
// Complexity: O(len(array)).
func IsHeapFunc[T any](array []T, less LessFn[T]) bool {
	parent := 0
	for child := 1; child < len(array); child++ {
		if !less(array[parent], array[child]) {
			return false
		}

		if (child & 1) == 0 {
			parent++
		}

	}
	return true
}

// PushHeapFunc pushes a element v into the heap.
//
// Complexity: O(log(len(*heap))).
func PushHeapFunc[T any](heap *[]T, v T, less LessFn[T]) {
	*heap = append(*heap, v)
	heapUpFunc(*heap, len(*heap)-1, less)
}

// PopHeapFunc removes and returns the minimum (according to less) element from the heap.
//
// Complexity: O(log n) where n = len(*heap).
func PopHeapFunc[T any](heap *[]T, less LessFn[T]) T {
	h := *heap
	n := len(h) - 1
	heapSwap(h, 0, n)
	heapDownFunc(h, 0, n, less)
	*heap = h[0:n]
	return h[n]
}

// RemoveHeapFunc removes and returns the element at index i from the heap.
//
// Complexity: is O(log(n)) where n = len(*heap).
func RemoveHeapFunc[T any](heap *[]T, i int, less LessFn[T]) T {
	h := *heap
	n := len(h) - 1
	if n != i {
		heapSwap(h, i, n)
		if !heapDownFunc(h, i, n, less) {
			heapUpFunc(h, i, less)
		}
	}
	*heap = h[0:n]
	return h[n]
}

func heapUpFunc[T any](heap []T, j int, less LessFn[T]) {
	for {
		i := (j - 1) / 2 // parent
		if i == j || !less(heap[j], heap[i]) {
			break
		}
		heapSwap(heap, i, j)
		j = i
	}
}

func heapDownFunc[T any](heap []T, i0, n int, less LessFn[T]) bool {
	i := i0
	for {
		j1 := 2*i + 1
		if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
			break
		}
		j := j1 // left child
		if j2 := j1 + 1; j2 < n && less(heap[j2], heap[j1]) {
			j = j2 // = 2*i + 2  // right child
		}
		if !less(heap[j], heap[i]) {
			break
		}
		heapSwap(heap, i, j)
		i = j
	}
	return i > i0
}


================================================
FILE: heap.md
================================================
# Heap

stl4go provides a group of [heap](https://en.wikipedia.org/wiki/Heap_(data_structure)) algorithms.

## Easy to use

For ordered types, you can easily use the heap algorithms, for example, with `int` type:

```go
func Example() {
    heap := []int {5, 4, 3, 2, 1}
    stl4go.MakeMinHeap(heap)
    stl4go.PushMinHeap(&heap, 6)
    n := stl4go.PopMinHeap(&heap) // get 1
}
```

Please compare it with [container/heap](https://pkg.go.dev/container/heap#example-package-IntHeap):

```go
// This example demonstrates an integer heap built using the heap interface.
package main

import (
	"container/heap"
	"fmt"
)

// An IntHeap is a min-heap of ints.
type IntHeap []int

func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x any) {
	// Push and Pop use pointer receivers because they modify the slice's length,
	// not just its contents.
	*h = append(*h, x.(int))
}

func (h *IntHeap) Pop() any {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func main() {
	h := &IntHeap{2, 1, 5}
	heap.Init(h)
	heap.Push(h, 3)
	fmt.Printf("minimum: %d\n", (*h)[0])
	for h.Len() > 0 {
		fmt.Printf("%d ", heap.Pop(h))
	}
}
```

You must define a new type `IntHeap` and five methods before to use the standard library,
these boilerplate codes are verbose, tedious, and boring.

## Benchmark

The heap algorithms are also much faster than `container/heap`, even for the `Func` version.:

```console
% go test -bench BenchmarkHeap -benchmem
goos: darwin
goarch: arm64
pkg: github.com/chen3feng/stl4go
BenchmarkHeapInit/container/heap.Init-10                  360126              3195 ns/op               0 B/op          0 allocs/op
BenchmarkHeapInit/stlgo.MakeMinHeap-10                    998325              1127 ns/op               0 B/op          0 allocs/op
BenchmarkHeapInit/stlgo.MakeHeapFunc-10                   488419              2355 ns/op               0 B/op          0 allocs/op
...
BenchmarkHeapPush/container/heap.Push-10                  101260             11630 ns/op            5952 B/op        744 allocs/op
BenchmarkHeapPush/stlgo.PushMinHeap-10                    511680              2261 ns/op               0 B/op          0 allocs/op
BenchmarkHeapPush/stlgo.PushHeapFunc-10                   445850              2625 ns/op               0 B/op          0 allocs/op
...
BenchmarkHeapPop/container/heap.Pop-10                     14709             81153 ns/op            5952 B/op        744 allocs/op
BenchmarkHeapPop/stlgo.PopMinHeap-10                       61608             19516 ns/op               0 B/op          0 allocs/op
BenchmarkHeapPop/stlgo.PopHeapFunc-10                      22887             52440 ns/op               0 B/op          0 allocs/op
PASS
ok      github.com/chen3feng/stl4go     19.827s
```


================================================
FILE: heap_bench_test.go
================================================
package stl4go

import (
	"container/heap"
	"testing"
)

// An intHeap is a min-heap of ints.
type intHeap []int

func (h intHeap) Len() int           { return len(h) }
func (h intHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h intHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h *intHeap) Push(x any)        { *h = append(*h, x.(int)) }

func (h *intHeap) Pop() any {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

func BenchmarkHeapInit(b *testing.B) {
	data := Range(1, 1000)
	Shuffle(data)
	b.Run("container/heap.Init", func(b *testing.B) {
		data = Copy(data)
		h := intHeap(data)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			heap.Init(&h)
		}
	})
	b.Run("stlgo.MakeMinHeap", func(b *testing.B) {
		data = Copy(data)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			MakeMinHeap(data)
		}
	})
	b.Run("stlgo.MakeHeapFunc", func(b *testing.B) {
		data = Copy(data)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			MakeHeapFunc(data, Less[int])
		}
	})
}

func BenchmarkHeapPush(b *testing.B) {
	const count = 1000
	b.Run("container/heap.Push", func(b *testing.B) {
		h := intHeap([]int{})
		for i := 0; i < b.N; i++ {
			h = h[0:0]
			for n := 0; n < count; n++ {
				heap.Push(&h, n)
			}
		}
	})
	b.Run("stlgo.PushMinHeap", func(b *testing.B) {
		h := []int{}
		for i := 0; i < b.N; i++ {
			h = h[0:0]
			for n := 0; n < count; n++ {
				PushMinHeap(&h, n)
			}
		}
	})
	b.Run("stlgo.PushHeapFunc", func(b *testing.B) {
		h := []int{}
		for i := 0; i < b.N; i++ {
			h = h[0:0]
			for n := 0; n < count; n++ {
				PushHeapFunc(&h, n, Less[int])
			}
		}
	})
}

func BenchmarkHeapPop(b *testing.B) {
	s := Range(1, 1000)
	b.Run("container/heap.Pop", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			h := intHeap(Copy(s))
			heap.Init(&h)
			b.StartTimer()
			for len(h) > 0 {
				_ = heap.Pop(&h).(int)
			}
		}
	})
	b.Run("stlgo.PopMinHeap", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			h := Copy(s)
			MakeMinHeap(h)
			b.StartTimer()
			for len(h) > 0 {
				_ = PopMinHeap(&h)
			}
		}
	})
	b.Run("stlgo.PopHeapFunc", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			h := Copy(s)
			MakeMinHeap(h)
			b.StartTimer()
			for len(h) > 0 {
				_ = PopHeapFunc(&h, Less[int])
			}
		}
	})
}


================================================
FILE: heap_test.go
================================================
package stl4go

import (
	"testing"
)

func TestMakeMinHeap(t *testing.T) {
	data := []int{5, 4, 3, 2, 1}
	expectFalse(t, IsMinHeap(data))
	MakeMinHeap(data)
	expectTrue(t, IsMinHeap(data))
}

func TestIsMinHeap(t *testing.T) {
	heap := []int{}
	expectTrue(t, IsMinHeap(heap))
	heap = append(heap, 1)
	expectTrue(t, IsMinHeap(heap))
}

func TestMakeHeapFunc(t *testing.T) {
	data := []int{1, 2, 3, 4, 5}
	expectFalse(t, IsHeapFunc(data, Greater[int]))
	MakeHeapFunc(data, Greater[int])
	expectTrue(t, IsHeapFunc(data, Greater[int]))
}

func Test_MinHeap_PushPop(t *testing.T) {
	heap := []int{}
	PushMinHeap(&heap, 1)
	expectEq(t, PopMinHeap(&heap), 1)
	expectTrue(t, IsMinHeap(heap))
}

func Test_HeapFunc_PushPop(t *testing.T) {
	heap := []int{}
	cmp := Greater[int]
	PushHeapFunc(&heap, 1, cmp)
	expectTrue(t, IsHeapFunc(heap, cmp))
	expectEq(t, PopHeapFunc(&heap, cmp), 1)
	expectTrue(t, IsHeapFunc(heap, cmp))
}

func Test_MinHeap_Remove(t *testing.T) {
	heap := []int{5, 4, 3, 2, 1}
	MakeMinHeap(heap)
	RemoveMinHeap(&heap, 1)
	expectTrue(t, IsMinHeap(heap))
}

func Test_HeapFunc_Remove(t *testing.T) {
	heap := []int{1, 2, 3, 4, 5}
	cmp := Greater[int]
	MakeHeapFunc(heap, cmp)
	RemoveHeapFunc(&heap, 1, cmp)
	expectTrue(t, IsHeapFunc(heap, cmp))
}


================================================
FILE: helper.go
================================================
package stl4go

import (
	"reflect"
)

// nameOfType return type name as a string.
func nameOfType[T any]() string {
	var t *T
	return reflect.TypeOf(t).String()[1:]
}


================================================
FILE: iterator.go
================================================
package stl4go

// Iterator is the interface for container's iterator.
type Iterator[T any] interface {
	IsNotEnd() bool // Whether it is point to the end of the range.
	MoveToNext()    // Let it point to the next element.
	Value() T       // Return the value of current element.
}

// MutableIterator is the interface for container's mutable iterator.
type MutableIterator[T any] interface {
	Iterator[T]
	Pointer() *T // Return the pointer to the value of current element.
}

// MapIterator is the interface for map's iterator.
type MapIterator[K any, V any] interface {
	Iterator[V]
	Key() K // The key of the element
}

// MutableMapIterator is the interface for map's mutable iterator.
type MutableMapIterator[K any, V any] interface {
	MutableIterator[V]
	Key() K // The key of the element
}


================================================
FILE: lookup.go
================================================
package stl4go

// Max return the larger value between `a` and `b`.
//
// Complexity: O(1).
func Max[T Ordered](a, b T) T {
	if a > b {
		return a
	}
	return b
}

// Min return the smaller value between `a` and `b`.
//
// Complexity: O(1).
func Min[T Ordered](a, b T) T {
	if a < b {
		return a
	}
	return b
}

// MaxN return the maximum value in the sequence `a`.
//
// Complexity: O(len(a)).
func MaxN[T Ordered](a ...T) T {
	if len(a) == 0 {
		panic("can't call MaxN() with empty arguments list")
	}
	v := a[0]
	for i := 1; i < len(a); i++ {
		if a[i] > v {
			v = a[i]
		}
	}
	return v
}

// MinN return the minimum value in the sequence `a`.
//
// Complexity: O(len(a)).
func MinN[T Ordered](a ...T) T {
	if len(a) == 0 {
		panic("can't call MaxN() with empty arguments list")
	}
	v := a[0]
	for i := 1; i < len(a); i++ {
		if a[i] < v {
			v = a[i]
		}
	}
	return v
}

// MinMax returns both min and max between a and b.
//
// Complexity: O(1).
func MinMax[T Ordered](a, b T) (min, max T) {
	if a < b {
		return a, b
	}
	return b, a
}

// MinMaxN returns both min and max in slice a.
//
// Complexity: O(len(a))
func MinMaxN[T Ordered](a ...T) (min, max T) {
	if len(a) == 0 {
		panic("can't call MaxN() with empty arguments list")
	}
	min = a[0]
	max = a[0]
	for i := 1; i < len(a); i++ {
		if a[i] < min {
			min = a[i]
		}
		if a[i] > max {
			max = a[i]
		}
	}
	return
}

// Find find the first value x in the given slice a linearly.
// return (index, true) if found,
// return (_, false) if not found.
//
// Complexity: O(len(a)).
func Find[T comparable](a []T, x T) (index int, ok bool) {
	for i, v := range a {
		if v == x {
			return i, true
		}
	}
	return -1, false
}

// FindIf find the first value x satisfying function cond in the given slice a linearly.
// return (index, true) if found,
// return (_, false) if not found.
//
// Complexity: O(len(a)).
func FindIf[T any](a []T, cond func(T) bool) (index int, ok bool) {
	for i, v := range a {
		if cond(v) {
			return i, true
		}
	}
	return -1, false
}

// Index find the value x in the given slice a linearly.
//
// Return index if found, -1 if not found.
//
// Complexity: O(len(a)).
func Index[T comparable](a []T, x T) int {
	for i, v := range a {
		if v == x {
			return i
		}
	}
	return -1
}

// AllOf return true if pred(e) returns true for all elements e in a.
//
// Complexity: O(len(a)).
func AllOf[T any](a []T, pred func(T) bool) bool {
	for _, v := range a {
		if !pred(v) {
			return false
		}
	}
	return true
}

// AnyOf return true if pred(e) returns true for any elements e in a.
//
// Complexity: O(len(a)).
func AnyOf[T any](a []T, pred func(T) bool) bool {
	for _, v := range a {
		if pred(v) {
			return true
		}
	}
	return false
}

// NoneOf return true pred(e) returns true for none elements e in a.
//
// Complexity: O(len(a)).
func NoneOf[T any](a []T, pred func(T) bool) bool {
	return !AnyOf(a, pred)
}


================================================
FILE: lookup_test.go
================================================
package stl4go

import "testing"

func Test_Min(t *testing.T) {
	expectEq(t, Min(1, 2), 1)
	expectEq(t, Min(2, 1), 1)
	expectEq(t, Min(1, 1), 1)
	expectEq(t, Min("hello", "world"), "hello")
}

func Test_Max(t *testing.T) {
	expectEq(t, Max(1, 2), 2)
	expectEq(t, Max(2, 1), 2)
	expectEq(t, Max(2, 2), 2)
	expectEq(t, Max("hello", "world"), "world")
}

func Test_MinN(t *testing.T) {
	expectEq(t, MinN(1, 2, 3), 1)
	expectEq(t, MinN(2, 1, 3), 1)
	expectEq(t, MinN(1, 1, 1), 1)
	expectEq(t, MinN("hello", "world"), "hello")
	expectPanic(t, func() { MinN(emptyInts...) })
}

func Test_MaxN(t *testing.T) {
	expectEq(t, MaxN(1, 2), 2)
	expectEq(t, MaxN(2, 1), 2)
	expectEq(t, MaxN(2, 2), 2)
	expectEq(t, MaxN("hello", "world"), "world")
	expectPanic(t, func() { MaxN(emptyInts...) })
}

func Test_MinMax(t *testing.T) {
	min, max := MinMax(1, 2)
	expectEq(t, min, 1)
	expectEq(t, max, 2)
	min, max = MinMax(2, 1)
	expectEq(t, min, 1)
	expectEq(t, max, 2)
}

func Test_MinMaxN(t *testing.T) {
	min, max := MinMaxN(3, 4, 1, 2)
	expectEq(t, min, 1)
	expectEq(t, max, 4)
	expectPanic(t, func() { MinMaxN(emptyInts...) })
}

func Test_Find(t *testing.T) {
	a := []int{1, 2, 3, 4, 3}
	i, ok := Find(a, 3)
	expectTrue(t, ok)
	expectEq(t, i, 2)
	i, ok = Find(a, 5)
	expectFalse(t, ok)
}

func Test_FindIf(t *testing.T) {
	isNeg := func(x int) bool { return x < 0 }
	a := []int{1, 2, -3, 4, 3}
	i, ok := FindIf(a, isNeg)
	expectTrue(t, ok)
	expectEq(t, i, 2)
	i, ok = FindIf([]int{1, 2, 3, 4, 3}, isNeg)
	expectFalse(t, ok)
}

func Test_Index(t *testing.T) {
	a := []int{1, 2, 3, 4, 3}
	expectEq(t, Index(a, 3), 2)
	expectEq(t, Index(a, 5), -1)
}

var (
	pos = []int{1, 2, 3, 4, 5}
	neg = []int{-1, -2, -3, -4, -5}
	mix = []int{1, -2, 3, -4, 5}
)

func isNegative(n int) bool { return n < 0 }

func Test_AllOf(t *testing.T) {
	expectFalse(t, AllOf(pos, isNegative))
	expectTrue(t, AllOf(neg, isNegative))
	expectFalse(t, AllOf(mix, isNegative))
}

func Test_AnyOf(t *testing.T) {
	expectFalse(t, AnyOf(pos, isNegative))
	expectTrue(t, AnyOf(neg, isNegative))
	expectTrue(t, AnyOf(mix, isNegative))
}

func Test_NoneOf(t *testing.T) {
	expectTrue(t, NoneOf(pos, isNegative))
	expectFalse(t, NoneOf(neg, isNegative))
	expectFalse(t, NoneOf(mix, isNegative))
}


================================================
FILE: mlc_config.json
================================================
{
    "aliveStatusCodes": [
        400,
        429,
        200
    ]
}


================================================
FILE: pool.go
================================================
package stl4go

import "sync"

// Pool is a type safed sync.Pool.
type Pool[T any] sync.Pool

// MakePool returns a Pool object
func MakePool[T any]() Pool[T] {
	return Pool[T]{New: func() any { return new(T) }}
}

// MakePoolWithNew returns a Pool object with specified new function.
func MakePoolWithNew[T any](new func() *T) Pool[T] {
	if new != nil {
		return Pool[T]{New: func() any { return new() }}
	}
	return Pool[T]{}
}

// Get selects an arbitrary item from the Pool, removes it from the Pool, and returns it to the caller.
func (pool *Pool[T]) Get() *T {
	i := pool.untyped().Get()
	if i == nil {
		return nil
	}
	return i.(*T)
}

// Put puts x to the pool.
func (pool *Pool[T]) Put(x *T) {
	if x != nil {
		pool.untyped().Put(x)
	}
}

func (pool *Pool[T]) untyped() *sync.Pool {
	return (*sync.Pool)(pool)
}


================================================
FILE: pool_test.go
================================================
package stl4go

import "testing"

func TestPool(t *testing.T) {
	p := MakePool[int]()
	x := p.Get()
	p.Put(x)
}

func TestMakePoolWithNew(t *testing.T) {
	p := MakePoolWithNew(func() *int { return new(int) })
	x := p.Get()
	p.Put(x)
}

func TestMakePoolNil(t *testing.T) {
	p := MakePoolWithNew[int](nil)
	x := p.Get()
	expectEq(t, x, nil)
	p.Put(x)
}


================================================
FILE: priority_queue.go
================================================
package stl4go

// PriorityQueue is an queue with priority.
// The elements of the priority queue are ordered according to their natural ordering,
// or by a less function provided at construction time, depending on which constructor is used.
type PriorityQueue[T any] struct {
	heap []T
	impl pqImpl[T]
}

// NewPriorityQueue creates an empty priority object.
func NewPriorityQueue[T Ordered]() *PriorityQueue[T] {
	pq := pqOrdered[T]{}
	pq.impl = (pqImpl[T])(&pq)
	return &pq.PriorityQueue
}

// NewPriorityQueueOn creates a new priority object on the specified slices.
// The slice become a heap after the call.
func NewPriorityQueueOn[T Ordered](slice []T) *PriorityQueue[T] {
	MakeMinHeap(slice)
	pq := pqOrdered[T]{}
	pq.heap = slice
	pq.impl = pqImpl[T](&pq)
	return &pq.PriorityQueue
}

// NewPriorityQueueOf creates a new priority object with specified initial elements.
func NewPriorityQueueOf[T Ordered](elements ...T) *PriorityQueue[T] {
	return NewPriorityQueueOn(elements)
}

// NewPriorityQueueFunc creates an empty priority object with specified compare function less.
func NewPriorityQueueFunc[T any](less LessFn[T]) *PriorityQueue[T] {
	pq := pqFunc[T]{}
	pq.less = less
	pq.impl = (pqImpl[T])(&pq)
	return &pq.PriorityQueue
}

// Len returns the number of elements in the priority queue.
func (pq *PriorityQueue[T]) Len() int {
	return len(pq.heap)
}

// IsEmpty checks whether priority queue has no elements.
func (pq *PriorityQueue[T]) IsEmpty() bool {
	return len(pq.heap) == 0
}

// Clear clear the priority queue.
func (pq *PriorityQueue[T]) Clear() {
	pq.heap = pq.heap[0:0]
}

// Top returns the top element in the priority queue.
func (pq *PriorityQueue[T]) Top() T {
	return pq.heap[0]
}

// Push pushes the given element v to the priority queue.
func (pq *PriorityQueue[T]) Push(v T) {
	pq.impl.Push(v)
}

// Pop removes the top element in the priority queue.
func (pq *PriorityQueue[T]) Pop() T {
	return pq.impl.Pop()
}

type pqImpl[T any] interface {
	Push(v T)
	Pop() T
}

type pqOrdered[T Ordered] struct {
	PriorityQueue[T]
}

func (pq *pqOrdered[T]) Push(v T) {
	PushMinHeap(&pq.heap, v)
}

func (pq *pqOrdered[T]) Pop() T {
	return PopMinHeap(&pq.heap)
}

// funcHeap is a min-heap of T compared with less.
type pqFunc[T any] struct {
	PriorityQueue[T]
	less LessFn[T]
}

func (pq *pqFunc[T]) Push(v T) {
	PushHeapFunc(&pq.heap, v, pq.less)
}

func (pq *pqFunc[T]) Pop() T {
	return PopHeapFunc(&pq.heap, pq.less)
}


================================================
FILE: priority_queue_test.go
================================================
package stl4go

import (
	"fmt"
	"testing"
)

func TestInterface(t *testing.T) {
	_ = (Container)(NewPriorityQueue[int]())
}

func TestNewPriorityQueue(t *testing.T) {
	pq := NewPriorityQueue[int]()
	expectTrue(t, pq.IsEmpty())
	expectEq(t, pq.Len(), 0)
}

func TestNewPriorityQueueOf(t *testing.T) {
	pq := NewPriorityQueueOf(5, 4, 3, 2, 1)
	expectEq(t, pq.Len(), 5)
}

func TestPriorityQueue_PushPop(t *testing.T) {
	less := Less[int]
	pq := NewPriorityQueueFunc(less)
	for i := 5; i > 0; i-- {
		pq.Push(i)
		expectFalse(t, pq.IsEmpty())
	}
	var elements []int
	for !pq.IsEmpty() {
		elements = append(elements, pq.Pop())
	}
	expectTrue(t, pq.IsEmpty())
	expectTrue(t, IsSorted(elements))
	expectEq(t, len(elements), 5)
}

func TestPriorityQueueFunc_PushPop(t *testing.T) {
	pq := NewPriorityQueueFunc(Less[int])
	for i := 5; i > 0; i-- {
		pq.Push(i)
	}
	var elements []int
	for !pq.IsEmpty() {
		elements = append(elements, pq.Pop())
	}
	expectTrue(t, pq.IsEmpty())
	expectTrue(t, IsSorted(elements))
	expectEq(t, len(elements), 5)
}

func TestPriorityQueue_Clear(t *testing.T) {
	pq := NewPriorityQueue[int]()
	pq.Clear()
	expectTrue(t, pq.IsEmpty())
	expectEq(t, pq.Len(), 0)
	pq = NewPriorityQueueOf(1, 2, 3)
	pq.Clear()
	expectTrue(t, pq.IsEmpty())
	expectEq(t, pq.Len(), 0)
}

// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func ExamplePriorityQueue() {
	h := NewPriorityQueue[int]()
	h.Push(3)
	h.Push(2)
	h.Push(1)
	h.Push(5)
	fmt.Printf("minimum: %d\n", h.Top())

	for h.Len() > 0 {
		fmt.Printf("%d ", h.Pop())
	}
	// Output:
	// minimum: 1
	// 1 2 3 5
}


================================================
FILE: skiplist.go
================================================
// This implementation is based on https://github.com/liyue201/gostl/tree/master/ds/skiplist
// (many thanks), added many optimizations, such as:
//
//  - adaptive level
//  - lesser search for prevs when key already exists.
//  - reduce memory allocations
//  - richer interface.
//
// etc.

package stl4go

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

const (
	skipListMaxLevel = 40
)

// SkipList is a probabilistic data structure that seem likely to supplant balanced trees as the
// implementation method of choice for many applications. Skip list algorithms have the same
// asymptotic expected time bounds as balanced trees and are simpler, faster and use less space.
//
// See https://en.wikipedia.org/wiki/Skip_list for more details.
type SkipList[K any, V any] struct {
	level int                // Current level, may increase dynamically during insertion
	len   int                // Total elements number in the skiplist.
	head  skipListNode[K, V] // head.next[level] is the head of each level.
	// This cache is used to save the previous nodes when modifying the skip list to avoid
	// allocating memory each time it is called.
	prevsCache []*skipListNode[K, V]
	rander     *rand.Rand
	impl       skipListImpl[K, V]
}

// NewSkipList creates a new SkipList for Ordered key type.
func NewSkipList[K Ordered, V any]() *SkipList[K, V] {
	sl := skipListOrdered[K, V]{}
	sl.init()
	sl.impl = (skipListImpl[K, V])(&sl)
	return &sl.SkipList
}

// NewSkipListFromMap creates a new SkipList from a map.
func NewSkipListFromMap[K Ordered, V any](m map[K]V) *SkipList[K, V] {
	sl := NewSkipList[K, V]()
	for k, v := range m {
		sl.Insert(k, v)
	}
	return sl
}

// NewSkipListFunc creates a new SkipList with specified compare function keyCmp.
func NewSkipListFunc[K any, V any](keyCmp CompareFn[K]) *SkipList[K, V] {
	sl := skipListFunc[K, V]{}
	sl.init()
	sl.keyCmp = keyCmp
	sl.impl = skipListImpl[K, V](&sl)
	return &sl.SkipList
}

// IsEmpty implements the Container interface.
func (sl *SkipList[K, V]) IsEmpty() bool {
	return sl.len == 0
}

// Len implements the Container interface.
func (sl *SkipList[K, V]) Len() int {
	return sl.len
}

// Clear implements the Container interface.
func (sl *SkipList[K, V]) Clear() {
	for i := range sl.head.next {
		sl.head.next[i] = nil
	}
	sl.level = 1
	sl.len = 0
}

// Iterate return an iterator to the skiplist.
func (sl *SkipList[K, V]) Iterate() MutableMapIterator[K, V] {
	return &skipListIterator[K, V]{sl.head.next[0], nil}
}

// Insert inserts a key-value pair into the skiplist.
// If the key is already in the skip list, it's value will be updated.
func (sl *SkipList[K, V]) Insert(key K, value V) {
	node, prevs := sl.impl.findInsertPoint(key)

	if node != nil {
		// Already exist, update the value
		node.value = value
		return
	}

	level := sl.randomLevel()
	node = newSkipListNode(level, key, value)

	// Insert node to each level
	for i := 0; i < Min(level, sl.level); i++ {
		node.next[i] = prevs[i].next[i]
		prevs[i].next[i] = node
	}

	if level > sl.level {
		// Increase the level
		for i := sl.level; i < level; i++ {
			sl.head.next[i] = node
		}
		sl.level = level
	}

	sl.len++
}

// Find returns the value associated with the passed key if the key is in the skiplist, otherwise
// returns nil.
func (sl *SkipList[K, V]) Find(key K) *V {
	node := sl.impl.findNode(key)
	if node != nil {
		return &node.value
	}
	return nil
}

// Has implement the Map interface.
func (sl *SkipList[K, V]) Has(key K) bool {
	return sl.impl.findNode(key) != nil
}

// LowerBound returns an iterator to the first element in the skiplist that
// does not satisfy element < value (i.e. greater or equal to),
// or a end iterator if no such element is found.
func (sl *SkipList[K, V]) LowerBound(key K) MutableMapIterator[K, V] {
	return &skipListIterator[K, V]{sl.impl.lowerBound(key), nil}
}

// UpperBound returns an iterator to the first element in the skiplist that
// does not satisfy value < element (i.e. strictly greater),
// or a end iterator if no such element is found.
func (sl *SkipList[K, V]) UpperBound(key K) MutableMapIterator[K, V] {
	return &skipListIterator[K, V]{sl.impl.upperBound(key), nil}
}

// FindRange returns an iterator in range [first, last) (last is not included).
func (sl *SkipList[K, V]) FindRange(first, last K) MutableMapIterator[K, V] {
	return &skipListIterator[K, V]{sl.impl.lowerBound(first), sl.impl.upperBound(last)}
}

// Remove removes the key-value pair associated with the passed key and returns true if the key is
// in the skiplist, otherwise returns false.
func (sl *SkipList[K, V]) Remove(key K) bool {
	node, prevs := sl.impl.findRemovePoint(key)
	if node == nil {
		return false
	}
	for i, v := range node.next { // Nomove the node from each level's links.
		prevs[i].next[i] = v
	}
	// Decrease the level if the top level become empty
	for sl.level > 1 && sl.head.next[sl.level-1] == nil {
		sl.level--
	}
	sl.len--
	return true
}

// ForEach implements the Map interface.
func (sl *SkipList[K, V]) ForEach(op func(K, V)) {
	for e := sl.head.next[0]; e != nil; e = e.next[0] {
		op(e.key, e.value)
	}
}

// ForEachMutable implements the Map interface.
func (sl *SkipList[K, V]) ForEachMutable(op func(K, *V)) {
	for e := sl.head.next[0]; e != nil; e = e.next[0] {
		op(e.key, &e.value)
	}
}

// ForEachIf implements the Map interface.
func (sl *SkipList[K, V]) ForEachIf(op func(K, V) bool) {
	for e := sl.head.next[0]; e != nil; e = e.next[0] {
		if !op(e.key, e.value) {
			return
		}
	}
}

// ForEachMutableIf implements the Map interface.
func (sl *SkipList[K, V]) ForEachMutableIf(op func(K, *V) bool) {
	for e := sl.head.next[0]; e != nil; e = e.next[0] {
		if !op(e.key, &e.value) {
			return
		}
	}
}

/// SkipList implementation part.

type skipListNode[K any, V any] struct {
	key   K
	value V
	next  []*skipListNode[K, V]
}

//go:generate bash ./skiplist_newnode_generate.sh skipListMaxLevel skiplist_newnode.go
// func newSkipListNode[K Ordered, V any](level int, key K, value V) *skipListNode[K, V]

type skipListIterator[K any, V any] struct {
	node, end *skipListNode[K, V]
}

func (it *skipListIterator[K, V]) IsNotEnd() bool {
	return it.node != it.end
}

func (it *skipListIterator[K, V]) MoveToNext() {
	it.node = it.node.next[0]
}

func (it *skipListIterator[K, V]) Key() K {
	return it.node.key
}

func (it *skipListIterator[K, V]) Value() V {
	return it.node.value
}

func (it *skipListIterator[K, V]) Pointer() *V {
	return &it.node.value
}

// skipListImpl is an interface to provide different implementation for Ordered key or CompareFn.
//
// We can use CompareFn to compare Ordered keys, but a separated implementation is much faster.
// We don't make the whole skip list an interface, in order to share the type independented method.
// And because these methods are called directly without going through the interface, they are also
// much faster.
type skipListImpl[K any, V any] interface {
	findNode(key K) *skipListNode[K, V]
	lowerBound(key K) *skipListNode[K, V]
	upperBound(key K) *skipListNode[K, V]
	findInsertPoint(key K) (*skipListNode[K, V], []*skipListNode[K, V])
	findRemovePoint(key K) (*skipListNode[K, V], []*skipListNode[K, V])
}

func (sl *SkipList[K, V]) init() {
	sl.level = 1
	// #nosec G404 -- This is not a security condition
	sl.rander = rand.New(rand.NewSource(time.Now().Unix()))
	sl.prevsCache = make([]*skipListNode[K, V], skipListMaxLevel)
	sl.head.next = make([]*skipListNode[K, V], skipListMaxLevel)
}

func (sl *SkipList[K, V]) randomLevel() int {
	total := uint64(1)<<uint64(skipListMaxLevel) - 1 // 2^n-1
	k := sl.rander.Uint64() & total
	level := skipListMaxLevel - bits.Len64(k) + 1
	// Since levels are randomly generated, most should be less than log2(s.len).
	// Then make a limit according to sl.len to avoid unexpectedly large value.
	for level > 3 && 1<<(level-3) > sl.len {
		level--
	}
	if (level > skipListMaxLevel) {
		level = skipListMaxLevel
	}

	return level
}

/// skipListOrdered part

// skipListOrdered is the skip list implementation for Ordered types.
type skipListOrdered[K Ordered, V any] struct {
	SkipList[K, V]
}

func (sl *skipListOrdered[K, V]) findNode(key K) *skipListNode[K, V] {
	return sl.doFindNode(key, true)
}

func (sl *skipListOrdered[K, V]) doFindNode(key K, eq bool) *skipListNode[K, V] {
	// This function execute the job of findNode if eq is true, otherwise lowBound.
	// Passing the control variable eq is ugly but it's faster than testing node
	// again outside the function in findNode.
	prev := &sl.head
	for i := sl.level - 1; i >= 0; i-- {
		for cur := prev.next[i]; cur != nil; cur = cur.next[i] {
			if cur.key == key {
				return cur
			}
			if cur.key > key {
				// All other node in this level must be greater than the key,
				// search the next level.
				break
			}
			prev = cur
		}
	}
	if eq {
		return nil
	}
	return prev.next[0]
}

func (sl *skipListOrdered[K, V]) lowerBound(key K) *skipListNode[K, V] {
	return sl.doFindNode(key, false)
}

func (sl *skipListOrdered[K, V]) upperBound(key K) *skipListNode[K, V] {
	node := sl.lowerBound(key)
	if node != nil && node.key == key {
		return node.next[0]
	}
	return node
}

// findInsertPoint returns (*node, nil) to the existed node if the key exists,
// or (nil, []*node) to the previous nodes if the key doesn't exist
func (sl *skipListOrdered[K, V]) findInsertPoint(key K) (*skipListNode[K, V], []*skipListNode[K, V]) {
	prevs := sl.prevsCache[0:sl.level]
	prev := &sl.head
	for i := sl.level - 1; i >= 0; i-- {
		for next := prev.next[i]; next != nil; next = next.next[i] {
			if next.key == key {
				// The key is already existed, prevs are useless because no new node insertion.
				// stop searching.
				return next, nil
			}
			if next.key > key {
				// All other node in this level must be greater than the key,
				// search the next level.
				break
			}
			prev = next
		}
		prevs[i] = prev
	}
	return nil, prevs
}

// findRemovePoint finds the node which match the key and it's previous nodes.
func (sl *skipListOrdered[K, V]) findRemovePoint(key K) (*skipListNode[K, V], []*skipListNode[K, V]) {
	prevs := sl.findPrevNodes(key)
	node := prevs[0].next[0]
	if node == nil || node.key != key {
		return nil, nil
	}
	return node, prevs
}

func (sl *skipListOrdered[K, V]) findPrevNodes(key K) []*skipListNode[K, V] {
	prevs := sl.prevsCache[0:sl.level]
	prev := &sl.head
	for i := sl.level - 1; i >= 0; i-- {
		for next := prev.next[i]; next != nil; next = next.next[i] {
			if next.key >= key {
				break
			}
			prev = next
		}
		prevs[i] = prev
	}
	return prevs
}

/// skipListFunc part

// skipListFunc is the skip list implementation which compare keys with func.
type skipListFunc[K any, V any] struct {
	SkipList[K, V]
	keyCmp CompareFn[K]
}

func (sl *skipListFunc[K, V]) findNode(key K) *skipListNode[K, V] {
	node := sl.lowerBound(key)
	if node != nil && sl.keyCmp(node.key, key) == 0 {
		return node
	}
	return nil
}

func (sl *skipListFunc[K, V]) lowerBound(key K) *skipListNode[K, V] {
	var prev = &sl.head
	for i := sl.level - 1; i >= 0; i-- {
		cur := prev.next[i]
		for ; cur != nil; cur = cur.next[i] {
			cmpRet := sl.keyCmp(cur.key, key)
			if cmpRet == 0 {
				return cur
			}
			if cmpRet > 0 {
				break
			}
			prev = cur
		}
	}
	return prev.next[0]
}

func (sl *skipListFunc[K, V]) upperBound(key K) *skipListNode[K, V] {
	node := sl.lowerBound(key)
	if node != nil && sl.keyCmp(node.key, key) == 0 {
		return node.next[0]
	}
	return node
}

// findInsertPoint returns (*node, nil) to the existed node if the key exists,
// or (nil, []*node) to the previous nodes if the key doesn't exist
func (sl *skipListFunc[K, V]) findInsertPoint(key K) (*skipListNode[K, V], []*skipListNode[K, V]) {
	prevs := sl.prevsCache[0:sl.level]
	prev := &sl.head
	for i := sl.level - 1; i >= 0; i-- {
		for cur := prev.next[i]; cur != nil; cur = cur.next[i] {
			r := sl.keyCmp(cur.key, key)
			if r == 0 {
				// The key is already existed, prevs are useless because no new node insertion.
				// stop searching.
				return cur, nil
			}
			if r > 0 {
				// All other node in this level must be greater than the key,
				// search the next level.
				break
			}
			prev = cur
		}
		prevs[i] = prev
	}
	return nil, prevs
}

// findRemovePoint finds the node which match the key and it's previous nodes.
func (sl *skipListFunc[K, V]) findRemovePoint(key K) (*skipListNode[K, V], []*skipListNode[K, V]) {
	prevs := sl.findPrevNodes(key)
	node := prevs[0].next[0]
	if node == nil || sl.keyCmp(node.key, key) != 0 {
		return nil, nil
	}
	return node, prevs
}

func (sl *skipListFunc[K, V]) findPrevNodes(key K) []*skipListNode[K, V] {
	prevs := sl.prevsCache[0:sl.level]
	prev := &sl.head
	for i := sl.level - 1; i >= 0; i-- {
		for next := prev.next[i]; next != nil; next = next.next[i] {
			if sl.keyCmp(next.key, key) >= 0 {
				break
			}
			prev = next
		}
		prevs[i] = prev
	}
	return prevs
}


================================================
FILE: skiplist.md
================================================
# SkipList

TODO,See tests.


================================================
FILE: skiplist_bench_test.go
================================================
package stl4go

import (
	"strconv"
	"testing"
)

const (
	benchInitSize  = 1000000
	benchBatchSize = 10
)

func newMapN(n int) map[int]int {
	m := map[int]int{}
	for i := 0; i < n; i++ {
		m[i] = i
	}
	return m
}

func BenchmarkSkipList_Iterate(b *testing.B) {
	sl := newSkipListN(100)
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for i := sl.Iterate(); i.IsNotEnd(); i.MoveToNext() {
			_, _ = i.Key(), i.
Download .txt
gitextract_wl0h18v1/

├── .github/
│   └── workflows/
│       ├── check-markdown-links.yml
│       ├── go.yml
│       └── gosec.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_zh.md
├── binary_search.go
├── binary_search_test.go
├── builtin_set.go
├── builtin_set_test.go
├── check.bat
├── check.sh
├── compare.go
├── compare_test.go
├── compute.go
├── compute_test.go
├── container.go
├── container_test.go
├── dlist.go
├── dlist_queue.go
├── dlist_queue_test.go
├── dlist_test.go
├── doc.go
├── functor.go
├── generate.go
├── generate_test.go
├── generated_doc.md
├── go.mod
├── go.sum
├── heap.go
├── heap.md
├── heap_bench_test.go
├── heap_test.go
├── helper.go
├── iterator.go
├── lookup.go
├── lookup_test.go
├── mlc_config.json
├── pool.go
├── pool_test.go
├── priority_queue.go
├── priority_queue_test.go
├── skiplist.go
├── skiplist.md
├── skiplist_bench_test.go
├── skiplist_newnode.go
├── skiplist_newnode_generate.sh
├── skiplist_set.go
├── skiplist_set_test.go
├── skiplist_test.go
├── slist.go
├── slist_test.go
├── sort.go
├── sort_test.go
├── stack.go
├── stack_test.go
├── test_helper.go
├── transform.go
├── transform_fillzero_clear.go
├── transform_fillzero_old.go
├── transform_test.go
├── types.go
├── updatedoc.bat
├── updatedoc.sh
├── vector.go
└── vector_test.go
Download .txt
SYMBOL INDEX (599 symbols across 47 files)

FILE: binary_search.go
  function LowerBound (line 8) | func LowerBound[T Ordered](a []T, value T) int {
  function LowerBoundFunc (line 32) | func LowerBoundFunc[T any](a []T, value T, less LessFn[T]) int {
  function UpperBound (line 54) | func UpperBound[T Ordered](a []T, value T) int {
  function UpperBoundFunc (line 78) | func UpperBoundFunc[T any](a []T, value T, less LessFn[T]) int {
  function BinarySearch (line 100) | func BinarySearch[T Ordered](a []T, value T) (index int, ok bool) {
  function BinarySearchFunc (line 115) | func BinarySearchFunc[T any](a []T, value T, less LessFn[T]) (index int,...

FILE: binary_search_test.go
  function TestLowerBound (line 5) | func TestLowerBound(t *testing.T) {
  function TestLowerBoundFunc (line 12) | func TestLowerBoundFunc(t *testing.T) {
  function TestUpperBound (line 19) | func TestUpperBound(t *testing.T) {
  function TestUpperBoundFunc (line 26) | func TestUpperBoundFunc(t *testing.T) {
  function TestBinarySearch (line 33) | func TestBinarySearch(t *testing.T) {
  function TestBinarySearchFunc (line 48) | func TestBinarySearchFunc(t *testing.T) {

FILE: builtin_set.go
  type BuiltinSet (line 8) | type BuiltinSet
  function SetOf (line 11) | func SetOf[K comparable](ks ...K) BuiltinSet[K] {
  method IsEmpty (line 18) | func (s BuiltinSet[K]) IsEmpty() bool {
  method Len (line 23) | func (s BuiltinSet[K]) Len() int {
  method Clear (line 28) | func (s BuiltinSet[K]) Clear() {
  method Has (line 35) | func (s BuiltinSet[K]) Has(k K) bool {
  method Insert (line 41) | func (s BuiltinSet[K]) Insert(k K) bool {
  method InsertN (line 48) | func (s BuiltinSet[K]) InsertN(ks ...K) int {
  method Remove (line 57) | func (s BuiltinSet[K]) Remove(k K) bool {
  method Delete (line 65) | func (s BuiltinSet[K]) Delete(k K) {
  method RemoveN (line 70) | func (s BuiltinSet[K]) RemoveN(ks ...K) int {
  method Keys (line 79) | func (s BuiltinSet[K]) Keys() []K {
  method ForEach (line 88) | func (s BuiltinSet[K]) ForEach(cb func(k K)) {
  method ForEachIf (line 95) | func (s BuiltinSet[K]) ForEachIf(cb func(k K) bool) {
  method String (line 104) | func (s BuiltinSet[K]) String() string {
  method Update (line 109) | func (s BuiltinSet[K]) Update(other BuiltinSet[K]) {
  method Union (line 116) | func (s BuiltinSet[K]) Union(other BuiltinSet[K]) BuiltinSet[K] {
  function orderSet (line 123) | func orderSet[K comparable](a, b BuiltinSet[K]) (small, large BuiltinSet...
  method Intersection (line 131) | func (s BuiltinSet[K]) Intersection(other BuiltinSet[K]) BuiltinSet[K] {
  method Difference (line 143) | func (s BuiltinSet[K]) Difference(other BuiltinSet[K]) BuiltinSet[K] {
  method IsDisjointOf (line 155) | func (s BuiltinSet[K]) IsDisjointOf(other BuiltinSet[K]) bool {
  method IsSubsetOf (line 166) | func (s BuiltinSet[K]) IsSubsetOf(other BuiltinSet[K]) bool {
  method IsSupersetOf (line 179) | func (s BuiltinSet[K]) IsSupersetOf(other BuiltinSet[K]) bool {

FILE: builtin_set_test.go
  function Test_BuiltinSet_Interface (line 9) | func Test_BuiltinSet_Interface(t *testing.T) {
  function Test_MakeBuiltinSet (line 14) | func Test_MakeBuiltinSet(t *testing.T) {
  function Test_MakeBuiltinSet2 (line 20) | func Test_MakeBuiltinSet2(t *testing.T) {
  function Test_SetOf (line 26) | func Test_SetOf(t *testing.T) {
  function Test_BuiltinSet_IsEmpty (line 31) | func Test_BuiltinSet_IsEmpty(t *testing.T) {
  function Test_BuiltinSet_Clear (line 38) | func Test_BuiltinSet_Clear(t *testing.T) {
  function Test_BuiltinSet_String (line 44) | func Test_BuiltinSet_String(t *testing.T) {
  function Test_BuiltinSet_Has (line 49) | func Test_BuiltinSet_Has(t *testing.T) {
  function Test_BuiltinSet_Insert (line 56) | func Test_BuiltinSet_Insert(t *testing.T) {
  function Test_BuiltinSet_InsertN (line 66) | func Test_BuiltinSet_InsertN(t *testing.T) {
  function Test_BuiltinSet_Remove (line 72) | func Test_BuiltinSet_Remove(t *testing.T) {
  function Test_BuiltinSet_Delete (line 82) | func Test_BuiltinSet_Delete(t *testing.T) {
  function Test_BuiltinSet_RemoveN (line 92) | func Test_BuiltinSet_RemoveN(t *testing.T) {
  function Test_BuiltinSet_Keys (line 99) | func Test_BuiltinSet_Keys(t *testing.T) {
  function Test_BuiltinSet_For (line 105) | func Test_BuiltinSet_For(t *testing.T) {
  function Test_BuiltinSet_ForEach (line 112) | func Test_BuiltinSet_ForEach(t *testing.T) {
  function Test_BuiltinSet_ForEachIf (line 121) | func Test_BuiltinSet_ForEachIf(t *testing.T) {
  function Test_BuiltinSet_Update (line 131) | func Test_BuiltinSet_Update(t *testing.T) {
  function Test_BuiltinSet_Union (line 138) | func Test_BuiltinSet_Union(t *testing.T) {
  function Test_BuiltinSet_Intersection (line 145) | func Test_BuiltinSet_Intersection(t *testing.T) {
  function Test_BuiltinSet_Difference (line 154) | func Test_BuiltinSet_Difference(t *testing.T) {
  function Test_BuiltinSet_IsDisjointOf (line 165) | func Test_BuiltinSet_IsDisjointOf(t *testing.T) {
  function Test_BuiltinSet_IsSubsetOf (line 172) | func Test_BuiltinSet_IsSubsetOf(t *testing.T) {
  function Test_BuiltinSet_IsSupersetOf (line 181) | func Test_BuiltinSet_IsSupersetOf(t *testing.T) {

FILE: compare.go
  function Equal (line 7) | func Equal[T comparable](a, b []T) bool {
  function Compare (line 26) | func Compare[E Ordered](a, b []E) int {

FILE: compare_test.go
  function Test_Equal (line 5) | func Test_Equal(t *testing.T) {
  function Test_Compare (line 12) | func Test_Compare(t *testing.T) {

FILE: compute.go
  function SumAs (line 6) | func SumAs[R, T Numeric](a []T) R {
  function Sum (line 32) | func Sum[T Numeric](a []T) T {
  function AverageAs (line 37) | func AverageAs[R, T Numeric](a []T) R {
  function Average (line 42) | func Average[T Numeric](a []T) T {
  function Count (line 59) | func Count[T comparable](a []T, x T) int {
  function CountIf (line 72) | func CountIf[T comparable](a []T, pred func(T) bool) int {

FILE: compute_test.go
  function Test_SumAs (line 7) | func Test_SumAs(t *testing.T) {
  function Test_Sum (line 29) | func Test_Sum(t *testing.T) {
  function Test_Average (line 34) | func Test_Average(t *testing.T) {
  function Test_AverageAs (line 39) | func Test_AverageAs(t *testing.T) {
  function Test_Average_U64 (line 44) | func Test_Average_U64(t *testing.T) {
  function Test_Average_Float (line 49) | func Test_Average_Float(t *testing.T) {
  function Test_Average_SmallType (line 54) | func Test_Average_SmallType(t *testing.T) {
  function Test_Average_UintPtr (line 59) | func Test_Average_UintPtr(t *testing.T) {
  function Test_Average_Signed (line 64) | func Test_Average_Signed(t *testing.T) {
  function Test_Count (line 69) | func Test_Count(t *testing.T) {

FILE: container.go
  type Container (line 4) | type Container interface
  type Map (line 11) | type Map interface
  type Set (line 24) | type Set interface
  type SortedMap (line 36) | type SortedMap interface
  type SortedSet (line 53) | type SortedSet interface
  type Queue (line 71) | type Queue interface
  type Deque (line 81) | type Deque interface

FILE: dlist.go
  type DList (line 6) | type DList struct
  type dListNode (line 11) | type dListNode struct
  function DListOf (line 17) | func DListOf[T any](vs ...T) DList[T] {
  method Clear (line 26) | func (l *DList[T]) Clear() {
  method Len (line 35) | func (l *DList[T]) Len() int {
  method IsEmpty (line 40) | func (l *DList[T]) IsEmpty() bool {
  method String (line 45) | func (l *DList[T]) String() string {
  type dlistIterator (line 49) | type dlistIterator struct
  method IsNotEnd (line 54) | func (it *dlistIterator[T]) IsNotEnd() bool {
  method MoveToNext (line 58) | func (it *dlistIterator[T]) MoveToNext() {
  method Value (line 62) | func (it *dlistIterator[T]) Value() T {
  method Pointer (line 66) | func (it *dlistIterator[T]) Pointer() *T {
  method Iterate (line 71) | func (l *DList[T]) Iterate() MutableIterator[T] {
  method Front (line 80) | func (l *DList[T]) Front() T {
  method Back (line 88) | func (l *DList[T]) Back() T {
  method PushFront (line 96) | func (l *DList[T]) PushFront(val T) {
  method PushBack (line 105) | func (l *DList[T]) PushBack(val T) {
  method PopFront (line 114) | func (l *DList[T]) PopFront() T {
  method PopBack (line 123) | func (l *DList[T]) PopBack() T {
  method TryPopFront (line 132) | func (l *DList[T]) TryPopFront() (T, bool) {
  method TryPopBack (line 148) | func (l *DList[T]) TryPopBack() (T, bool) {
  method ForEach (line 164) | func (l *DList[T]) ForEach(cb func(val T)) {
  method ForEachIf (line 175) | func (l *DList[T]) ForEachIf(cb func(val T) bool) {
  method ForEachMutable (line 187) | func (l *DList[T]) ForEachMutable(cb func(val *T)) {
  method ForEachMutableIf (line 198) | func (l *DList[T]) ForEachMutableIf(cb func(val *T) bool) {
  method ensureHead (line 210) | func (l *DList[T]) ensureHead() {

FILE: dlist_queue.go
  type DListQueue (line 8) | type DListQueue struct
  function NewDListQueue (line 13) | func NewDListQueue[T any]() *DListQueue[T] {
  method Len (line 19) | func (q *DListQueue[T]) Len() int {
  method IsEmpty (line 24) | func (q *DListQueue[T]) IsEmpty() bool {
  method Clear (line 29) | func (q *DListQueue[T]) Clear() {
  method String (line 34) | func (q *DListQueue[T]) String() string {
  method Front (line 39) | func (q *DListQueue[T]) Front() T {
  method Back (line 44) | func (q *DListQueue[T]) Back() T {
  method PushFront (line 49) | func (q *DListQueue[T]) PushFront(val T) {
  method PushBack (line 54) | func (q *DListQueue[T]) PushBack(val T) {
  method PopFront (line 59) | func (q *DListQueue[T]) PopFront() T {
  method PopBack (line 64) | func (q *DListQueue[T]) PopBack() T {
  method TryPopFront (line 69) | func (q *DListQueue[T]) TryPopFront() (T, bool) {
  method TryPopBack (line 74) | func (q *DListQueue[T]) TryPopBack() (T, bool) {

FILE: dlist_queue_test.go
  function Test_Queue_Interface (line 7) | func Test_Queue_Interface(t *testing.T) {
  function Test_Queue_New (line 12) | func Test_Queue_New(t *testing.T) {
  function Test_Queue_Clear (line 18) | func Test_Queue_Clear(t *testing.T) {
  function Test_Queue_String (line 26) | func Test_Queue_String(t *testing.T) {
  function Test_Queue_Front_Back (line 31) | func Test_Queue_Front_Back(t *testing.T) {
  function Test_Queue_PushFront (line 41) | func Test_Queue_PushFront(t *testing.T) {
  function Test_Queue_PushBack (line 48) | func Test_Queue_PushBack(t *testing.T) {
  function Test_Queue_TryPopFront (line 55) | func Test_Queue_TryPopFront(t *testing.T) {
  function Test_Queue_TryPopBack (line 60) | func Test_Queue_TryPopBack(t *testing.T) {
  function Test_Queue_PushFront_PopFront (line 66) | func Test_Queue_PushFront_PopFront(t *testing.T) {
  function Test_Queue_PushFront_PopBack (line 74) | func Test_Queue_PushFront_PopBack(t *testing.T) {
  function Test_Queue_PushBack_PopFront (line 80) | func Test_Queue_PushBack_PopFront(t *testing.T) {
  function Test_Queue_PushBack_PopBack (line 86) | func Test_Queue_PushBack_PopBack(t *testing.T) {

FILE: dlist_test.go
  function Test_Dlist_Interface (line 7) | func Test_Dlist_Interface(t *testing.T) {
  function Test_DList_New (line 11) | func Test_DList_New(t *testing.T) {
  function Test_DListOf (line 17) | func Test_DListOf(t *testing.T) {
  function Test_DList_String (line 23) | func Test_DList_String(t *testing.T) {
  function Test_DList_Iterate (line 28) | func Test_DList_Iterate(t *testing.T) {
  function Test_DList_Iterate_Empty (line 39) | func Test_DList_Iterate_Empty(t *testing.T) {
  function Test_DList_FrontBack (line 48) | func Test_DList_FrontBack(t *testing.T) {
  function Test_DList_PushFront (line 54) | func Test_DList_PushFront(t *testing.T) {
  function Test_DList_PushBack (line 61) | func Test_DList_PushBack(t *testing.T) {
  function Test_DList_PopFront (line 68) | func Test_DList_PopFront(t *testing.T) {
  function Test_DList_PopBack (line 86) | func Test_DList_PopBack(t *testing.T) {
  function Test_DList_PushBack_PopFront (line 104) | func Test_DList_PushBack_PopFront(t *testing.T) {
  function Test_DList_PushBack_PopBack (line 114) | func Test_DList_PushBack_PopBack(t *testing.T) {
  function Test_DList_PushFront_PopBack (line 121) | func Test_DList_PushFront_PopBack(t *testing.T) {
  function Test_DList_PushFront_PopFront (line 128) | func Test_DList_PushFront_PopFront(t *testing.T) {
  function Test_DList_ForEach (line 135) | func Test_DList_ForEach(t *testing.T) {
  function Test_DList_ForEachIf (line 146) | func Test_DList_ForEachIf(t *testing.T) {
  function Test_DList_ForEachMutable (line 156) | func Test_DList_ForEachMutable(t *testing.T) {
  function Test_DList_ForEachMutableIf (line 172) | func Test_DList_ForEachMutableIf(t *testing.T) {
  function Test_DList_ForEach_EmptyOK (line 182) | func Test_DList_ForEach_EmptyOK(t *testing.T) {
  function Benchmark_DList_Iterate (line 190) | func Benchmark_DList_Iterate(b *testing.B) {

FILE: functor.go
  function Less (line 4) | func Less[T Ordered](a, b T) bool {
  function Greater (line 9) | func Greater[T Ordered](a, b T) bool {
  function OrderedCompare (line 14) | func OrderedCompare[T Ordered](a, b T) int {

FILE: generate.go
  function Range (line 7) | func Range[T Numeric](first, last T) []T {
  function Generate (line 18) | func Generate[T any](a []T, gen func() T) {

FILE: generate_test.go
  function Test_Range (line 5) | func Test_Range(t *testing.T) {
  function Test_Generate (line 12) | func Test_Generate(t *testing.T) {

FILE: heap.go
  function MakeMinHeap (line 8) | func MakeMinHeap[T Ordered](array []T) {
  function IsMinHeap (line 19) | func IsMinHeap[T Ordered](array []T) bool {
  function PushMinHeap (line 36) | func PushMinHeap[T Ordered](heap *[]T, v T) {
  function PopMinHeap (line 44) | func PopMinHeap[T Ordered](heap *[]T) T {
  function RemoveMinHeap (line 56) | func RemoveMinHeap[T Ordered](heap *[]T, i int) T {
  function heapSwap (line 69) | func heapSwap[T any](heap []T, i, j int) {
  function heapUp (line 73) | func heapUp[T Ordered](heap []T, j int) {
  function heapDown (line 84) | func heapDown[T Ordered](heap []T, i0, n int) bool {
  function MakeHeapFunc (line 107) | func MakeHeapFunc[T any](array []T, less LessFn[T]) {
  function IsHeapFunc (line 118) | func IsHeapFunc[T any](array []T, less LessFn[T]) bool {
  function PushHeapFunc (line 136) | func PushHeapFunc[T any](heap *[]T, v T, less LessFn[T]) {
  function PopHeapFunc (line 144) | func PopHeapFunc[T any](heap *[]T, less LessFn[T]) T {
  function RemoveHeapFunc (line 156) | func RemoveHeapFunc[T any](heap *[]T, i int, less LessFn[T]) T {
  function heapUpFunc (line 169) | func heapUpFunc[T any](heap []T, j int, less LessFn[T]) {
  function heapDownFunc (line 180) | func heapDownFunc[T any](heap []T, i0, n int, less LessFn[T]) bool {

FILE: heap_bench_test.go
  type intHeap (line 9) | type intHeap
    method Len (line 11) | func (h intHeap) Len() int           { return len(h) }
    method Less (line 12) | func (h intHeap) Less(i, j int) bool { return h[i] < h[j] }
    method Swap (line 13) | func (h intHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
    method Push (line 14) | func (h *intHeap) Push(x any)        { *h = append(*h, x.(int)) }
    method Pop (line 16) | func (h *intHeap) Pop() any {
  function BenchmarkHeapInit (line 24) | func BenchmarkHeapInit(b *testing.B) {
  function BenchmarkHeapPush (line 51) | func BenchmarkHeapPush(b *testing.B) {
  function BenchmarkHeapPop (line 82) | func BenchmarkHeapPop(b *testing.B) {

FILE: heap_test.go
  function TestMakeMinHeap (line 7) | func TestMakeMinHeap(t *testing.T) {
  function TestIsMinHeap (line 14) | func TestIsMinHeap(t *testing.T) {
  function TestMakeHeapFunc (line 21) | func TestMakeHeapFunc(t *testing.T) {
  function Test_MinHeap_PushPop (line 28) | func Test_MinHeap_PushPop(t *testing.T) {
  function Test_HeapFunc_PushPop (line 35) | func Test_HeapFunc_PushPop(t *testing.T) {
  function Test_MinHeap_Remove (line 44) | func Test_MinHeap_Remove(t *testing.T) {
  function Test_HeapFunc_Remove (line 51) | func Test_HeapFunc_Remove(t *testing.T) {

FILE: helper.go
  function nameOfType (line 8) | func nameOfType[T any]() string {

FILE: iterator.go
  type Iterator (line 4) | type Iterator interface
  type MutableIterator (line 11) | type MutableIterator interface
  type MapIterator (line 17) | type MapIterator interface
  type MutableMapIterator (line 23) | type MutableMapIterator interface

FILE: lookup.go
  function Max (line 6) | func Max[T Ordered](a, b T) T {
  function Min (line 16) | func Min[T Ordered](a, b T) T {
  function MaxN (line 26) | func MaxN[T Ordered](a ...T) T {
  function MinN (line 42) | func MinN[T Ordered](a ...T) T {
  function MinMax (line 58) | func MinMax[T Ordered](a, b T) (min, max T) {
  function MinMaxN (line 68) | func MinMaxN[T Ordered](a ...T) (min, max T) {
  function Find (line 90) | func Find[T comparable](a []T, x T) (index int, ok bool) {
  function FindIf (line 104) | func FindIf[T any](a []T, cond func(T) bool) (index int, ok bool) {
  function Index (line 118) | func Index[T comparable](a []T, x T) int {
  function AllOf (line 130) | func AllOf[T any](a []T, pred func(T) bool) bool {
  function AnyOf (line 142) | func AnyOf[T any](a []T, pred func(T) bool) bool {
  function NoneOf (line 154) | func NoneOf[T any](a []T, pred func(T) bool) bool {

FILE: lookup_test.go
  function Test_Min (line 5) | func Test_Min(t *testing.T) {
  function Test_Max (line 12) | func Test_Max(t *testing.T) {
  function Test_MinN (line 19) | func Test_MinN(t *testing.T) {
  function Test_MaxN (line 27) | func Test_MaxN(t *testing.T) {
  function Test_MinMax (line 35) | func Test_MinMax(t *testing.T) {
  function Test_MinMaxN (line 44) | func Test_MinMaxN(t *testing.T) {
  function Test_Find (line 51) | func Test_Find(t *testing.T) {
  function Test_FindIf (line 60) | func Test_FindIf(t *testing.T) {
  function Test_Index (line 70) | func Test_Index(t *testing.T) {
  function isNegative (line 82) | func isNegative(n int) bool { return n < 0 }
  function Test_AllOf (line 84) | func Test_AllOf(t *testing.T) {
  function Test_AnyOf (line 90) | func Test_AnyOf(t *testing.T) {
  function Test_NoneOf (line 96) | func Test_NoneOf(t *testing.T) {

FILE: pool.go
  type Pool (line 6) | type Pool
  function MakePool (line 9) | func MakePool[T any]() Pool[T] {
  function MakePoolWithNew (line 14) | func MakePoolWithNew[T any](new func() *T) Pool[T] {
  method Get (line 22) | func (pool *Pool[T]) Get() *T {
  method Put (line 31) | func (pool *Pool[T]) Put(x *T) {
  method untyped (line 37) | func (pool *Pool[T]) untyped() *sync.Pool {

FILE: pool_test.go
  function TestPool (line 5) | func TestPool(t *testing.T) {
  function TestMakePoolWithNew (line 11) | func TestMakePoolWithNew(t *testing.T) {
  function TestMakePoolNil (line 17) | func TestMakePoolNil(t *testing.T) {

FILE: priority_queue.go
  type PriorityQueue (line 6) | type PriorityQueue struct
  function NewPriorityQueue (line 12) | func NewPriorityQueue[T Ordered]() *PriorityQueue[T] {
  function NewPriorityQueueOn (line 20) | func NewPriorityQueueOn[T Ordered](slice []T) *PriorityQueue[T] {
  function NewPriorityQueueOf (line 29) | func NewPriorityQueueOf[T Ordered](elements ...T) *PriorityQueue[T] {
  function NewPriorityQueueFunc (line 34) | func NewPriorityQueueFunc[T any](less LessFn[T]) *PriorityQueue[T] {
  method Len (line 42) | func (pq *PriorityQueue[T]) Len() int {
  method IsEmpty (line 47) | func (pq *PriorityQueue[T]) IsEmpty() bool {
  method Clear (line 52) | func (pq *PriorityQueue[T]) Clear() {
  method Top (line 57) | func (pq *PriorityQueue[T]) Top() T {
  method Push (line 62) | func (pq *PriorityQueue[T]) Push(v T) {
  method Pop (line 67) | func (pq *PriorityQueue[T]) Pop() T {
  type pqImpl (line 71) | type pqImpl interface
  type pqOrdered (line 76) | type pqOrdered struct
  method Push (line 80) | func (pq *pqOrdered[T]) Push(v T) {
  method Pop (line 84) | func (pq *pqOrdered[T]) Pop() T {
  type pqFunc (line 89) | type pqFunc struct
  method Push (line 94) | func (pq *pqFunc[T]) Push(v T) {
  method Pop (line 98) | func (pq *pqFunc[T]) Pop() T {

FILE: priority_queue_test.go
  function TestInterface (line 8) | func TestInterface(t *testing.T) {
  function TestNewPriorityQueue (line 12) | func TestNewPriorityQueue(t *testing.T) {
  function TestNewPriorityQueueOf (line 18) | func TestNewPriorityQueueOf(t *testing.T) {
  function TestPriorityQueue_PushPop (line 23) | func TestPriorityQueue_PushPop(t *testing.T) {
  function TestPriorityQueueFunc_PushPop (line 39) | func TestPriorityQueueFunc_PushPop(t *testing.T) {
  function TestPriorityQueue_Clear (line 53) | func TestPriorityQueue_Clear(t *testing.T) {
  function ExamplePriorityQueue (line 66) | func ExamplePriorityQueue() {

FILE: skiplist.go
  constant skipListMaxLevel (line 20) | skipListMaxLevel = 40
  type SkipList (line 28) | type SkipList struct
  function NewSkipList (line 40) | func NewSkipList[K Ordered, V any]() *SkipList[K, V] {
  function NewSkipListFromMap (line 48) | func NewSkipListFromMap[K Ordered, V any](m map[K]V) *SkipList[K, V] {
  function NewSkipListFunc (line 57) | func NewSkipListFunc[K any, V any](keyCmp CompareFn[K]) *SkipList[K, V] {
  method IsEmpty (line 66) | func (sl *SkipList[K, V]) IsEmpty() bool {
  method Len (line 71) | func (sl *SkipList[K, V]) Len() int {
  method Clear (line 76) | func (sl *SkipList[K, V]) Clear() {
  method Iterate (line 85) | func (sl *SkipList[K, V]) Iterate() MutableMapIterator[K, V] {
  method Insert (line 91) | func (sl *SkipList[K, V]) Insert(key K, value V) {
  method Find (line 122) | func (sl *SkipList[K, V]) Find(key K) *V {
  method Has (line 131) | func (sl *SkipList[K, V]) Has(key K) bool {
  method LowerBound (line 138) | func (sl *SkipList[K, V]) LowerBound(key K) MutableMapIterator[K, V] {
  method UpperBound (line 145) | func (sl *SkipList[K, V]) UpperBound(key K) MutableMapIterator[K, V] {
  method FindRange (line 150) | func (sl *SkipList[K, V]) FindRange(first, last K) MutableMapIterator[K,...
  method Remove (line 156) | func (sl *SkipList[K, V]) Remove(key K) bool {
  method ForEach (line 173) | func (sl *SkipList[K, V]) ForEach(op func(K, V)) {
  method ForEachMutable (line 180) | func (sl *SkipList[K, V]) ForEachMutable(op func(K, *V)) {
  method ForEachIf (line 187) | func (sl *SkipList[K, V]) ForEachIf(op func(K, V) bool) {
  method ForEachMutableIf (line 196) | func (sl *SkipList[K, V]) ForEachMutableIf(op func(K, *V) bool) {
  type skipListNode (line 206) | type skipListNode struct
  type skipListIterator (line 215) | type skipListIterator struct
  method IsNotEnd (line 219) | func (it *skipListIterator[K, V]) IsNotEnd() bool {
  method MoveToNext (line 223) | func (it *skipListIterator[K, V]) MoveToNext() {
  method Key (line 227) | func (it *skipListIterator[K, V]) Key() K {
  method Value (line 231) | func (it *skipListIterator[K, V]) Value() V {
  method Pointer (line 235) | func (it *skipListIterator[K, V]) Pointer() *V {
  type skipListImpl (line 245) | type skipListImpl interface
  method init (line 253) | func (sl *SkipList[K, V]) init() {
  method randomLevel (line 261) | func (sl *SkipList[K, V]) randomLevel() int {
  type skipListOrdered (line 280) | type skipListOrdered struct
  method findNode (line 284) | func (sl *skipListOrdered[K, V]) findNode(key K) *skipListNode[K, V] {
  method doFindNode (line 288) | func (sl *skipListOrdered[K, V]) doFindNode(key K, eq bool) *skipListNod...
  method lowerBound (line 312) | func (sl *skipListOrdered[K, V]) lowerBound(key K) *skipListNode[K, V] {
  method upperBound (line 316) | func (sl *skipListOrdered[K, V]) upperBound(key K) *skipListNode[K, V] {
  method findInsertPoint (line 326) | func (sl *skipListOrdered[K, V]) findInsertPoint(key K) (*skipListNode[K...
  method findRemovePoint (line 349) | func (sl *skipListOrdered[K, V]) findRemovePoint(key K) (*skipListNode[K...
  method findPrevNodes (line 358) | func (sl *skipListOrdered[K, V]) findPrevNodes(key K) []*skipListNode[K,...
  type skipListFunc (line 376) | type skipListFunc struct
  method findNode (line 381) | func (sl *skipListFunc[K, V]) findNode(key K) *skipListNode[K, V] {
  method lowerBound (line 389) | func (sl *skipListFunc[K, V]) lowerBound(key K) *skipListNode[K, V] {
  method upperBound (line 407) | func (sl *skipListFunc[K, V]) upperBound(key K) *skipListNode[K, V] {
  method findInsertPoint (line 417) | func (sl *skipListFunc[K, V]) findInsertPoint(key K) (*skipListNode[K, V...
  method findRemovePoint (line 441) | func (sl *skipListFunc[K, V]) findRemovePoint(key K) (*skipListNode[K, V...
  method findPrevNodes (line 450) | func (sl *skipListFunc[K, V]) findPrevNodes(key K) []*skipListNode[K, V] {

FILE: skiplist_bench_test.go
  constant benchInitSize (line 9) | benchInitSize  = 1000000
  constant benchBatchSize (line 10) | benchBatchSize = 10
  function newMapN (line 13) | func newMapN(n int) map[int]int {
  function BenchmarkSkipList_Iterate (line 21) | func BenchmarkSkipList_Iterate(b *testing.B) {
  function BenchmarkSkipList_Insert (line 31) | func BenchmarkSkipList_Insert(b *testing.B) {
  function BenchmarkMap_Insert (line 43) | func BenchmarkMap_Insert(b *testing.B) {
  function BenchmarkSkipList_Insert_Dup (line 55) | func BenchmarkSkipList_Insert_Dup(b *testing.B) {
  function BenchmarkMap_Insert_Dup (line 65) | func BenchmarkMap_Insert_Dup(b *testing.B) {
  function BenchmarkMap_Find (line 75) | func BenchmarkMap_Find(b *testing.B) {
  function BenchmarkSkipList_Find (line 85) | func BenchmarkSkipList_Find(b *testing.B) {
  function BenchmarkSkipListString (line 111) | func BenchmarkSkipListString(b *testing.B) {

FILE: skiplist_newnode.go
  function newSkipListNode (line 7) | func newSkipListNode[K any, V any](level int, key K, value V) *skipListN...

FILE: skiplist_set.go
  type SkipListSet (line 4) | type SkipListSet
  function NewSkipListSet (line 7) | func NewSkipListSet[K Ordered]() *SkipListSet[K] {
  function NewSkipListSetFunc (line 12) | func NewSkipListSetFunc[K any](cmp CompareFn[K]) *SkipListSet[K] {
  function NewSkipListSetOf (line 17) | func NewSkipListSetOf[K Ordered](elements ...K) *SkipListSet[K] {
  method IsEmpty (line 26) | func (s *SkipListSet[K]) IsEmpty() bool {
  method Len (line 31) | func (s *SkipListSet[K]) Len() int {
  method Clear (line 36) | func (s *SkipListSet[K]) Clear() {
  method Has (line 41) | func (s *SkipListSet[K]) Has(key K) bool {
  method Insert (line 46) | func (s *SkipListSet[K]) Insert(key K) bool {
  method InsertN (line 53) | func (s *SkipListSet[K]) InsertN(keys ...K) int {
  method Remove (line 62) | func (s *SkipListSet[K]) Remove(key K) bool {
  method RemoveN (line 67) | func (s *SkipListSet[K]) RemoveN(keys ...K) int {
  method Keys (line 76) | func (s *SkipListSet[K]) Keys() []K {
  method ForEach (line 83) | func (s *SkipListSet[K]) ForEach(f func(K)) {
  method ForEachIf (line 88) | func (s *SkipListSet[K]) ForEachIf(f func(K) bool) {
  method LowerBound (line 93) | func (s *SkipListSet[K]) LowerBound(key K) Iterator[K] {
  method UpperBound (line 98) | func (s *SkipListSet[K]) UpperBound(key K) Iterator[K] {
  method FindRange (line 103) | func (s *SkipListSet[K]) FindRange(first, last K) Iterator[K] {
  method asMap (line 108) | func (s *SkipListSet[K]) asMap() *SkipList[K, struct{}] {
  type skipListSetIterator (line 112) | type skipListSetIterator
  method IsNotEnd (line 114) | func (it *skipListSetIterator[K]) IsNotEnd() bool {
  method MoveToNext (line 118) | func (it *skipListSetIterator[K]) MoveToNext() {
  method Value (line 122) | func (it *skipListSetIterator[K]) Value() K {

FILE: skiplist_set_test.go
  function TestNewSkipList_Interface (line 7) | func TestNewSkipList_Interface(t *testing.T) {
  function TestNewSkipListSet (line 12) | func TestNewSkipListSet(t *testing.T) {
  function TestNewSkipListSetOf (line 18) | func TestNewSkipListSetOf(t *testing.T) {
  function TestNewSkipListSetFunc (line 23) | func TestNewSkipListSetFunc(t *testing.T) {
  function TestNewSkipListSet_Insert_Remove_Has (line 29) | func TestNewSkipListSet_Insert_Remove_Has(t *testing.T) {
  function TestNewSkipListSet_Clear (line 49) | func TestNewSkipListSet_Clear(t *testing.T) {
  function TestNewSkipListSet_InsertN (line 56) | func TestNewSkipListSet_InsertN(t *testing.T) {
  function TestNewSkipListSet_RemoveN (line 63) | func TestNewSkipListSet_RemoveN(t *testing.T) {
  function TestNewSkipListSet_ForEach (line 71) | func TestNewSkipListSet_ForEach(t *testing.T) {
  function TestNewSkipListSet_ForEachIf (line 78) | func TestNewSkipListSet_ForEachIf(t *testing.T) {
  function TestNewSkipList_Iterate (line 85) | func TestNewSkipList_Iterate(t *testing.T) {
  function TestSkipListSet_Iterater (line 96) | func TestSkipListSet_Iterater(t *testing.T) {

FILE: skiplist_test.go
  function TestSkipList_Interface (line 8) | func TestSkipList_Interface(t *testing.T) {
  function TestNewSkipListString (line 16) | func TestNewSkipListString(t *testing.T) {
  function testNewSkipListType (line 25) | func testNewSkipListType[T Numeric](t *testing.T) {
  function TestNewSkipListInt8 (line 35) | func TestNewSkipListInt8(t *testing.T)  { testNewSkipListType[int8](t) }
  function TestNewSkipListInt16 (line 36) | func TestNewSkipListInt16(t *testing.T) { testNewSkipListType[int16](t) }
  function TestNewSkipListInt32 (line 37) | func TestNewSkipListInt32(t *testing.T) { testNewSkipListType[int32](t) }
  function TestNewSkipListInt64 (line 38) | func TestNewSkipListInt64(t *testing.T) { testNewSkipListType[int64](t) }
  function TestNewSkipListUInt8 (line 40) | func TestNewSkipListUInt8(t *testing.T)  { testNewSkipListType[uint8](t) }
  function TestNewSkipListUInt16 (line 41) | func TestNewSkipListUInt16(t *testing.T) { testNewSkipListType[uint16](t) }
  function TestNewSkipListUInt32 (line 42) | func TestNewSkipListUInt32(t *testing.T) { testNewSkipListType[uint32](t) }
  function TestNewSkipListUInt64 (line 43) | func TestNewSkipListUInt64(t *testing.T) { testNewSkipListType[uint64](t) }
  function TestNewSkipListUIntPtr (line 45) | func TestNewSkipListUIntPtr(t *testing.T) { testNewSkipListType[uintptr]...
  function TestNewSkipListFloat32 (line 47) | func TestNewSkipListFloat32(t *testing.T) { testNewSkipListType[float32]...
  function TestNewSkipListFloat64 (line 48) | func TestNewSkipListFloat64(t *testing.T) { testNewSkipListType[float64]...
  function TestNewSkipListFunc (line 50) | func TestNewSkipListFunc(t *testing.T) {
  function TestNewSkipListFromMap (line 88) | func TestNewSkipListFromMap(t *testing.T) {
  function TestSkipList_Iterate (line 96) | func TestSkipList_Iterate(t *testing.T) {
  function testSkipListIterater (line 107) | func testSkipListIterater(t *testing.T, sl *SkipList[int, int]) {
  function TestSkipList_Iterater (line 131) | func TestSkipList_Iterater(t *testing.T) {
  function TestSkipList_Func_Iterater (line 136) | func TestSkipList_Func_Iterater(t *testing.T) {
  function TestSkipList_Insert (line 144) | func TestSkipList_Insert(t *testing.T) {
  function TestSkipList_Insert_Reverse (line 153) | func TestSkipList_Insert_Reverse(t *testing.T) {
  function TestSkipList_Insert_Dup (line 162) | func TestSkipList_Insert_Dup(t *testing.T) {
  function newSkipListN (line 170) | func newSkipListN(n int) *SkipList[int, int] {
  function TestSkipList_Remove (line 179) | func TestSkipList_Remove(t *testing.T) {
  function TestSkipList_Remove_Nonexist (line 188) | func TestSkipList_Remove_Nonexist(t *testing.T) {
  function TestSkipList_Remove_Level (line 197) | func TestSkipList_Remove_Level(t *testing.T) {
  function TestSkipList_Clean (line 206) | func TestSkipList_Clean(t *testing.T) {
  function TestSkipList_level (line 218) | func TestSkipList_level(t *testing.T) {
  function TestSkipList_newnode (line 230) | func TestSkipList_newnode(t *testing.T) {
  function TestSkipList_Find (line 239) | func TestSkipList_Find(t *testing.T) {
  function TestSkipList_Has (line 248) | func TestSkipList_Has(t *testing.T) {
  function TestSkipList_ForEach (line 255) | func TestSkipList_ForEach(t *testing.T) {
  function TestSkipList_ForEachIf (line 265) | func TestSkipList_ForEachIf(t *testing.T) {
  function TestSkipList_ForEachMutable (line 278) | func TestSkipList_ForEachMutable(t *testing.T) {
  function TestSkipList_ForEachMutableIf (line 288) | func TestSkipList_ForEachMutableIf(t *testing.T) {

FILE: slist.go
  type SList (line 4) | type SList struct
  type sListNode (line 10) | type sListNode struct
  function SListOf (line 16) | func SListOf[T any](values ...T) SList[T] {
  method IsEmpty (line 25) | func (l *SList[T]) IsEmpty() bool {
  method Len (line 30) | func (l *SList[T]) Len() int {
  method Clear (line 35) | func (l *SList[T]) Clear() {
  method Front (line 42) | func (l *SList[T]) Front() T {
  method Back (line 50) | func (l *SList[T]) Back() T {
  method PushFront (line 58) | func (l *SList[T]) PushFront(v T) {
  method PushBack (line 68) | func (l *SList[T]) PushBack(v T) {
  method PopFront (line 82) | func (l *SList[T]) PopFront() T {
  method Reverse (line 97) | func (l *SList[T]) Reverse() {
  method Values (line 113) | func (l *SList[T]) Values() []T {
  method ForEach (line 134) | func (l *SList[T]) ForEach(cb func(T)) {
  method ForEachIf (line 142) | func (l *SList[T]) ForEachIf(cb func(T) bool) {
  method ForEachMutable (line 151) | func (l *SList[T]) ForEachMutable(cb func(*T)) {
  method ForEachMutableIf (line 159) | func (l *SList[T]) ForEachMutableIf(cb func(*T) bool) {
  method Iterate (line 168) | func (l *SList[T]) Iterate() MutableIterator[T] {
  type sListIterator (line 173) | type sListIterator struct
  method IsNotEnd (line 177) | func (it *sListIterator[T]) IsNotEnd() bool {
  method MoveToNext (line 181) | func (it *sListIterator[T]) MoveToNext() {
  method Value (line 185) | func (it *sListIterator[T]) Value() T {
  method Pointer (line 189) | func (it *sListIterator[T]) Pointer() *T {

FILE: slist_test.go
  function Test_SList_Interface (line 7) | func Test_SList_Interface(t *testing.T) {
  function Test_SList_Clean (line 12) | func Test_SList_Clean(t *testing.T) {
  function Test_SList_Front (line 20) | func Test_SList_Front(t *testing.T) {
  function Test_SList_Back (line 39) | func Test_SList_Back(t *testing.T) {
  function Test_SList_PushFront (line 58) | func Test_SList_PushFront(t *testing.T) {
  function Test_SList_PushBack (line 67) | func Test_SList_PushBack(t *testing.T) {
  function Test_SList_PopFront (line 77) | func Test_SList_PopFront(t *testing.T) {
  function Test_SList_Reverse (line 88) | func Test_SList_Reverse(t *testing.T) {
  function Test_SList_ForEach (line 94) | func Test_SList_ForEach(t *testing.T) {
  function Test_SList_ForEachIf (line 104) | func Test_SList_ForEachIf(t *testing.T) {
  function Test_SList_ForEachMutable (line 115) | func Test_SList_ForEachMutable(t *testing.T) {
  function Test_SList_ForEachMutableIf (line 129) | func Test_SList_ForEachMutableIf(t *testing.T) {
  function Test_SList_Iterate (line 140) | func Test_SList_Iterate(t *testing.T) {

FILE: sort.go
  function IsSorted (line 10) | func IsSorted[T Ordered](a []T) bool {
  function IsDescSorted (line 27) | func IsDescSorted[T Ordered](a []T) bool {
  type ascSlice (line 41) | type ascSlice
  method Len (line 43) | func (x ascSlice[T]) Len() int           { return len(x) }
  method Less (line 44) | func (x ascSlice[T]) Less(i, j int) bool { return x[i] < x[j] }
  method Swap (line 45) | func (x ascSlice[T]) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
  function Sort (line 51) | func Sort[T Ordered](a []T) {
  function StableSort (line 59) | func StableSort[T Ordered](a []T) {
  type descSlice (line 63) | type descSlice
  method Len (line 65) | func (x descSlice[T]) Len() int           { return len(x) }
  method Less (line 66) | func (x descSlice[T]) Less(i, j int) bool { return x[i] > x[j] }
  method Swap (line 67) | func (x descSlice[T]) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
  function DescSort (line 73) | func DescSort[T Ordered](a []T) {
  function DescStableSort (line 81) | func DescStableSort[T Ordered](a []T) {
  type funcSortable (line 85) | type funcSortable struct
  method Len (line 90) | func (x funcSortable[T]) Len() int           { return len(x.e) }
  method Less (line 91) | func (x funcSortable[T]) Less(i, j int) bool { return x.less(x.e[i], x.e...
  method Swap (line 92) | func (x funcSortable[T]) Swap(i, j int)      { x.e[i], x.e[j] = x.e[j], ...
  function SortFunc (line 98) | func SortFunc[T any](a []T, less func(x, y T) bool) {
  function StableSortFunc (line 106) | func StableSortFunc[T any](a []T, less func(x, y T) bool) {

FILE: sort_test.go
  function Test_IsSorted (line 7) | func Test_IsSorted(t *testing.T) {
  function Test_IsDescSorted (line 14) | func Test_IsDescSorted(t *testing.T) {
  function Test_Sort (line 21) | func Test_Sort(t *testing.T) {
  function Test_DescSort (line 27) | func Test_DescSort(t *testing.T) {
  function Test_StableSort (line 33) | func Test_StableSort(t *testing.T) {
  function Test_DescStableSort (line 39) | func Test_DescStableSort(t *testing.T) {
  function greater (line 45) | func greater(x, y int) bool { return x > y }
  function Test_SortFunc (line 47) | func Test_SortFunc(t *testing.T) {
  function Test_StableSortFunc (line 53) | func Test_StableSortFunc(t *testing.T) {

FILE: stack.go
  type Stack (line 5) | type Stack struct
  function NewStack (line 10) | func NewStack[T any]() *Stack[T] {
  function NewStackCap (line 15) | func NewStackCap[T any](capicity int) *Stack[T] {
  method IsEmpty (line 20) | func (s Stack[T]) IsEmpty() bool {
  method Len (line 25) | func (s Stack[T]) Len() int {
  method Cap (line 30) | func (s Stack[T]) Cap() int {
  method Clear (line 35) | func (s *Stack[T]) Clear() {
  method Push (line 40) | func (s *Stack[T]) Push(t T) {
  method TryPop (line 45) | func (s *Stack[T]) TryPop() (val T, ok bool) {
  method Pop (line 58) | func (s *Stack[T]) Pop() T {
  method Top (line 67) | func (s Stack[T]) Top() T {

FILE: stack_test.go
  function Test_Stack_Interface (line 7) | func Test_Stack_Interface(t *testing.T) {
  function Test_NewStack (line 10) | func Test_NewStack(t *testing.T) {
  function Test_NewStackCap (line 17) | func Test_NewStackCap(t *testing.T) {
  function Test_StackCap (line 23) | func Test_StackCap(t *testing.T) {
  function Test_Stack_Clear (line 30) | func Test_Stack_Clear(t *testing.T) {
  function Test_Stack_Push (line 39) | func Test_Stack_Push(t *testing.T) {
  function Test_Stack_TryPop (line 47) | func Test_Stack_TryPop(t *testing.T) {
  function Test_Stack_Pop (line 57) | func Test_Stack_Pop(t *testing.T) {
  function Test_Stack_Top (line 65) | func Test_Stack_Top(t *testing.T) {

FILE: test_helper.go
  function report (line 8) | func report(t *testing.T, msg string) {
  function reportMismatch (line 13) | func reportMismatch[T comparable](t *testing.T, a T, op string, b T) {
  function expectEq (line 18) | func expectEq[T comparable](t *testing.T, a, b T) {
  function expectNe (line 25) | func expectNe[T comparable](t *testing.T, a, b T) {
  function expectLt (line 32) | func expectLt[T Ordered](t *testing.T, a, b T) {
  function expectGt (line 39) | func expectGt[T Ordered](t *testing.T, a, b T) {
  function expectLe (line 46) | func expectLe[T Ordered](t *testing.T, a, b T) {
  function expectGe (line 53) | func expectGe[T Ordered](t *testing.T, a, b T) {
  function expectTrue (line 60) | func expectTrue(t *testing.T, actual bool) {
  function expectFalse (line 67) | func expectFalse(t *testing.T, actual bool) {
  function expectPanic (line 74) | func expectPanic(t *testing.T, f func()) {

FILE: transform.go
  function Copy (line 8) | func Copy[T any](a []T) []T {
  function CopyTo (line 16) | func CopyTo[T any](a []T, to []T) []T {
  function Fill (line 24) | func Fill[T any](a []T, v T) {
  function FillPattern (line 42) | func FillPattern[T any](a []T, pattern []T) {
  function TransformTo (line 60) | func TransformTo[R any, T any](a []T, op func(T) R, b []R) []R {
  function Transform (line 71) | func Transform[T any](a []T, op func(T) T) {
  function TransformCopy (line 80) | func TransformCopy[R any, T any](a []T, op func(T) R) []R {
  function Replace (line 91) | func Replace[T comparable](a []T, old, new T) {
  function ReplaceIf (line 102) | func ReplaceIf[T any](a []T, pred func(v T) bool, new T) {
  function Unique (line 114) | func Unique[T comparable](a []T) []T {
  function UniqueCopy (line 134) | func UniqueCopy[T comparable](a []T) []T {
  function Remove (line 154) | func Remove[T comparable](a []T, x T) []T {
  function RemoveCopy (line 169) | func RemoveCopy[T comparable](a []T, x T) []T {
  function RemoveIf (line 183) | func RemoveIf[T any](a []T, cond func(T) bool) []T {
  function RemoveIfCopy (line 198) | func RemoveIfCopy[T any](a []T, cond func(T) bool) []T {
  function Shuffle (line 211) | func Shuffle[T any](a []T) {
  function Reverse (line 220) | func Reverse[T any](a []T) {
  function ReverseCopy (line 229) | func ReverseCopy[T any](a []T) []T {

FILE: transform_fillzero_clear.go
  function FillZero (line 9) | func FillZero[T any](a []T) {

FILE: transform_fillzero_old.go
  function FillZero (line 9) | func FillZero[T any](a []T) {

FILE: transform_test.go
  function Test_Copy (line 12) | func Test_Copy(t *testing.T) {
  function Test_CopyTo (line 18) | func Test_CopyTo(t *testing.T) {
  function Test_Fill (line 27) | func Test_Fill(t *testing.T) {
  function Test_FillZero (line 36) | func Test_FillZero(t *testing.T) {
  function naiveFill (line 42) | func naiveFill[T any](a []T, v T) {
  function BenchmarkFill (line 48) | func BenchmarkFill(b *testing.B) {
  function Test_FillPattern (line 62) | func Test_FillPattern(t *testing.T) {
  function Test_Transform (line 70) | func Test_Transform(t *testing.T) {
  function Test_TransformTo (line 78) | func Test_TransformTo(t *testing.T) {
  function Test_TransformCopy (line 92) | func Test_TransformCopy(t *testing.T) {
  function Test_Replace (line 100) | func Test_Replace(t *testing.T) {
  function Test_ReplaceIf (line 106) | func Test_ReplaceIf(t *testing.T) {
  function Test_Unique (line 112) | func Test_Unique(t *testing.T) {
  function Test_UniqueCopy (line 120) | func Test_UniqueCopy(t *testing.T) {
  function Test_Remove (line 129) | func Test_Remove(t *testing.T) {
  function Test_RemoveCopy (line 136) | func Test_RemoveCopy(t *testing.T) {
  function Test_RemoveIf (line 144) | func Test_RemoveIf(t *testing.T) {
  function Test_RemoveIfCopy (line 151) | func Test_RemoveIfCopy(t *testing.T) {
  function Test_Shuffle (line 159) | func Test_Shuffle(t *testing.T) {
  function Test_Reverse (line 164) | func Test_Reverse(t *testing.T) {
  function Test_Reverse_Odd (line 170) | func Test_Reverse_Odd(t *testing.T) {
  function Test_ReverseCopy (line 176) | func Test_ReverseCopy(t *testing.T) {

FILE: types.go
  type Signed (line 6) | type Signed interface
  type Unsigned (line 13) | type Unsigned interface
  type Integer (line 20) | type Integer interface
  type Float (line 27) | type Float interface
  type Ordered (line 35) | type Ordered interface
  type Numeric (line 40) | type Numeric interface
  type LessFn (line 45) | type LessFn
  type CompareFn (line 51) | type CompareFn
  type HashFn (line 54) | type HashFn

FILE: vector.go
  type Vector (line 7) | type Vector
  function MakeVector (line 10) | func MakeVector[T any]() Vector[T] {
  function MakeVectorCap (line 15) | func MakeVectorCap[T any](c int) Vector[T] {
  function VectorOf (line 21) | func VectorOf[T any](v ...T) Vector[T] {
  function AsVector (line 26) | func AsVector[T any](s []T) Vector[T] {
  method IsEmpty (line 31) | func (v *Vector[T]) IsEmpty() bool {
  method Len (line 36) | func (v *Vector[T]) Len() int {
  method Cap (line 41) | func (v *Vector[T]) Cap() int {
  method Clear (line 47) | func (v *Vector[T]) Clear() {
  method Reserve (line 58) | func (v *Vector[T]) Reserve(l int) {
  method Shrink (line 67) | func (v *Vector[T]) Shrink() {
  method At (line 75) | func (v *Vector[T]) At(i int) T {
  method Set (line 81) | func (v *Vector[T]) Set(i int, x T) {
  method PushBack (line 88) | func (v *Vector[T]) PushBack(x T) {
  method PopBack (line 95) | func (v *Vector[T]) PopBack() T {
  method TryPopBack (line 104) | func (v *Vector[T]) TryPopBack() (T, bool) {
  method Back (line 115) | func (v Vector[T]) Back() T {
  method Append (line 120) | func (v *Vector[T]) Append(x ...T) {
  method Insert (line 129) | func (v *Vector[T]) Insert(i int, x ...T) {
  method Remove (line 149) | func (v *Vector[T]) Remove(i int) {
  method RemoveRange (line 154) | func (v *Vector[T]) RemoveRange(i, j int) {
  method RemoveLength (line 161) | func (v *Vector[T]) RemoveLength(i int, len int) {
  method RemoveIf (line 166) | func (v *Vector[T]) RemoveIf(cond func(T) bool) {
  method ForEach (line 173) | func (v Vector[T]) ForEach(cb func(val T)) {
  method ForEachIf (line 181) | func (v Vector[T]) ForEachIf(cb func(val T) bool) {
  method ForEachMutable (line 190) | func (v Vector[T]) ForEachMutable(cb func(val *T)) {
  method ForEachMutableIf (line 198) | func (v Vector[T]) ForEachMutableIf(cb func(val *T) bool) {
  method Iterate (line 207) | func (v Vector[T]) Iterate() MutableIterator[T] {
  method IterateRange (line 212) | func (v Vector[T]) IterateRange(i, j int) MutableIterator[T] {
  type vectorIterator (line 216) | type vectorIterator struct
  method Value (line 221) | func (it vectorIterator[T]) Value() T {
  method Pointer (line 225) | func (it vectorIterator[T]) Pointer() *T {
  method IsNotEnd (line 229) | func (it vectorIterator[T]) IsNotEnd() bool {
  method MoveToNext (line 233) | func (it *vectorIterator[T]) MoveToNext() {

FILE: vector_test.go
  function Test_Vector_Interface (line 7) | func Test_Vector_Interface(t *testing.T) {
  function Test_MakeVector (line 12) | func Test_MakeVector(t *testing.T) {
  function Test_MakeVectorCap (line 21) | func Test_MakeVectorCap(t *testing.T) {
  function Test_VectorOf (line 27) | func Test_VectorOf(t *testing.T) {
  function Test_AsVector (line 36) | func Test_AsVector(t *testing.T) {
  function Test_VectorCap (line 43) | func Test_VectorCap(t *testing.T) {
  function Test_Vector_Clear (line 51) | func Test_Vector_Clear(t *testing.T) {
  function Test_Vector_Reserve (line 59) | func Test_Vector_Reserve(t *testing.T) {
  function Test_Vector_Shrink (line 68) | func Test_Vector_Shrink(t *testing.T) {
  function Test_Vector_At_Set (line 76) | func Test_Vector_At_Set(t *testing.T) {
  function Test_Vector_PushBack (line 85) | func Test_Vector_PushBack(t *testing.T) {
  function Test_Vector_PopBack (line 91) | func Test_Vector_PopBack(t *testing.T) {
  function Test_Vector_PopBack_Clear (line 103) | func Test_Vector_PopBack_Clear(t *testing.T) {
  function Test_Vector_Back (line 110) | func Test_Vector_Back(t *testing.T) {
  function Test_Vector_Insert (line 117) | func Test_Vector_Insert(t *testing.T) {
  function Test_Vector_Insert_Tail (line 123) | func Test_Vector_Insert_Tail(t *testing.T) {
  function Test_Vector_Insert_Mid (line 129) | func Test_Vector_Insert_Mid(t *testing.T) {
  function Test_Vector_Insert_Cap (line 135) | func Test_Vector_Insert_Cap(t *testing.T) {
  function Test_Vector_Remove (line 142) | func Test_Vector_Remove(t *testing.T) {
  function Test_Vector_RemoveRange (line 153) | func Test_Vector_RemoveRange(t *testing.T) {
  function Test_Vector_RemoveLength (line 165) | func Test_Vector_RemoveLength(t *testing.T) {
  function Test_Vector_RemoveIf (line 177) | func Test_Vector_RemoveIf(t *testing.T) {
  function Test_Vector_ForEach (line 189) | func Test_Vector_ForEach(t *testing.T) {
  function Test_Vector_ForEachIf (line 200) | func Test_Vector_ForEachIf(t *testing.T) {
  function Test_Vector_ForEachMutable (line 210) | func Test_Vector_ForEachMutable(t *testing.T) {
  function Test_Vector_ForEachMutableIf (line 222) | func Test_Vector_ForEachMutableIf(t *testing.T) {
  function Test_Vector_Iterate (line 232) | func Test_Vector_Iterate(t *testing.T) {
  function Test_Vector_IterateRange (line 243) | func Test_Vector_IterateRange(t *testing.T) {
Condensed preview — 67 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (281K chars).
[
  {
    "path": ".github/workflows/check-markdown-links.yml",
    "chars": 324,
    "preview": "name: Check Markdown links\n\non: push\n\njobs:\n  markdown-link-check:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: act"
  },
  {
    "path": ".github/workflows/go.yml",
    "chars": 790,
    "preview": "name: Go\n\non:\n  push:\n    branches: [ \"master\" ]\n  pull_request:\n    branches: [ \"master\" ]\n\njobs:\n\n  build:\n    runs-on"
  },
  {
    "path": ".github/workflows/gosec.yml",
    "chars": 363,
    "preview": "name: Run Gosec\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\njobs:\n  tests:\n   "
  },
  {
    "path": ".gitignore",
    "chars": 299,
    "preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n__debug_bin\n\n# Test binary, built with `go test -c`\n"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 11854,
    "preview": "# stl4go -- STL for Golang\n\nEnglish | [简体中文](README_zh.md)\n\nThis library contains generic containers and algorithms, it "
  },
  {
    "path": "README_zh.md",
    "chars": 6873,
    "preview": "# stl4go -- Go 语言的 STL\n\n[English](README.md) | 简体中文\n\n本库包含 Go 语言实现的泛型容器和算法库,就像 C++ 中的 STL。\n\n[![License Apache 2.0](https:"
  },
  {
    "path": "binary_search.go",
    "chars": 2983,
    "preview": "package stl4go\n\n// LowerBound returns an index to the first element in the ascending ordered slice a that\n// does not sa"
  },
  {
    "path": "binary_search_test.go",
    "chars": 1394,
    "preview": "package stl4go\n\nimport \"testing\"\n\nfunc TestLowerBound(t *testing.T) {\n\ta := []int{1, 2, 4, 5, 5, 6}\n\texpectEq(t, LowerBo"
  },
  {
    "path": "builtin_set.go",
    "chars": 4016,
    "preview": "package stl4go\n\nimport (\n\t\"fmt\"\n)\n\n// BuiltinSet is an associative container that contains an unordered set of unique ob"
  },
  {
    "path": "builtin_set_test.go",
    "chars": 4506,
    "preview": "package stl4go\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc Test_BuiltinSet_Interface(t *testing.T) {\n\ts := make(Built"
  },
  {
    "path": "check.bat",
    "chars": 102,
    "preview": "go build\n\ngo test ./... -coverprofile=coverage.out\n\ngolint\n\ngosec .\n\ngo tool cover -html=coverage.out\n"
  },
  {
    "path": "check.sh",
    "chars": 123,
    "preview": "#!/bin/bash\n\nset -e\n\ngo build\n\ngo test ./... -coverprofile=coverage.out\n\ngolint\n\ngosec .\n\ngo tool cover -html=coverage.o"
  },
  {
    "path": "compare.go",
    "chars": 748,
    "preview": "package stl4go\n\n// Equal returns whether two slices are equal.\n// Return true if they are the same length and all elemen"
  },
  {
    "path": "compare_test.go",
    "chars": 630,
    "preview": "package stl4go\n\nimport \"testing\"\n\nfunc Test_Equal(t *testing.T) {\n\texpectTrue(t, Equal([]int{}, []int{}))\n\texpectTrue(t,"
  },
  {
    "path": "compute.go",
    "chars": 1806,
    "preview": "package stl4go\n\n// SumAs summarize all elements in a.\n// returns the result as type R, this is useful when T is too smal"
  },
  {
    "path": "compute_test.go",
    "chars": 1569,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_SumAs(t *testing.T) {\n\tt.Run(\"sum uint8 to int\", func(t *testing.T) {\n\t"
  },
  {
    "path": "container.go",
    "chars": 4634,
    "preview": "package stl4go\n\n// Container is a holder object that stores a collection of other objects.\ntype Container interface {\n\tI"
  },
  {
    "path": "container_test.go",
    "chars": 15,
    "preview": "package stl4go\n"
  },
  {
    "path": "dlist.go",
    "chars": 4358,
    "preview": "package stl4go\n\nimport \"fmt\"\n\n// DList is a doubly linked list.\ntype DList[T any] struct {\n\thead   *dListNode[T]\n\tlength"
  },
  {
    "path": "dlist_queue.go",
    "chars": 1727,
    "preview": "package stl4go\n\nimport (\n\t\"fmt\"\n)\n\n// DListQueue is a FIFO container\ntype DListQueue[T any] struct {\n\tlist DList[T]\n}\n\n/"
  },
  {
    "path": "dlist_queue_test.go",
    "chars": 1799,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_Queue_Interface(t *testing.T) {\n\tq := NewDListQueue[int]()\n\t_ = Deque[i"
  },
  {
    "path": "dlist_test.go",
    "chars": 3855,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_Dlist_Interface(t *testing.T) {\n\t_ = Container(&DList[int]{})\n}\n\nfunc T"
  },
  {
    "path": "doc.go",
    "chars": 86,
    "preview": "// Package stl4go is a generic container and algorithm library for go.\npackage stl4go\n"
  },
  {
    "path": "functor.go",
    "chars": 401,
    "preview": "package stl4go\n\n// Less wraps the '<' operator for ordered types.\nfunc Less[T Ordered](a, b T) bool {\n\treturn a < b\n}\n\n/"
  },
  {
    "path": "generate.go",
    "chars": 482,
    "preview": "package stl4go\n\n// Range make a []T filled with values in the `[first, last)` sequence.\n// NOTE: the last is not include"
  },
  {
    "path": "generate_test.go",
    "chars": 319,
    "preview": "package stl4go\n\nimport \"testing\"\n\nfunc Test_Range(t *testing.T) {\n\ta := Range(0, 100)\n\texpectEq(t, len(a), 100)\n\texpectE"
  },
  {
    "path": "generated_doc.md",
    "chars": 91543,
    "preview": "<!-- markdownlint-disable -->\n<!-- gomarkdoc:embed:start -->\n\n<!-- Code generated by gomarkdoc. DO NOT EDIT -->\n\n# stl4g"
  },
  {
    "path": "go.mod",
    "chars": 44,
    "preview": "module github.com/chen3feng/stl4go\n\ngo 1.18\n"
  },
  {
    "path": "go.sum",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "heap.go",
    "chars": 4083,
    "preview": "// Fast generic heap algorithms, faster than [container/heap]\n\npackage stl4go\n\n// MakeMinHeap build a min-heap on slice "
  },
  {
    "path": "heap.md",
    "chars": 3025,
    "preview": "# Heap\n\nstl4go provides a group of [heap](https://en.wikipedia.org/wiki/Heap_(data_structure)) algorithms.\n\n## Easy to u"
  },
  {
    "path": "heap_bench_test.go",
    "chars": 2312,
    "preview": "package stl4go\n\nimport (\n\t\"container/heap\"\n\t\"testing\"\n)\n\n// An intHeap is a min-heap of ints.\ntype intHeap []int\n\nfunc ("
  },
  {
    "path": "heap_test.go",
    "chars": 1257,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc TestMakeMinHeap(t *testing.T) {\n\tdata := []int{5, 4, 3, 2, 1}\n\texpectFalse(t"
  },
  {
    "path": "helper.go",
    "chars": 168,
    "preview": "package stl4go\n\nimport (\n\t\"reflect\"\n)\n\n// nameOfType return type name as a string.\nfunc nameOfType[T any]() string {\n\tva"
  },
  {
    "path": "iterator.go",
    "chars": 798,
    "preview": "package stl4go\n\n// Iterator is the interface for container's iterator.\ntype Iterator[T any] interface {\n\tIsNotEnd() bool"
  },
  {
    "path": "lookup.go",
    "chars": 2899,
    "preview": "package stl4go\n\n// Max return the larger value between `a` and `b`.\n//\n// Complexity: O(1).\nfunc Max[T Ordered](a, b T) "
  },
  {
    "path": "lookup_test.go",
    "chars": 2245,
    "preview": "package stl4go\n\nimport \"testing\"\n\nfunc Test_Min(t *testing.T) {\n\texpectEq(t, Min(1, 2), 1)\n\texpectEq(t, Min(2, 1), 1)\n\te"
  },
  {
    "path": "mlc_config.json",
    "chars": 74,
    "preview": "{\n    \"aliveStatusCodes\": [\n        400,\n        429,\n        200\n    ]\n}\n"
  },
  {
    "path": "pool.go",
    "chars": 820,
    "preview": "package stl4go\n\nimport \"sync\"\n\n// Pool is a type safed sync.Pool.\ntype Pool[T any] sync.Pool\n\n// MakePool returns a Pool"
  },
  {
    "path": "pool_test.go",
    "chars": 352,
    "preview": "package stl4go\n\nimport \"testing\"\n\nfunc TestPool(t *testing.T) {\n\tp := MakePool[int]()\n\tx := p.Get()\n\tp.Put(x)\n}\n\nfunc Te"
  },
  {
    "path": "priority_queue.go",
    "chars": 2453,
    "preview": "package stl4go\n\n// PriorityQueue is an queue with priority.\n// The elements of the priority queue are ordered according "
  },
  {
    "path": "priority_queue_test.go",
    "chars": 1638,
    "preview": "package stl4go\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestInterface(t *testing.T) {\n\t_ = (Container)(NewPriorityQueue[int]("
  },
  {
    "path": "skiplist.go",
    "chars": 12894,
    "preview": "// This implementation is based on https://github.com/liyue201/gostl/tree/master/ds/skiplist\n// (many thanks), added man"
  },
  {
    "path": "skiplist.md",
    "chars": 28,
    "preview": "# SkipList\n\nTODO,See tests.\n"
  },
  {
    "path": "skiplist_bench_test.go",
    "chars": 2957,
    "preview": "package stl4go\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n)\n\nconst (\n\tbenchInitSize  = 1000000\n\tbenchBatchSize = 10\n)\n\nfunc newMapN"
  },
  {
    "path": "skiplist_newnode.go",
    "chars": 7722,
    "preview": "// AUTO GENERATED CODE, DO NOT EDIT!!!\n// EDIT skiplist_newnode_generate.sh accordingly.\n\npackage stl4go\n\n// newSkipList"
  },
  {
    "path": "skiplist_newnode_generate.sh",
    "chars": 1201,
    "preview": "#!/bin/bash\n\n# The go generics sucks!\n# We have to generate skiplist_newnode.go by myself.\n\ngenerate() {\n\t# NOTE the tab"
  },
  {
    "path": "skiplist_set.go",
    "chars": 3314,
    "preview": "package stl4go\n\n// SkipListSet is a SortedSet implemented with skiplist.\ntype SkipListSet[K any] SkipList[K, struct{}]\n\n"
  },
  {
    "path": "skiplist_set_test.go",
    "chars": 2874,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc TestNewSkipList_Interface(t *testing.T) {\n\ts := NewSkipListSet[int]()\n\t_ = S"
  },
  {
    "path": "skiplist_test.go",
    "chars": 7088,
    "preview": "package stl4go\n\nimport (\n\t\"math\"\n\t\"testing\"\n)\n\nfunc TestSkipList_Interface(t *testing.T) {\n\tsl := NewSkipList[int, int]("
  },
  {
    "path": "slist.go",
    "chars": 4247,
    "preview": "package stl4go\n\n// SList is a singly linked list.\ntype SList[T any] struct {\n\thead   *sListNode[T]\n\ttail   *sListNode[T]"
  },
  {
    "path": "slist_test.go",
    "chars": 2751,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_SList_Interface(t *testing.T) {\n\tsl := SList[int]{}\n\t_ = Container(&sl)"
  },
  {
    "path": "sort.go",
    "chars": 2801,
    "preview": "package stl4go\n\nimport (\n\t\"sort\"\n)\n\n// IsSorted returns whether the slice a is sorted in ascending order.\n//\n// Complexi"
  },
  {
    "path": "sort_test.go",
    "chars": 1214,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_IsSorted(t *testing.T) {\n\texpectTrue(t, IsSorted([]int{}))\n\texpectTrue("
  },
  {
    "path": "stack.go",
    "chars": 1710,
    "preview": "package stl4go\n\n// Stack s is a container adaptor that provides the functionality of a stack,\n// a LIFO (last-in, first-"
  },
  {
    "path": "stack_test.go",
    "chars": 1248,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_Stack_Interface(t *testing.T) {\n\t_ = Container(NewStack[int]())\n}\nfunc "
  },
  {
    "path": "test_helper.go",
    "chars": 1348,
    "preview": "package stl4go\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc report(t *testing.T, msg string) {\n\tt.Helper()\n\tt.Errorf(\"Wrong: %v\\n"
  },
  {
    "path": "transform.go",
    "chars": 5125,
    "preview": "package stl4go\n\nimport \"math/rand\"\n\n// Copy make a copy of slice a.\n//\n// Complexity: O(len(a)).\nfunc Copy[T any](a []T)"
  },
  {
    "path": "transform_fillzero_clear.go",
    "chars": 182,
    "preview": "//go:build go1.21\n// +build go1.21\n\npackage stl4go\n\n// FillZero fills each element in slice a with zero value.\n//\n// Com"
  },
  {
    "path": "transform_fillzero_old.go",
    "chars": 201,
    "preview": "//go:build !go1.21\n// +build !go1.21\n\npackage stl4go\n\n// FillZero fills each element in slice a with zero value.\n//\n// C"
  },
  {
    "path": "transform_test.go",
    "chars": 4005,
    "preview": "package stl4go\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n)\n\nvar (\n\temptyInts = []int{}\n)\n\nfunc Test_Copy(t *testing.T) {\n\ta := []i"
  },
  {
    "path": "types.go",
    "chars": 1730,
    "preview": "package stl4go\n\n// Signed is a constraint that permits any signed integer type.\n// If future releases of Go add new pred"
  },
  {
    "path": "updatedoc.bat",
    "chars": 46,
    "preview": "@echo off\n\ngomarkdoc -o generated_doc.md -e .\n"
  },
  {
    "path": "updatedoc.sh",
    "chars": 48,
    "preview": "#!/bin/bash\n\ngomarkdoc -o generated_doc.md -e .\n"
  },
  {
    "path": "vector.go",
    "chars": 5695,
    "preview": "package stl4go\n\n// Many tricks are from:\n// https://github.com/golang/go/wiki/SliceTricks#in-place-deduplicate-comparabl"
  },
  {
    "path": "vector_test.go",
    "chars": 4997,
    "preview": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_Vector_Interface(t *testing.T) {\n\tv := MakeVector[int]()\n\t_ = Container"
  }
]

About this extraction

This page contains the full source code of the chen3feng/stl4go GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 67 files (250.5 KB), approximately 82.8k tokens, and a symbol index with 599 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!