[
  {
    "path": ".github/workflows/check-markdown-links.yml",
    "content": "name: Check Markdown links\n\non: push\n\njobs:\n  markdown-link-check:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@master\n    - uses: gaurav-nelson/github-action-markdown-link-check@v1\n      with:\n        use-quiet-mode: 'yes'\n        check-modified-files-only: 'yes'\n        config-file: mlc_config.json\n"
  },
  {
    "path": ".github/workflows/go.yml",
    "content": "name: Go\n\non:\n  push:\n    branches: [ \"master\" ]\n  pull_request:\n    branches: [ \"master\" ]\n\njobs:\n\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v3\n\n    - name: Set up Go\n      uses: actions/setup-go@v3\n      with:\n        go-version: 1.18\n\n    - name: Build\n      run: go build -v ./...\n\n    - name: Test\n      run: go test -v ./... -covermode=count -coverprofile=coverage.out.tmp\n\n    - name: Filter out test_helper\n      run: grep -E -v \"/(test_helper)\\.go:\" coverage.out.tmp > coverage.out\n\n    - name: Convert coverage.out to coverage.lcov\n      uses: jandelgado/gcov2lcov-action@v1.0.9\n\n    - name: Coveralls\n      uses: coverallsapp/github-action@v1.1.2\n      with:\n        github-token: ${{ secrets.github_token }}\n        path-to-lcov: coverage.lcov\n"
  },
  {
    "path": ".github/workflows/gosec.yml",
    "content": "name: Run Gosec\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\njobs:\n  tests:\n    runs-on: ubuntu-latest\n    env:\n      GO111MODULE: on\n    steps:\n      - name: Checkout Source\n        uses: actions/checkout@v2\n      - name: Run Gosec Security Scanner\n        uses: securego/gosec@master\n        with:\n          args: ./...\n"
  },
  {
    "path": ".gitignore",
    "content": "# 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*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n*.tmp\n*.bak\n*.old\n\n# Dependency directories (remove the comment below to include it)\n# vendor/\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# stl4go -- STL for Golang\n\nEnglish | [简体中文](README_zh.md)\n\nThis library contains generic containers and algorithms, it is designed to be STL for Golang.\n\n[![License Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-red.svg)](COPYING)\n[![Golang](https://img.shields.io/badge/Language-go1.18+-blue.svg)](https://go.dev/)\n![Build Status](https://github.com/chen3feng/stl4go/actions/workflows/go.yml/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/chen3feng/stl4go/badge.svg?branch=master)](https://coveralls.io/github/chen3feng/stl4go?branch=master)\n[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/report/github.com/chen3feng/stl4go)\n[![Go Reference](https://pkg.go.dev/badge/github.com/chen3feng/stl4go.svg)](https://pkg.go.dev/github.com/chen3feng/stl4go)\n\nThis library depends on go generics, which is introduced in 1.18+.\n\n<!-- gomarkdoc:embed:start -->\n\n<!-- Code generated by gomarkdoc. DO NOT EDIT -->\n\n```go\nimport \"github.com/chen3feng/stl4go\"\n```\n\nPackage stl4go is a generic container and algorithm library for go.\n\n## Introduce\n\nThis 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.\n(Personally I's totally unacceptable for me  use to languages without generics, so I didn't try it until go 1.18).\n\nThe code quality of this library is quite high and follows the latest best practices in the industry.\nTest coverage is close💯%, ✅，CI, and [gosec](https://securego.io/) check are both set up, got\n[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/report/github.com/chen3feng/stl4go) score。\n\n## Features\n\nAs we all know, C++'s STL includes containers, algorithms, and iterators relate the two.\n\nDue to language limitations, it is impossible and unnecessary to completely imitate the interface of C++ STL in Go,\nso C++ users may feel familiar, and sometimes (maybe) feel more convenient.\n\n### Containers\n\nThere are following container interfaces:\n\n- `Container` is the base interface for all containers\n- `Map` is a key-value associative container\n- `Set` is set container\n- `SortedMap` is a ordered key-value associative container\n- `SortedSet` is a ordered set container\n- `Queue` is a FIFO Queue\n- `Deque` is a double ended queue\n\nDifferent interface has different methods. The `Container` interface has following methods:\n\n- `IsEmpty() bool` returns whether the container is empty\n- `Len() int` returns the number of elements in the container\n- `Clear()` to clear the container\n\nRead [source code](container.go) for details.\n\nCurrently container implementations are:\n\n- [x] `BuiltinSet` provided a set funtionality based on Go's own `map`. It provides basic operations such as insert,\n      search and remove, as well as advanced functions such as union, intersection, difference, subset, superset, and disjoint.\n- [x] `Vector` is a thin encapsulation based on `slice`. It provides functions such as insertion and deletion in the middle, range deletion, etc.,\n      and is still compatible with slices.\n- [x] `DList` is a doubly linked list, supports push/popup at both ending.\n- [x] `SList` is a singly linked list, supports push/popup at the head and push at the tail.\n- [x] [SkipList](skiplist.md) is an ordered associative container that fills the gap where Go `map` only supports unordered.\n      This is currently the fastest skip list I tested in GitHub, see [skiplist-survey](https://github.com/chen3feng/skiplist-survey) for performance comparison\n- [x] `SkipList` is a `SortedSet` container based on the skiplist.\n- [x] `Stack`, is a FILO container based on Slice implementation\n- [x] `DListQueue` is a bidirectional FIFO queue, implemented based on linked list.\n- [x] `PriorityQuque` is a priority queue based on heap. Much easier to use and faster than [container/heap](https://pkg.go.dev/container/heap).\n\n### Non-Container Components\n\n- [x] `Pool` A type safe Pool, is implemented based on `sync.Pool`.\n\n### Iterators\n\nVector, DList and SkipList support iterators.\n\n```go\n// Iterator is the interface for container's iterator.\ntype Iterator[T any] interface {\n\tIsNotEnd() bool // Whether it is point to the end of the range.\n\tMoveToNext()    // Let it point to the next element.\n\tValue() T       // Return the value of current element.\n}\n\n// MutableIterator is the interface for container's mutable iterator.\ntype MutableIterator[T any] interface {\n\tIterator[T]\n\tPointer() *T // Return the pointer to the value of current element.\n}\n```\n\n```go\nl := stl4go.NewDListOf(Range(1, 10000)...)\nsum := 0\nfor i := 0; i < b.N; i++ {\n    for it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n        sum += it.Value()\n    }\n}\n```\n\nThe iterator of SkipList is `MutableMapIterator`:\n\n```go\n// MapIterator is the interface for map's iterator.\ntype MapIterator[K any, V any] interface {\n\tIterator[V]\n\tKey() K // The key of the element\n}\n\n// MutableMapIterator is the interface for map's mutable iterator.\ntype MutableMapIterator[K any, V any] interface {\n\tMutableIterator[V]\n\tKey() K // The key of the element\n}\n```\n\nSkipList also supports range iteration:\n\n```go\nsl := stl4go.NewSkipList[int, int]()\nfor i := 0; i < 1000; i++ {\n    sl.Insert(i, 0)\n}\nit := sl.FindRange(120, 350)\n```\n\nIterating over `it` only yields the keys between 120 and 349.\n\nIn many cases, it is more convenient to use the `ForEach` and `ForEachIf` methods provided by the container,\nand the performance is often better:\n\n```go\nfunc TestSkipList_ForEach(t *testing.T) {\n    sl := newSkipListN(100)\n    a := []int{}\n    sl.ForEach(func(k int, v int) {\n        a = append(a, k)\n    })\n    expectEq(t, len(a), 100)\n    expectTrue(t, IsSorted(a))\n}\n```\n\n`ForEachIf` is used for scenarios that you want to end early during the iteration:\n\n ```go\nfunc Test_DList_ForEachIf(t *testing.T) {\n    l := NewDListOf(1, 2, 3)\n    c := 0\n    l.ForEachIf(func(n int) bool {\n        c = n\n        return n != 2\n    })\n    expectEq(t, c, 2)\n}\n ```\n\nYou can use `ForEachMutable` or `ForEachMutable` to modify the value of an element during the iteration:\n\n```go\nfunc TestSkipList_ForEachMutable(t *testing.T) {\n    sl := newSkipListN(100)\n    sl.ForEachMutable(func(k int, v *int) {\n        *v = -*v\n    })\n    for i := 0; i < sl.Len(); i++ {\n        expectEq(t, *sl.Find(i), -i)\n    }\n}\n```\n\n### Algorithms\n\nDue to the limitations of language, most algorithms only support Slice.\nThe functions name of the algorithms ends with `If` or `Func`,\nindicating that a custom comparison function can be passed.\n\n#### Generate\n\n- `Range` returns a Slice of contains integers in the range of `[begin, end)`\n- `Generate` generates a sequence with the given function to fill the Slice\n\n#### Data manipulation\n\n- `Copy` return a copies of specified slice\n- `CopyTo` copies all elements in slice a to slice to, return the copied slice.\n- `Fill` repeatedly fills a slice with the specified value\n- `FillZero` fills each element in slice a with zero value.\n- `FillPattern` repeatedly fills a slice with the specified pattern\n- `Replace` replaces every element that equals to old with new\n- `ReplaceIf` replaces every element that make preq returns true with new\n- `Transform` passes the value at each position of the slice to the specified function and sets it back with its return value\n- `TransformTo` passes the value at each position of slice `a` to the specified function,\n  sets its return value to the corresponding position in slice `b`, and returns a slice of corresponding length of slice `b`\n- `TransformCopy` passes the value at each position of the slice to the specified function,\n  sets its return value to the corresponding position in a new slice and returns\n- `Unique` removes adjacent duplicate elements from a slice and returns a slice with new length containing the remaining elements,\n  `UniqueCopy` returns a copy without modifying the original slice\n- `Remove` removes all elements in the slice equal to the specified value, `RemoveCopy` returns a copy without modifying the original slice\n- `RemoveIf` removes all elements in the slice that are equivalent to making the specified function return `true`,\n  `RemoveIfCopy` does not modify the original slice but returns a copy\n- `Shuffle` random shuffle elements in the slice\n- `Reverse` reverses a slice, `ReverseCopy` returns a copy without modifying the original slice\n\n#### Compute\n\n- `Sum` Sum\n- `SumAs` sums and returns a result as another type (eg. use `int64` to return the sum of `[]int32`).\n- `Average` finds the average value.\n- `AverageAs` averages and returns the result as another type (eg. use `float64` to return the sum of `[]int`).\n- `Count` returns the number equivalent to the specified value\n- `CountIf` returns the number of elements for which the specified function returns `true`\n\n#### Compare\n\n- `Equal` checks whether two sequences are equal\n- `Compare` compares two sequences and returns `-1`, `0`, and `1` in lexicographical order, respectively indicating the relationship of 2 slices.\n\n#### Lookup\n\n- `Min`, `Max` find the maximum and minimum\n- `MinN`, `MaxN`, `MinMax` return the maximum and minimum values in the slice\n- `Find` linearly finds the first specified value and returns its index\n- `FindIf` linearly finds the first value that make specified function returns `true` and returns its index\n- `AllOf`, `AnyOf`, `NoneOf` return whether all, any, or none of the elements in the range can make the passed function return `true` accordingly.\n\n#### Binary Search\n\nSee C++ STL.\n\n- `BinarySearch`\n- `LowerBound`\n- `UpperBound`\n\n#### Sort\n\n- `Sort` sorting\n- `DescSort` descending sorting\n- `StableSort` stable sorting\n- `DescStableSort` descending stable sorting\n- `IsSorted` check whether the slice is sorted\n- `IsDescSorted` check whether the slice is sorted in descending order\n\n#### heap\n\n[Heap](heap.md) provides basic min heap algorithms:\n\n- `MakeMinHeap` Convert a slice to a min heap\n- `IsMinHeap` Check whether a slice is a min heap\n- `PushMinHeap` Pushes an element in to the heap\n- `PopMinHeap` Popups an element from the top of the heap\n- `RemoveMinHeap` Removes an element at index from the heap\n\nand variants with custome comparasion function:\n\n- `MakeHeapFunc`\n- `IsHeapFunc`\n- `PushHeapFunc`\n- `PopHeapFunc`\n- `RemoveHeapFunc`\n\nboth of them are mush faster and easier to use than [container/heap](https://pkg.go.dev/container/heap).\n\nSee detailed usage and benchmark report in the [document of heap](heap.md)。\n\n### Interface Design and Naming\n\nThe 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?\n\nMany libraries are designed for small code repositories or split into multiple subpackages in one repository.\nFor example:\n\n```go\nimport (\n    \"github.com/someone/awesomelib/skiplist\"\n    \"github.com/someone/awesomelib/binarysearch\"\n)\n\nfunc main() {\n    sl := skiplist.New()\n}\n```\n\nThis 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,\nand different users have different renaming style, which increases the mental burden of code reading and writing.\n\nI don't like this style, especially in a larger repository.\n\nTherefore, this library is all under the `stl4go` package, and it is expected that it will not namesake in other people's libraries.\n\n### TODO\n\nSee [Issue](https://github.com/chen3feng/stl4go/issues)。\n\nAnd add more detailed documents.\n\n## Go Doc\n\nClick to view the [generated doc](generated_doc.md).\n\n## Reference\n\n- [C++ STL](https://en.wikipedia.org/wiki/Standard_Template_Library)\n- [liyue201/gostl](https://github.com/liyue201/gostl)\n- [zyedidia/generic](https://github.com/zyedidia/generic)\n- [hlccd/goSTL](https://github.com/hlccd/goSTL)\n"
  },
  {
    "path": "README_zh.md",
    "content": "# stl4go -- Go 语言的 STL\n\n[English](README.md) | 简体中文\n\n本库包含 Go 语言实现的泛型容器和算法库，就像 C++ 中的 STL。\n\n[![License Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-red.svg)](COPYING)\n[![Golang](https://img.shields.io/badge/Language-go1.18+-blue.svg)](https://go.dev/)\n![Build Status](https://github.com/chen3feng/stl4go/actions/workflows/go.yml/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/chen3feng/stl4go/badge.svg?branch=master)](https://coveralls.io/github/chen3feng/stl4go?branch=master)\n[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/report/github.com/chen3feng/stl4go)\n[![Go Reference](https://pkg.go.dev/badge/github.com/chen3feng/stl4go.svg)](https://pkg.go.dev/github.com/chen3feng/stl4go)\n\n```go\nimport \"github.com/chen3feng/stl4go\"\n```\n\n## 简介\n\n本库是在 Go 1.18 开始支持泛型后，尝试借鉴 C++ STL 实现的一个通用容器和算法库。（我个人完全无法接受没有泛型的语言，因此直到 go 1.18 才开始尝试用它）\n\n本库代码质量高，遵循了业界最新的最佳实践。测试覆盖率接近 💯%，✅，设置了 CI、 [gosec](https://securego.io/) 检查，\n[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/report/github.com/chen3feng/stl4go) 评分。\n\n## 主要功能\n\n众所周知，C++ 的 STL 包括容器、算法，并以迭代器关联两者。\n\n受语言限制，在 Go 中无法也没有必要完全模仿 C++的接口，因此 C++ 用户可能会感觉似曾相识相识，有时候也会感觉更方便。\n\n### 容器\n\n定义了如下容器接口：\n\n- `Container` 是所有容器的基础接口\n- `Map` 定义了 key-value 关联容器的接口\n- `Set` 定义了集合容器的接口\n- `SortedMap` 定义了有序 key-value 关联容器的接口\n- `SortedSet` 定义了有序集合容器的接口\n- `Queue` 定义了先进先出的队列的接口\n- `Deque` 定义了双端队列的接口\n\n不同的容器接口支持的方法不同，下面是 `Container` 接口的方法：\n\n- `IsEmpty() bool` 返回容器是否为空\n- `Len() int` 返回容器中的元素个数\n- `Clear()` 清空容器\n\n具体请参考[源代码](container.go)。\n\n提供的具体容器实现有：\n\n- [x] `BuiltinSet` 是基于 Go 自己的 map 封装的集合。提供了插入查找删除等基本操作，以及并集、交集、差集、子集、超集、不交集等高级功能。\n- [x] `Vector` 是基于切片封装的向量。提供了中间插入删除、区间删除等功能，依然与切片兼容。\n- [x] `DList` 是双链表容器，支持两端插入删除。\n- [x] `SList` 是单链表容器，支持头部插入删除及尾部插入。\n- [x] [跳表（SkipList）](skiplist.md) 是一种有序的关联容器，可以填补 Go `map` 只支持无序的的空白。这是目前全 GitHub 最快的跳表，参见 [skiplist-survey](https://github.com/chen3feng/skiplist-survey)的性能比较\n- [x] `SkipListSet` 是基于跳表实现的有序集合容器\n- [x] `Stack`，栈基于 Slice 实现\n- [x] `DListQueue` 双向进出的队列，基于双链表实现\n- [x] `PriorityQuque` 优先队列，基于堆实现，比 [container/heap](https://pkg.go.dev/container/heap) 更易用而且快不少。\n\n### 非容器组件\n\n- [x] `Pool` 类型安全的 Pool，基于对 `sync.Pool` 的封装而实现。\n\n### 迭代器\n\nVector、DList 和 SkipList 支持迭代器。\n\n```go\n// Iterator is the interface for container's iterator.\ntype Iterator[T any] interface {\n\tIsNotEnd() bool // Whether it is point to the end of the range.\n\tMoveToNext()    // Let it point to the next element.\n\tValue() T       // Return the value of current element.\n}\n\n// MutableIterator is the interface for container's mutable iterator.\ntype MutableIterator[T any] interface {\n\tIterator[T]\n\tPointer() *T // Return the pointer to the value of current element.\n}\n```\n\n```go\nl := stl4go.NewDListOf(Range(1, 10000)...)\nsum := 0\nfor i := 0; i < b.N; i++ {\n    for it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n        sum += it.Value()\n    }\n}\n```\n\nSkipList 的迭代器是 `MutableMapIterator`:\n\n```go\n// MapIterator is the interface for map's iterator.\ntype MapIterator[K any, V any] interface {\n\tIterator[V]\n\tKey() K // The key of the element\n}\n\n// MutableMapIterator is the interface for map's mutable iterator.\ntype MutableMapIterator[K any, V any] interface {\n\tMutableIterator[V]\n\tKey() K // The key of the element\n}\n```\n\nSkipList 还支持区间迭代：\n\n```go\nsl := stl4go.NewSkipList[int, int]()\nfor i := 0; i < 1000; i++ {\n    sl.Insert(i, 0)\n}\nit := sl.FindRange(120, 350)\n```\n\n对 `it` 迭代可以只会得到 120~349 之间的数。\n\n更多时候，使用容器提供的 `ForEach` 和 `ForEachIf` 更方便，往往性能也更好一些：\n\n```go\nfunc TestSkipList_ForEach(t *testing.T) {\n    sl := newSkipListN(100)\n    a := []int{}\n    sl.ForEach(func(k int, v int) {\n        a = append(a, k)\n    })\n    expectEq(t, len(a), 100)\n    expectTrue(t, IsSorted(a))\n}\n```\n\n `ForEachIf` 用于遍历时候提前结束的场景：\n\n ```go\nfunc Test_DList_ForEachIf(t *testing.T) {\n    l := NewDListOf(1, 2, 3)\n    c := 0\n    l.ForEachIf(func(n int) bool {\n        c = n\n        return n != 2\n    })\n    expectEq(t, c, 2)\n}\n ```\n\n使用 `ForEachMutable` 或 `ForEachMutable` 可以在遍历时候修改元素的值：\n\n```go\nfunc TestSkipList_ForEachMutable(t *testing.T) {\n    sl := newSkipListN(100)\n    sl.ForEachMutable(func(k int, v *int) {\n        *v = -*v\n    })\n    for i := 0; i < sl.Len(); i++ {\n        expectEq(t, *sl.Find(i), -i)\n    }\n}\n```\n\n### 算法\n\n受语言功能限制，绝大部分算法只支持 Slice。算法的函数名以 `If`、`Func` 结尾的，表示可以传递一个自定义的比较函数。\n\n#### 生成型\n\n- Range 返回一个 [begin, end) 的整数构成的 Slice\n- Generate 用给定的函数生成一个序列填充到 Slice 中\n\n#### 数据操作\n\n- `Copy` 返回切片的拷贝\n- `CopyTo` 拷贝切片的内容到另一个切片\n- `Fill` 用指定的值重复填充一个切片\n- `FillZero` 用类型的零值重复填充一个切片\n- `FillPattern` 用指定的模式重复填充一个切片\n- `Replace` 替换所有等于指定值的元素为新值\n- `ReplaceIf` 替换所有让函数返回 `true` 的元素为新值\n- `Transform` 把切片的每个位置的值传给指定的函数，用其返回值设置回去\n- `TransformTo` 把切片 a 的每个位置的值传给指定的函数，将其返回值设置到切片 b 中相应的位置，并返回 b 的相应长度的切片\n- `TransformCopy` 把切片的每个位置的值传给指定的函数，将其返回值设置到一个新的切片中相应的位置并返回\n- `Unique` 去除切片中相邻的重复元素，返回包含剩余元素的新长度的切片，`UniqueCopy` 则不修改原切片而是返回一个拷贝\n- `Remove` 去除切片中等于指定值的所有元素，`RemoveCopy` 则不修改原切片而是返回一个拷贝\n- `RemoveIf` 去除切片中等于让指定函数返回 `true` 的所有元素，`RemoveIfCopy` 则不修改原切片而是返回一个拷贝\n- `Shuffle` 随机洗牌\n- `Reverse` 反转一个切片，`ReverseCopy` 则不修改原切片而是返回一个拷贝\n\n#### 计算型\n\n- `Sum` 求和\n- `SumAs` 求和并以另一种类型的结果返回（比如以 `int64` 类型返回 `[]int32` 的和）\n- `Average` 求平均值。\n- `AverageAs` 求平均值并以另一种类型的结果返回（比如 `float64` 返回 `[]int` 的和）\n- `Count` 返回和指定值相当的个数\n- `CountIf` 返回让指定函数返回 `true` 的元素的个数\n\n#### 比较\n\n- `Equal` 判断两个序列是否相等\n- `Compare` 比较两个序列，按字典序返回 -1、0、1 分别表示起大小关系\n\n#### 查找\n\n- `Min`, `Max` 求最大最小值\n- `MinN`、`MaxN`、`MinMax` 返回 slice 中的最大和最小值\n- `Find` 线性查找第一个指定的值，返回其下标\n- `FindIf` 线性查找指定函数返回 `true` 的值，返回其下标\n- `AllOf`、`AnyOf`、`NoneOf` 返回区间中是否全部、任何一个、没有一个元素能使传入的函数返回 `true`\n\n#### 二分查找\n\n参考 C++STL。\n\n- `BinarySearch`\n- `LowerBound`\n- `UpperBound`\n\n#### 排序\n\n- `Sort` 升序排序\n- `DescSort` 降序排序\n- `StableSort` 升序稳定排序\n- `DescStableSort` 降序稳定排序\n- `IsSorted` 是否是升序排序的\n- `IsDescSorted` 是否是降序排序的\n\n#### 堆\n\n提供基本的堆算法：\n\n- `MakeMinHeap` 在一个切片上构造出一个最小堆\n- `IsMinHeap` 判断一个切片是不是一个最小堆\n- `PushMinHeap` 把一个元素压入最小堆\n- `PopMinHeap` 弹出堆顶的元素\n- `RemoveMinHeap` 从切片的指定位置删除一个元素\n\n以及相应的自定义比较函数的版本：\n\n- `MakeHeapFunc`\n- `IsHeapFunc`\n- `PushHeapFunc`\n- `PopHeapFunc`\n- `RemoveHeapFunc`\n\n都比 go 标准库 [container/heap](https://pkg.go.dev/container/heap) 更容易使用且更快。\n\n用法和测试详情参见[heap的文档](heap.md)。\n\n### 接口设计和命名\n\n较多地参考了 C++ STL。T 表示模板。是的，Go 的泛型不是模板，但是谁让 C++ 那么影响力，而 STL 又那么有名呢。\n\n很多库的设计采用小的代码仓库或者一个仓库中拆分成多个子包。\n\n比如\n\n```go\nimport (\n    \"github.com/someone/awesomelib/skiplist\"\n    \"github.com/someone/awesomelib/binarysearch\"\n)\n\nfunc main() {\n    sl := skiplist.New()\n}\n```\n\n这种写法看似优雅，但是由于好的名字大家都喜欢，在使用中又不得不引入 import 重命名，而不同的使用者别名不一样，增加代码读写的心智负担。\n\n我不太喜欢这种风格。\n\n因此本库全部在 `stl4go` 包下，期望不会和别人的库重名。\n\n### TODO\n\n参见 [Issue](https://github.com/chen3feng/stl4go/issues)。\n\n以及更详细的文档。\n\n## Go Doc\n\n点击查看[生成的文档](generated_doc.md).\n\n## Reference\n\n- [C++ STL](https://en.wikipedia.org/wiki/Standard_Template_Library)\n- [liyue201/gostl](https://github.com/liyue201/gostl)\n- [zyedidia/generic](https://github.com/zyedidia/generic)\n- [hlccd/goSTL](https://github.com/hlccd/goSTL)\n"
  },
  {
    "path": "binary_search.go",
    "content": "package stl4go\n\n// LowerBound returns an index to the first element in the ascending ordered slice a that\n// does not satisfy element < value (i.e. greater or equal to),\n// or len(a) if no such element is found.\n//\n// Complexity: O(log(len(a))).\nfunc LowerBound[T Ordered](a []T, value T) int {\n\tloc := 0\n\tcount := len(a)\n\tfor count > 0 {\n\t\ti := loc\n\t\tstep := count / 2\n\t\ti += step\n\t\tif a[i] < value {\n\t\t\ti++\n\t\t\tloc = i\n\t\t\tcount -= step + 1\n\t\t} else {\n\t\t\tcount = step\n\t\t}\n\t}\n\treturn loc\n}\n\n// LowerBoundFunc returns an index to the first element in the ordered slice a that\n// does not satisfy less(element, value)), or len(a) if no such element is found.\n//\n// The elements in the slice a should sorted according with compare func less.\n//\n// Complexity: O(log(len(a))).\nfunc LowerBoundFunc[T any](a []T, value T, less LessFn[T]) int {\n\tloc := 0\n\tcount := len(a)\n\tfor count > 0 {\n\t\ti := loc\n\t\tstep := count / 2\n\t\ti += step\n\t\tif less(a[i], value) {\n\t\t\ti++\n\t\t\tloc = i\n\t\t\tcount -= step + 1\n\t\t} else {\n\t\t\tcount = step\n\t\t}\n\t}\n\treturn loc\n}\n\n// UpperBound returns an index to the first element in the ascending ordered slice a such that\n// value < element (i.e. strictly greater), or len(a) if no such element is found.\n//\n// Complexity: O(log(len(a))).\nfunc UpperBound[T Ordered](a []T, value T) int {\n\tloc := 0\n\tcount := len(a)\n\tfor count > 0 {\n\t\ti := loc\n\t\tstep := count / 2\n\t\ti += step\n\t\tif !(value < a[i]) {\n\t\t\ti++\n\t\t\tloc = i\n\t\t\tcount -= step + 1\n\t\t} else {\n\t\t\tcount = step\n\t\t}\n\t}\n\treturn loc\n}\n\n// UpperBoundFunc returns an index to the first element in the ordered slice a such that\n// less(value, element)) is true (i.e. strictly greater), or len(a) if no such element is found.\n//\n// The elements in the slice a should sorted according with compare func less.\n//\n// Complexity: O(log(len(a))).\nfunc UpperBoundFunc[T any](a []T, value T, less LessFn[T]) int {\n\tloc := 0\n\tcount := len(a)\n\tfor count > 0 {\n\t\ti := loc\n\t\tstep := count / 2\n\t\ti += step\n\t\tif !less(value, a[i]) {\n\t\t\ti++\n\t\t\tloc = i\n\t\t\tcount -= step + 1\n\t\t} else {\n\t\t\tcount = step\n\t\t}\n\t}\n\treturn loc\n}\n\n// BinarySearch returns the (index, true) to the first element in the ascending ordered slice a\n// such that element == value, or (-1, false) if no such element is found.\n//\n// Complexity: O(log(len(a))).\nfunc BinarySearch[T Ordered](a []T, value T) (index int, ok bool) {\n\tloc := LowerBound(a, value)\n\tif loc < len(a) && a[loc] == value {\n\t\treturn loc, true\n\t}\n\treturn -1, false\n}\n\n// BinarySearchFunc returns the (index, true) to the first element in the ordered slice a such that\n// less(element, value) and less(value, element) are both false,\n// or (-1, false) if no such element is found.\n//\n// The elements in the slice a should sorted according with compare func less.\n//\n// Complexity: O(log(len(a))).\nfunc BinarySearchFunc[T any](a []T, value T, less LessFn[T]) (index int, ok bool) {\n\tloc := LowerBoundFunc(a, value, less)\n\tif loc < len(a) && !less(value, a[loc]) {\n\t\treturn loc, true\n\t}\n\treturn -1, false\n}\n"
  },
  {
    "path": "binary_search_test.go",
    "content": "package stl4go\n\nimport \"testing\"\n\nfunc TestLowerBound(t *testing.T) {\n\ta := []int{1, 2, 4, 5, 5, 6}\n\texpectEq(t, LowerBound(a, 1), 0)\n\texpectEq(t, LowerBound(a, 5), 3)\n\texpectEq(t, LowerBound(a, 7), len(a))\n}\n\nfunc TestLowerBoundFunc(t *testing.T) {\n\ta := []int{1, 2, 4, 5, 5, 6}\n\texpectEq(t, LowerBoundFunc(a, 1, Less[int]), 0)\n\texpectEq(t, LowerBoundFunc(a, 5, Less[int]), 3)\n\texpectEq(t, LowerBoundFunc(a, 7, Less[int]), len(a))\n}\n\nfunc TestUpperBound(t *testing.T) {\n\ta := []int{1, 2, 4, 5, 5, 6}\n\texpectEq(t, UpperBound(a, 1), 1)\n\texpectEq(t, UpperBound(a, 5), 5)\n\texpectEq(t, UpperBound(a, 7), len(a))\n}\n\nfunc TestUpperBoundFunc(t *testing.T) {\n\ta := []int{1, 2, 4, 5, 5, 6}\n\texpectEq(t, UpperBoundFunc(a, 1, Less[int]), 1)\n\texpectEq(t, UpperBoundFunc(a, 5, Less[int]), 5)\n\texpectEq(t, UpperBoundFunc(a, 7, Less[int]), len(a))\n}\n\nfunc TestBinarySearch(t *testing.T) {\n\ta := []int{1, 2, 4, 5, 5, 6}\n\n\ti, ok := BinarySearch(a, 4)\n\texpectTrue(t, ok)\n\texpectEq(t, i, 2)\n\n\ti, ok = BinarySearch(a, 5)\n\texpectTrue(t, ok)\n\texpectEq(t, i, 3)\n\n\ti, ok = BinarySearch(a, 3)\n\texpectFalse(t, ok)\n}\n\nfunc TestBinarySearchFunc(t *testing.T) {\n\ta := []int{1, 2, 4, 5, 5, 6}\n\n\ti, ok := BinarySearchFunc(a, 4, Less[int])\n\texpectTrue(t, ok)\n\texpectEq(t, i, 2)\n\n\ti, ok = BinarySearchFunc(a, 5, Less[int])\n\texpectTrue(t, ok)\n\texpectEq(t, i, 3)\n\n\ti, ok = BinarySearchFunc(a, 3, Less[int])\n\texpectFalse(t, ok)\n}\n"
  },
  {
    "path": "builtin_set.go",
    "content": "package stl4go\n\nimport (\n\t\"fmt\"\n)\n\n// BuiltinSet is an associative container that contains an unordered set of unique objects of type K.\ntype BuiltinSet[K comparable] map[K]struct{}\n\n// SetOf creates a new BuiltinSet object with the initial content from ks.\nfunc SetOf[K comparable](ks ...K) BuiltinSet[K] {\n\ts := make(BuiltinSet[K])\n\ts.InsertN(ks...)\n\treturn s\n}\n\n// IsEmpty implements the Container interface.\nfunc (s BuiltinSet[K]) IsEmpty() bool {\n\treturn len(s) == 0\n}\n\n// Len implements the Container interface.\nfunc (s BuiltinSet[K]) Len() int {\n\treturn len(s)\n}\n\n// Clear implements the Container interface.\nfunc (s BuiltinSet[K]) Clear() {\n\tfor k := range s {\n\t\tdelete(s, k)\n\t}\n}\n\n// Has implements the Set interface.\nfunc (s BuiltinSet[K]) Has(k K) bool {\n\t_, ok := s[k]\n\treturn ok\n}\n\n// Insert implements the Set interface.\nfunc (s BuiltinSet[K]) Insert(k K) bool {\n\toldLen := len(s)\n\ts[k] = struct{}{}\n\treturn len(s) > oldLen\n}\n\n// InsertN implements the Set interface.\nfunc (s BuiltinSet[K]) InsertN(ks ...K) int {\n\toldLen := len(s)\n\tfor _, key := range ks {\n\t\ts[key] = struct{}{}\n\t}\n\treturn len(s) - oldLen\n}\n\n// Remove implements the Set interface.\nfunc (s BuiltinSet[K]) Remove(k K) bool {\n\t_, ok := s[k]\n\tdelete(s, k)\n\treturn ok\n}\n\n// Delete deletes an element from the set.\n// It returns nothing, so it's faster than Remove.\nfunc (s BuiltinSet[K]) Delete(k K) {\n\tdelete(s, k)\n}\n\n// RemoveN implements the Set interface.\nfunc (s BuiltinSet[K]) RemoveN(ks ...K) int {\n\toldLen := len(s)\n\tfor _, k := range ks {\n\t\tdelete(s, k)\n\t}\n\treturn oldLen - len(s)\n}\n\n// Keys return a copy of all keys as a slice.\nfunc (s BuiltinSet[K]) Keys() []K {\n\tkeys := make([]K, 0, len(s))\n\tfor k := range s {\n\t\tkeys = append(keys, k)\n\t}\n\treturn keys\n}\n\n// ForEach implements the Set interface.\nfunc (s BuiltinSet[K]) ForEach(cb func(k K)) {\n\tfor k := range s {\n\t\tcb(k)\n\t}\n}\n\n// ForEachIf implements the Container interface.\nfunc (s BuiltinSet[K]) ForEachIf(cb func(k K) bool) {\n\tfor k := range s {\n\t\tif !cb(k) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// String implements the fmt.Stringer interface.\nfunc (s BuiltinSet[K]) String() string {\n\treturn fmt.Sprintf(\"BuiltinSet[%s]%v\", nameOfType[K](), s.Keys())\n}\n\n// Update adds all elements from other to set. set |= other.\nfunc (s BuiltinSet[K]) Update(other BuiltinSet[K]) {\n\tfor k := range other {\n\t\ts[k] = struct{}{}\n\t}\n}\n\n// Union returns a new set with elements from the set and other.\nfunc (s BuiltinSet[K]) Union(other BuiltinSet[K]) BuiltinSet[K] {\n\tresult := BuiltinSet[K]{}\n\tresult.Update(s)\n\tresult.Update(other)\n\treturn result\n}\n\nfunc orderSet[K comparable](a, b BuiltinSet[K]) (small, large BuiltinSet[K]) {\n\tif a.Len() < b.Len() {\n\t\treturn a, b\n\t}\n\treturn b, a\n}\n\n// Intersection returns a new set with elements common to the set and other.\nfunc (s BuiltinSet[K]) Intersection(other BuiltinSet[K]) BuiltinSet[K] {\n\tresult := BuiltinSet[K]{}\n\tsmall, large := orderSet(s, other)\n\tfor k := range small {\n\t\tif large.Has(k) {\n\t\t\tresult.Insert(k)\n\t\t}\n\t}\n\treturn result\n}\n\n// Difference returns a new set with elements in the set that are not in other.\nfunc (s BuiltinSet[K]) Difference(other BuiltinSet[K]) BuiltinSet[K] {\n\tresult := BuiltinSet[K]{}\n\tfor k := range s {\n\t\tif !other.Has(k) {\n\t\t\tresult.Insert(k)\n\t\t}\n\t}\n\treturn result\n}\n\n// IsDisjointOf return True if the set has no elements in common with other.\n// Sets are disjoint if and only if their intersection is the empty set.\nfunc (s BuiltinSet[K]) IsDisjointOf(other BuiltinSet[K]) bool {\n\tsmall, large := orderSet(s, other)\n\tfor k := range small {\n\t\tif large.Has(k) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// IsSubsetOf tests whether every element in the set is in other.\nfunc (s BuiltinSet[K]) IsSubsetOf(other BuiltinSet[K]) bool {\n\tif s.Len() > other.Len() {\n\t\treturn false\n\t}\n\tfor k := range s {\n\t\tif !other.Has(k) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// IsSupersetOf tests whether every element in other is in the set.\nfunc (s BuiltinSet[K]) IsSupersetOf(other BuiltinSet[K]) bool {\n\treturn other.IsSubsetOf(s)\n}\n"
  },
  {
    "path": "builtin_set_test.go",
    "content": "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(BuiltinSet[int])\n\t_ = Set[int](&s)\n}\n\nfunc Test_MakeBuiltinSet(t *testing.T) {\n\ts := make(BuiltinSet[string])\n\texpectEq(t, s.Len(), 0)\n\texpectEq(t, s.IsEmpty(), true)\n}\n\nfunc Test_MakeBuiltinSet2(t *testing.T) {\n\ts := BuiltinSet[string]{}\n\texpectEq(t, s.Len(), 0)\n\texpectEq(t, s.IsEmpty(), true)\n}\n\nfunc Test_SetOf(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\texpectEq(t, s.Len(), 2)\n}\n\nfunc Test_BuiltinSet_IsEmpty(t *testing.T) {\n\ts := make(BuiltinSet[string])\n\texpectEq(t, s.IsEmpty(), true)\n\ts.Insert(\"hello\")\n\texpectEq(t, s.IsEmpty(), false)\n}\n\nfunc Test_BuiltinSet_Clear(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\ts.Clear()\n\texpectTrue(t, s.IsEmpty())\n}\n\nfunc Test_BuiltinSet_String(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\texpectTrue(t, strings.HasPrefix(fmt.Sprintf(\"%v\", s), \"BuiltinSet[string]\"))\n}\n\nfunc Test_BuiltinSet_Has(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\texpectTrue(t, s.Has(\"hello\"))\n\texpectTrue(t, s.Has(\"world\"))\n\texpectFalse(t, s.Has(\"!\"))\n}\n\nfunc Test_BuiltinSet_Insert(t *testing.T) {\n\ts := make(BuiltinSet[string])\n\texpectTrue(t, s.Insert(\"hello\"))\n\texpectFalse(t, s.Insert(\"hello\"))\n\texpectEq(t, s.Has(\"world\"), false)\n\texpectTrue(t, s.Insert(\"world\"))\n\texpectEq(t, s.Has(\"hello\"), true)\n\texpectEq(t, s.Len(), 2)\n}\n\nfunc Test_BuiltinSet_InsertN(t *testing.T) {\n\ts := make(BuiltinSet[string])\n\texpectEq(t, s.InsertN(\"hello\", \"world\"), 2)\n\texpectEq(t, s.Len(), 2)\n}\n\nfunc Test_BuiltinSet_Remove(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\texpectTrue(t, s.Remove(\"hello\"))\n\texpectEq(t, s.Len(), 1)\n\texpectFalse(t, s.Remove(\"hello\"))\n\texpectEq(t, s.Len(), 1)\n\texpectTrue(t, s.Remove(\"world\"))\n\texpectEq(t, s.Len(), 0)\n}\n\nfunc Test_BuiltinSet_Delete(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\ts.Delete(\"hello\")\n\texpectEq(t, s.Len(), 1)\n\ts.Delete(\"hello\")\n\texpectEq(t, s.Len(), 1)\n\ts.Delete(\"world\")\n\texpectEq(t, s.Len(), 0)\n}\n\nfunc Test_BuiltinSet_RemoveN(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\texpectEq(t, s.RemoveN(\"hello\", \"world\"), 2)\n\texpectFalse(t, s.Remove(\"world\"))\n\texpectTrue(t, s.IsEmpty())\n}\n\nfunc Test_BuiltinSet_Keys(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\tks := s.Keys()\n\texpectEq(t, 2, len(ks))\n}\n\nfunc Test_BuiltinSet_For(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\tfor v := range s {\n\t\texpectTrue(t, v == \"hello\" || v == \"world\")\n\t}\n}\n\nfunc Test_BuiltinSet_ForEach(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\tc := 0\n\ts.ForEach(func(string) {\n\t\tc++\n\t})\n\texpectEq(t, c, 2)\n}\n\nfunc Test_BuiltinSet_ForEachIf(t *testing.T) {\n\ts := SetOf(\"hello\", \"world\")\n\tc := 0\n\ts.ForEachIf(func(string) bool {\n\t\tc++\n\t\treturn false\n\t})\n\texpectLt(t, c, 2)\n}\n\nfunc Test_BuiltinSet_Update(t *testing.T) {\n\ts := SetOf(1, 2, 3)\n\ts.Update(SetOf(3, 4))\n\texpectEq(t, s.Len(), 4)\n\texpectTrue(t, s.Has(4))\n}\n\nfunc Test_BuiltinSet_Union(t *testing.T) {\n\ts := SetOf(1, 2, 3)\n\ts2 := s.Union(SetOf(3, 4))\n\texpectEq(t, s2.Len(), 4)\n\texpectTrue(t, s2.Has(4))\n}\n\nfunc Test_BuiltinSet_Intersection(t *testing.T) {\n\ts := SetOf(1, 2, 3).Intersection(SetOf(3, 4))\n\texpectEq(t, s.Len(), 1)\n\texpectTrue(t, s.Has(3))\n\ts = SetOf(3, 4).Intersection(SetOf(1, 2, 3))\n\texpectEq(t, s.Len(), 1)\n\texpectTrue(t, s.Has(3))\n}\n\nfunc Test_BuiltinSet_Difference(t *testing.T) {\n\ts := SetOf(1, 2, 3).Difference(SetOf(3, 4))\n\texpectEq(t, s.Len(), 2)\n\texpectTrue(t, s.Has(1))\n\texpectTrue(t, s.Has(2))\n\ts = SetOf(1, 2).Difference(SetOf(3, 4))\n\texpectEq(t, s.Len(), 2)\n\texpectTrue(t, s.Has(1))\n\texpectTrue(t, s.Has(2))\n}\n\nfunc Test_BuiltinSet_IsDisjointOf(t *testing.T) {\n\ts1 := SetOf(1, 2, 3)\n\ts2 := SetOf(3, 4)\n\texpectFalse(t, s1.IsDisjointOf(s2))\n\texpectTrue(t, s1.IsDisjointOf(SetOf(4, 5)))\n}\n\nfunc Test_BuiltinSet_IsSubsetOf(t *testing.T) {\n\texpectTrue(t, SetOf[int]().IsSubsetOf(SetOf[int]()))\n\texpectTrue(t, SetOf[int]().IsSubsetOf(SetOf(1)))\n\texpectTrue(t, SetOf(1, 2, 3).IsSubsetOf(SetOf(1, 2, 3)))\n\texpectTrue(t, SetOf(1, 2).IsSubsetOf(SetOf(1, 2, 3)))\n\texpectFalse(t, SetOf(1, 2, 3).IsSubsetOf(SetOf(1, 2)))\n\texpectFalse(t, SetOf(1, 2).IsSubsetOf(SetOf(2, 3)))\n}\n\nfunc Test_BuiltinSet_IsSupersetOf(t *testing.T) {\n\texpectTrue(t, SetOf[int]().IsSupersetOf(SetOf[int]()))\n\texpectTrue(t, SetOf(1).IsSupersetOf(SetOf[int]()))\n\texpectTrue(t, SetOf(1, 2, 3).IsSupersetOf(SetOf(1, 2, 3)))\n\texpectTrue(t, SetOf(1, 2, 3).IsSupersetOf(SetOf(1, 2)))\n\texpectFalse(t, SetOf(1, 2).IsSupersetOf(SetOf(1, 2, 3)))\n\texpectFalse(t, SetOf(1, 2).IsSupersetOf(SetOf(2, 3)))\n}\n"
  },
  {
    "path": "check.bat",
    "content": "go build\n\ngo test ./... -coverprofile=coverage.out\n\ngolint\n\ngosec .\n\ngo tool cover -html=coverage.out\n"
  },
  {
    "path": "check.sh",
    "content": "#!/bin/bash\n\nset -e\n\ngo build\n\ngo test ./... -coverprofile=coverage.out\n\ngolint\n\ngosec .\n\ngo tool cover -html=coverage.out\n"
  },
  {
    "path": "compare.go",
    "content": "package stl4go\n\n// Equal returns whether two slices are equal.\n// Return true if they are the same length and all elements are equal.\n//\n// Complexity: O(min(len(a), len(b))).\nfunc Equal[T comparable](a, b []T) bool {\n\tif len(a) != len(b) {\n\t\treturn false\n\t}\n\tfor i := range a {\n\t\tif a[i] != b[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// Compare compares each elements in a and b.\n//\n// return 0 if they are equals,\n// return 1 if a > b,\n// return -1 if a < b.\n//\n// Complexity: O(min(len(a), len(b))).\nfunc Compare[E Ordered](a, b []E) int {\n\tbl := len(b)\n\tfor i, v1 := range a {\n\t\tif i >= bl {\n\t\t\treturn 1\n\t\t}\n\t\tv2 := b[i]\n\t\tswitch {\n\t\tcase v1 < v2:\n\t\t\treturn -1\n\t\tcase v1 > v2:\n\t\t\treturn 1\n\t\t}\n\t}\n\tif len(a) < bl {\n\t\treturn -1\n\t}\n\treturn 0\n}\n"
  },
  {
    "path": "compare_test.go",
    "content": "package stl4go\n\nimport \"testing\"\n\nfunc Test_Equal(t *testing.T) {\n\texpectTrue(t, Equal([]int{}, []int{}))\n\texpectTrue(t, Equal([]int{1, 2, 3}, []int{1, 2, 3}))\n\texpectFalse(t, Equal([]int{1, 2}, []int{1, 2, 3}))\n\texpectFalse(t, Equal([]int{1, 2, 2}, []int{1, 2, 3}))\n}\n\nfunc Test_Compare(t *testing.T) {\n\texpectEq(t, Compare([]int{}, []int{}), 0)\n\texpectEq(t, Compare([]int{1, 2, 3}, []int{1, 2, 3}), 0)\n\texpectEq(t, Compare([]int{1, 2, 2}, []int{1, 2, 3}), -1)\n\texpectEq(t, Compare([]int{1, 2, 4}, []int{1, 2, 3}), 1)\n\texpectEq(t, Compare([]int{1, 2}, []int{1, 2, 3}), -1)\n\texpectEq(t, Compare([]int{1, 2, 3}, []int{1, 2}), 1)\n}\n"
  },
  {
    "path": "compute.go",
    "content": "package stl4go\n\n// SumAs summarize all elements in a.\n// returns the result as type R, this is useful when T is too small to hold the result.\n// Complexity: O(len(a)).\nfunc SumAs[R, T Numeric](a []T) R {\n\tswitch zero := T(0); any(zero).(type) {\n\tcase int8, int16, int32, int, int64:\n\t\tvar total int64\n\t\tfor _, v := range a {\n\t\t\ttotal += int64(v)\n\t\t}\n\t\treturn R(total)\n\tcase uint8, uint16, uint32, uint, uint64, uintptr:\n\t\tvar total uint64\n\t\tfor _, v := range a {\n\t\t\ttotal += uint64(v)\n\t\t}\n\t\treturn R(total)\n\tdefault:\n\t\tvar total float64\n\t\tfor _, v := range a {\n\t\t\ttotal += float64(v)\n\t\t}\n\t\treturn R(total)\n\t}\n}\n\n// Sum summarize all elements in a.\n// returns the result as type R, you should use SumAs if T can't hold the result.\n// Complexity: O(len(a)).\nfunc Sum[T Numeric](a []T) T {\n\treturn SumAs[T](a)\n}\n\n// AverageAs returns the average value of a as type R.\nfunc AverageAs[R, T Numeric](a []T) R {\n\treturn SumAs[R](a) / R(len(a))\n}\n\n// Average returns the average value of a.\nfunc Average[T Numeric](a []T) T {\n\tvar zero T // NOTE: convert 0 to interface have no malloc\n\tswitch any(zero).(type) {\n\tcase int, int8, uint8, int16, uint16, int32, uint32:\n\t\treturn T(AverageAs[int64](a))\n\tcase uint64:\n\t\treturn T(AverageAs[uint64](a))\n\tcase float32, float64:\n\t\treturn T(AverageAs[float64](a))\n\t}\n\t// int64, uint64, uintptr ...\n\treturn AverageAs[T](a)\n}\n\n// Count returns the number of elements in the slice equals to x.\n//\n// Complexity: O(len(a)).\nfunc Count[T comparable](a []T, x T) int {\n\tc := 0\n\tfor _, v := range a {\n\t\tif v == x {\n\t\t\tc++\n\t\t}\n\t}\n\treturn c\n}\n\n// CountIf returns the number of elements in the slice which pred returns true.\n//\n// Complexity: O(len(a)).\nfunc CountIf[T comparable](a []T, pred func(T) bool) int {\n\tc := 0\n\tfor _, v := range a {\n\t\tif pred(v) {\n\t\t\tc++\n\t\t}\n\t}\n\treturn c\n}\n"
  },
  {
    "path": "compute_test.go",
    "content": "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\ta := Range[uint8](1, 101)\n\t\texpectEq(t, SumAs[int](a), 5050)\n\t})\n\n\tt.Run(\"sum int to uint8\", func(t *testing.T) {\n\t\ta := Range[int](1, 101)\n\t\texpectEq(t, SumAs[uint8](a), uint8(5050%256))\n\t})\n\n\tt.Run(\"sum int64 to float64\", func(t *testing.T) {\n\t\ta := Range[int64](1, 101)\n\t\texpectEq(t, SumAs[float64](a), 5050.)\n\t})\n\n\tt.Run(\"sum float64 to int64\", func(t *testing.T) {\n\t\ta := Range[float64](1.1, 101.1)\n\t\texpectEq(t, SumAs[int](a), 101.2*50) // 5060\n\t})\n}\n\nfunc Test_Sum(t *testing.T) {\n\ta := Range(1, 101)\n\texpectEq(t, Sum(a), 5050)\n}\n\nfunc Test_Average(t *testing.T) {\n\ta := Range(1, 101)\n\texpectEq(t, Average(a), 50)\n}\n\nfunc Test_AverageAs(t *testing.T) {\n\ta := []int{1, 0}\n\texpectEq(t, AverageAs[float64](a), 0.5)\n}\n\nfunc Test_Average_U64(t *testing.T) {\n\ta := Range[uint64](0, 101)\n\texpectEq(t, Average(a), 50)\n}\n\nfunc Test_Average_Float(t *testing.T) {\n\ta := Range(0.0, 101.0)\n\texpectEq(t, Average(a), 50.0)\n}\n\nfunc Test_Average_SmallType(t *testing.T) {\n\ta := Range[uint8](0, 101)\n\texpectEq(t, Average(a), 50)\n}\n\nfunc Test_Average_UintPtr(t *testing.T) {\n\ta := Range[uintptr](0, 101)\n\texpectEq(t, Average(a), 50)\n}\n\nfunc Test_Average_Signed(t *testing.T) {\n\ta := []int{-2, 1, -1, 2, 1, -1, 0}\n\texpectEq(t, Average(a), 0)\n}\n\nfunc Test_Count(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 3}\n\texpectEq(t, Count(a, 3), 2)\n\texpectEq(t, CountIf(pos, isNegative), 0)\n\texpectEq(t, CountIf(neg, isNegative), 5)\n\texpectEq(t, CountIf(mix, isNegative), 2)\n}\n"
  },
  {
    "path": "container.go",
    "content": "package stl4go\n\n// Container is a holder object that stores a collection of other objects.\ntype Container interface {\n\tIsEmpty() bool // IsEmpty checks if the container has no elements.\n\tLen() int      // Len returns the number of elements in the container.\n\tClear()        // Clear erases all elements from the container. After this call, Len() returns zero.\n}\n\n// Map is a associative container that contains key-value pairs with unique keys.\ntype Map[K any, V any] interface {\n\tContainer\n\tHas(K) bool                        // Checks whether the container contains element with specific key.\n\tFind(K) *V                         // Finds element with specific key.\n\tInsert(K, V)                       // Inserts a key-value pair in to the container or replace existing value.\n\tRemove(K) bool                     // Remove element with specific key.\n\tForEach(func(K, V))                // Iterate the container.\n\tForEachIf(func(K, V) bool)         // Iterate the container, stops when the callback returns false.\n\tForEachMutable(func(K, *V))        // Iterate the container, *V is mutable.\n\tForEachMutableIf(func(K, *V) bool) // Iterate the container, *V is mutable, stops when the callback returns false.\n}\n\n// Set is a containers that store unique elements.\ntype Set[K any] interface {\n\tContainer\n\tHas(K) bool             // Checks whether the container contains element with specific key.\n\tInsert(K) bool          // Inserts a element in to the container or replace existing value.\n\tInsertN(...K) int       // Inserts multiple elements in to the container or replace existing value.\n\tRemove(K) bool          // Remove specific element, return true if element was in the container.\n\tRemoveN(...K) int       // Remove multiple elements, return the number of removed elements.\n\tForEach(func(K))        // Iterate the container.\n\tForEachIf(func(K) bool) // Iterate the container, stops when the callback returns false.\n}\n\n// SortedMap is a Map that provides a total ordering on its keys.\ntype SortedMap[K any, V any] interface {\n\tMap[K, V]\n\t// LowerBound returns an iterator to the first element in the container that\n\t// does not satisfy element.key < value (i.e. greater or equal to),\n\t// or a end iterator if no such element is found.\n\tLowerBound(K) MutableMapIterator[K, V]\n\n\t// UpperBound returns an iterator to the first element in the container that\n\t// does not satisfy value < element.key (i.e. strictly greater),\n\t// or a end iterator if no such element is found.\n\tUpperBound(K) MutableMapIterator[K, V]\n\n\t// FindRange returns an iterator in range [first, last) (last is not included).\n\tFindRange(K, K) MutableMapIterator[K, V]\n}\n\n// SortedSet is a Set that provides a total ordering on its elements.\ntype SortedSet[K any] interface {\n\tSet[K]\n\n\t// LowerBound returns an iterator to the first element in the container that\n\t// does not satisfy element < value (i.e. greater or equal to),\n\t// or a end iterator if no such element is found.\n\tLowerBound(K) Iterator[K]\n\n\t// UpperBound returns an iterator to the first element in the container that\n\t// does not satisfy value < element (i.e. strictly greater),\n\t// or a end iterator if no such element is found.\n\tUpperBound(K) Iterator[K]\n\n\t// FindRange returns an iterator in range [first, last) (last is not included).\n\tFindRange(K, K) Iterator[K]\n}\n\n// Queue is a container that can add elements to one end and remove elements from the other end.\ntype Queue[T any] interface {\n\tContainer\n\tFront()            // Front returns the first element in the container.\n\tBack()             // Back returns the last element in the container.\n\tPush(T)            // Push pushes an element at the back of the container.\n\tPop() T            // Pop popups a front from the back of the container.\n\tTryPop() (T, bool) // TryPop tries to popup a element from the front of the container.\n}\n\n// Deque is a container that can add and remove elements from both ends.\ntype Deque[T any] interface {\n\tContainer\n\tFront() T               // Front returns the first element in the container.\n\tBack() T                // Back returns the last element in the container.\n\tPushFront(T)            // PushBack pushes an element at the front of the container.\n\tPushBack(T)             // PushBack pushes an element at the back of the container.\n\tPopFront() T            // PopBack popups a front from the back of the container.\n\tPopBack() T             // PopBack popups a element from the back of the container.\n\tTryPopFront() (T, bool) // TryPopFront tries to popup a element from the front of the container.\n\tTryPopBack() (T, bool)  // TryPopBack tries to popup a element from the back of the container.\n}\n"
  },
  {
    "path": "container_test.go",
    "content": "package stl4go\n"
  },
  {
    "path": "dlist.go",
    "content": "package stl4go\n\nimport \"fmt\"\n\n// DList is a doubly linked list.\ntype DList[T any] struct {\n\thead   *dListNode[T]\n\tlength int\n}\n\ntype dListNode[T any] struct {\n\tprev, next *dListNode[T]\n\tvalue      T\n}\n\n// DListOf make a new DList from a serial of values.\nfunc DListOf[T any](vs ...T) DList[T] {\n\tl := DList[T]{}\n\tfor _, v := range vs {\n\t\tl.PushBack(v)\n\t}\n\treturn l\n}\n\n// Clear cleanup the list.\nfunc (l *DList[T]) Clear() {\n\tif l.head != nil {\n\t\tl.head.prev = l.head\n\t\tl.head.next = l.head\n\t}\n\tl.length = 0\n}\n\n// Len return the length of the list.\nfunc (l *DList[T]) Len() int {\n\treturn l.length\n}\n\n// IsEmpty return whether the list is empty.\nfunc (l *DList[T]) IsEmpty() bool {\n\treturn l.length == 0\n}\n\n// String convert the list to string.\nfunc (l *DList[T]) String() string {\n\treturn fmt.Sprintf(\"DList[%v]\", nameOfType[T]())\n}\n\ntype dlistIterator[T any] struct {\n\tdl   *DList[T]\n\tnode *dListNode[T]\n}\n\nfunc (it *dlistIterator[T]) IsNotEnd() bool {\n\treturn it.node != it.dl.head\n}\n\nfunc (it *dlistIterator[T]) MoveToNext() {\n\tit.node = it.node.next\n}\n\nfunc (it *dlistIterator[T]) Value() T {\n\treturn it.node.value\n}\n\nfunc (it *dlistIterator[T]) Pointer() *T {\n\treturn &it.node.value\n}\n\n// Iterate returns an iterator to the first element in the list.\nfunc (l *DList[T]) Iterate() MutableIterator[T] {\n\tnode := l.head\n\tif node != nil {\n\t\tnode = node.next\n\t}\n\treturn &dlistIterator[T]{l, node}\n}\n\n// Front returns the first element in the container.\nfunc (l *DList[T]) Front() T {\n\tif l.IsEmpty() {\n\t\tpanic(\"!IsEmpty\")\n\t}\n\treturn l.head.next.value\n}\n\n// Back returns the last element in the container.\nfunc (l *DList[T]) Back() T {\n\tif l.IsEmpty() {\n\t\tpanic(\"!IsEmpty\")\n\t}\n\treturn l.head.prev.value\n}\n\n// PushFront pushes an element at the front of the list.\nfunc (l *DList[T]) PushFront(val T) {\n\tl.ensureHead()\n\tn := dListNode[T]{l.head, l.head.next, val}\n\tl.head.next.prev = &n\n\tl.head.next = &n\n\tl.length++\n}\n\n// PushBack pushes an element at the back of the list.\nfunc (l *DList[T]) PushBack(val T) {\n\tl.ensureHead()\n\tn := dListNode[T]{l.head.prev, l.head, val}\n\tl.head.prev.next = &n\n\tl.head.prev = &n\n\tl.length++\n}\n\n// PopFront popups an element from the front of the list.\nfunc (l *DList[T]) PopFront() T {\n\tr, ok := l.TryPopFront()\n\tif !ok {\n\t\tpanic(\"DList.PopFront: empty list\")\n\t}\n\treturn r\n}\n\n// PopBack popups an element from the back of the list.\nfunc (l *DList[T]) PopBack() T {\n\tr, ok := l.TryPopBack()\n\tif !ok {\n\t\tpanic(\"DList.PopBack: empty list\")\n\t}\n\treturn r\n}\n\n// TryPopFront tries to pop up an element from the front of the list.\nfunc (l *DList[T]) TryPopFront() (T, bool) {\n\tvar val T\n\tif l.IsEmpty() {\n\t\treturn val, false\n\t}\n\tnode := l.head.next\n\tval = node.value\n\tl.head.next = node.next\n\tl.head.next.prev = l.head\n\tnode.prev = nil\n\tnode.next = nil\n\tl.length--\n\treturn val, true\n}\n\n// TryPopBack tries to pop up an element from the back of the list.\nfunc (l *DList[T]) TryPopBack() (T, bool) {\n\tvar val T\n\tif l.IsEmpty() {\n\t\treturn val, false\n\t}\n\tnode := l.head.prev\n\tval = node.value\n\tl.head.prev = l.head.prev.prev\n\tl.head.prev.next = l.head\n\tnode.prev = nil\n\tnode.next = nil\n\tl.length--\n\treturn val, true\n}\n\n// ForEach iterate the list, apply each element to the cb callback function.\nfunc (l *DList[T]) ForEach(cb func(val T)) {\n\tif l.IsEmpty() {\n\t\treturn\n\t}\n\tfor n := l.head.next; n != l.head; n = n.next {\n\t\tcb(n.value)\n\t}\n}\n\n// ForEachIf iterate the list, apply each element to the cb callback function,\n// stop if cb returns false.\nfunc (l *DList[T]) ForEachIf(cb func(val T) bool) {\n\tif l.IsEmpty() {\n\t\treturn\n\t}\n\tfor n := l.head.next; n != l.head; n = n.next {\n\t\tif !cb(n.value) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// ForEachMutable iterate the list, apply pointer of each element to the cb callback function.\nfunc (l *DList[T]) ForEachMutable(cb func(val *T)) {\n\tif l.IsEmpty() {\n\t\treturn\n\t}\n\tfor n := l.head.next; n != l.head; n = n.next {\n\t\tcb(&n.value)\n\t}\n}\n\n// ForEachMutableIf iterate the list, apply pointer of each element to the cb callback function,\n// stop if cb returns false.\nfunc (l *DList[T]) ForEachMutableIf(cb func(val *T) bool) {\n\tif l.IsEmpty() {\n\t\treturn\n\t}\n\tfor n := l.head.next; n != l.head; n = n.next {\n\t\tif !cb(&n.value) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// ensureHead ensure head is valid.\nfunc (l *DList[T]) ensureHead() {\n\tif l.head == nil {\n\t\tl.head = &dListNode[T]{}\n\t\tl.head.prev = l.head\n\t\tl.head.next = l.head\n\t}\n}\n"
  },
  {
    "path": "dlist_queue.go",
    "content": "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// NewDListQueue create a new Queue object.\nfunc NewDListQueue[T any]() *DListQueue[T] {\n\tq := DListQueue[T]{}\n\treturn &q\n}\n\n// Len implements the Container interface.\nfunc (q *DListQueue[T]) Len() int {\n\treturn q.list.Len()\n}\n\n// IsEmpty implements the Container interface.\nfunc (q *DListQueue[T]) IsEmpty() bool {\n\treturn q.list.IsEmpty()\n}\n\n// Clear implements the Container interface.\nfunc (q *DListQueue[T]) Clear() {\n\tq.list.Clear()\n}\n\n// Len implements the fmt.Stringer interface.\nfunc (q *DListQueue[T]) String() string {\n\treturn fmt.Sprintf(\"Queue[%v]\", nameOfType[T]())\n}\n\n// Front returns the first element in the container.\nfunc (q *DListQueue[T]) Front() T {\n\treturn q.list.Front()\n}\n\n// Back returns the last element in the container.\nfunc (q *DListQueue[T]) Back() T {\n\treturn q.list.Back()\n}\n\n// PushFront pushed an element to the front of the queue.\nfunc (q *DListQueue[T]) PushFront(val T) {\n\tq.list.PushFront(val)\n}\n\n// PushBack pushed an element to the back of the queue.\nfunc (q *DListQueue[T]) PushBack(val T) {\n\tq.list.PushBack(val)\n}\n\n// PopFront popups an element from the front of the queue.\nfunc (q *DListQueue[T]) PopFront() T {\n\treturn q.list.PopFront()\n}\n\n// PopBack popups an element from the back of the queue.\nfunc (q *DListQueue[T]) PopBack() T {\n\treturn q.list.PopBack()\n}\n\n// TryPopFront tries popuping an element from the front of the queue.\nfunc (q *DListQueue[T]) TryPopFront() (T, bool) {\n\treturn q.list.TryPopFront()\n}\n\n// TryPopBack tries popuping an element from the back of the queue.\nfunc (q *DListQueue[T]) TryPopBack() (T, bool) {\n\treturn q.list.TryPopBack()\n}\n"
  },
  {
    "path": "dlist_queue_test.go",
    "content": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_Queue_Interface(t *testing.T) {\n\tq := NewDListQueue[int]()\n\t_ = Deque[int](q)\n}\n\nfunc Test_Queue_New(t *testing.T) {\n\tq := NewDListQueue[int]()\n\texpectTrue(t, q.IsEmpty())\n\texpectEq(t, q.Len(), 0)\n}\n\nfunc Test_Queue_Clear(t *testing.T) {\n\tq := NewDListQueue[int]()\n\tq.PushBack(1)\n\tq.Clear()\n\texpectTrue(t, q.IsEmpty())\n\texpectEq(t, q.Len(), 0)\n}\n\nfunc Test_Queue_String(t *testing.T) {\n\tq := NewDListQueue[int]()\n\texpectEq(t, q.String(), \"Queue[int]\")\n}\n\nfunc Test_Queue_Front_Back(t *testing.T) {\n\tq := NewDListQueue[int]()\n\texpectPanic(t, func() { q.Front() })\n\texpectPanic(t, func() { q.Back() })\n\tq.PushBack(1)\n\tq.PushBack(2)\n\texpectEq(t, q.Front(), 1)\n\texpectEq(t, q.Back(), 2)\n}\n\nfunc Test_Queue_PushFront(t *testing.T) {\n\tq := NewDListQueue[int]()\n\tq.PushFront(1)\n\texpectFalse(t, q.IsEmpty())\n\texpectEq(t, q.Len(), 1)\n}\n\nfunc Test_Queue_PushBack(t *testing.T) {\n\tq := NewDListQueue[int]()\n\tq.PushBack(1)\n\texpectFalse(t, q.IsEmpty())\n\texpectEq(t, q.Len(), 1)\n}\n\nfunc Test_Queue_TryPopFront(t *testing.T) {\n\tq := NewDListQueue[int]()\n\t_, ok := q.TryPopFront()\n\texpectFalse(t, ok)\n}\nfunc Test_Queue_TryPopBack(t *testing.T) {\n\tq := NewDListQueue[int]()\n\t_, ok := q.TryPopBack()\n\texpectFalse(t, ok)\n}\n\nfunc Test_Queue_PushFront_PopFront(t *testing.T) {\n\tq := NewDListQueue[int]()\n\tq.PushFront(1)\n\tq.PushFront(2)\n\texpectEq(t, q.PopFront(), 2)\n\texpectEq(t, q.PopFront(), 1)\n}\n\nfunc Test_Queue_PushFront_PopBack(t *testing.T) {\n\tq := NewDListQueue[int]()\n\tq.PushFront(1)\n\texpectEq(t, q.PopBack(), 1)\n}\n\nfunc Test_Queue_PushBack_PopFront(t *testing.T) {\n\tq := NewDListQueue[int]()\n\tq.PushBack(1)\n\texpectEq(t, q.PopFront(), 1)\n}\n\nfunc Test_Queue_PushBack_PopBack(t *testing.T) {\n\tq := NewDListQueue[int]()\n\tq.PushBack(1)\n\texpectEq(t, q.PopBack(), 1)\n}\n"
  },
  {
    "path": "dlist_test.go",
    "content": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_Dlist_Interface(t *testing.T) {\n\t_ = Container(&DList[int]{})\n}\n\nfunc Test_DList_New(t *testing.T) {\n\tl := DList[int]{}\n\texpectTrue(t, l.IsEmpty())\n\texpectEq(t, l.Len(), 0)\n}\n\nfunc Test_DListOf(t *testing.T) {\n\tl := DListOf(1, 2, 3)\n\texpectFalse(t, l.IsEmpty())\n\texpectEq(t, l.Len(), 3)\n}\n\nfunc Test_DList_String(t *testing.T) {\n\tl := DList[int]{}\n\texpectEq(t, l.String(), \"DList[int]\")\n}\n\nfunc Test_DList_Iterate(t *testing.T) {\n\tl := DListOf(1, 2, 3)\n\ti := 1\n\tfor it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n\t\texpectEq(t, it.Value(), i)\n\t\texpectEq(t, *it.Pointer(), i)\n\t\ti++\n\t}\n\texpectEq(t, i, 4)\n}\n\nfunc Test_DList_Iterate_Empty(t *testing.T) {\n\tl := DList[int]{}\n\ti := 0\n\tfor it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n\t\ti++\n\t}\n\texpectEq(t, i, 0)\n}\n\nfunc Test_DList_FrontBack(t *testing.T) {\n\tl := DListOf(1, 2, 3)\n\texpectEq(t, l.Front(), 1)\n\texpectEq(t, l.Back(), 3)\n}\n\nfunc Test_DList_PushFront(t *testing.T) {\n\tl := DList[int]{}\n\tl.PushFront(1)\n\texpectFalse(t, l.IsEmpty())\n\texpectEq(t, l.Len(), 1)\n}\n\nfunc Test_DList_PushBack(t *testing.T) {\n\tl := DList[int]{}\n\tl.PushBack(1)\n\texpectFalse(t, l.IsEmpty())\n\texpectEq(t, l.Len(), 1)\n}\n\nfunc Test_DList_PopFront(t *testing.T) {\n\tl := DListOf(1, 2, 3, 4)\n\texpectEq(t, l.PopFront(), 1)\n\texpectEq(t, l.PopFront(), 2)\n\n\tn, ok := l.TryPopFront()\n\texpectEq(t, n, 3)\n\texpectTrue(t, ok)\n\n\tn, ok = l.TryPopBack()\n\texpectEq(t, n, 4)\n\texpectTrue(t, ok)\n\n\tn, ok = l.TryPopFront()\n\texpectFalse(t, ok)\n\texpectPanic(t, func() { l.PopFront() })\n}\n\nfunc Test_DList_PopBack(t *testing.T) {\n\tl := DListOf(1, 2, 3, 4)\n\texpectEq(t, l.PopBack(), 4)\n\texpectEq(t, l.PopBack(), 3)\n\n\tn, ok := l.TryPopBack()\n\texpectTrue(t, ok)\n\texpectEq(t, n, 2)\n\n\tn, ok = l.TryPopFront()\n\texpectTrue(t, ok)\n\texpectEq(t, n, 1)\n\n\tn, ok = l.TryPopBack()\n\texpectFalse(t, ok)\n\texpectPanic(t, func() { l.PopBack() })\n}\n\nfunc Test_DList_PushBack_PopFront(t *testing.T) {\n\tl := DList[int]{}\n\tl.PushBack(1)\n\tl.PushBack(2)\n\n\tv := l.PopFront()\n\texpectEq(t, v, 1)\n\texpectEq(t, l.PopFront(), 2)\n}\n\nfunc Test_DList_PushBack_PopBack(t *testing.T) {\n\tl := DList[int]{}\n\tl.PushBack(1)\n\tv := l.PopBack()\n\texpectEq(t, v, 1)\n}\n\nfunc Test_DList_PushFront_PopBack(t *testing.T) {\n\tl := DList[int]{}\n\tl.PushFront(1)\n\tv := l.PopBack()\n\texpectEq(t, v, 1)\n}\n\nfunc Test_DList_PushFront_PopFront(t *testing.T) {\n\tl := DList[int]{}\n\tl.PushFront(1)\n\tv := l.PopFront()\n\texpectEq(t, v, 1)\n}\n\nfunc Test_DList_ForEach(t *testing.T) {\n\ta := []int{1, 2, 3}\n\tl := DListOf(a...)\n\tvar b []int\n\tl.ForEach(func(n int) {\n\t\tb = append(b, n)\n\t})\n\texpectEq(t, len(b), 3)\n\texpectTrue(t, Equal(a, b))\n}\n\nfunc Test_DList_ForEachIf(t *testing.T) {\n\tl := DListOf(1, 2, 3)\n\tc := 0\n\tl.ForEachIf(func(n int) bool {\n\t\tc = n\n\t\treturn n != 2\n\t})\n\texpectEq(t, c, 2)\n}\n\nfunc Test_DList_ForEachMutable(t *testing.T) {\n\ta := []int{1, 2, 3}\n\tl := DListOf(a...)\n\tl.ForEachMutable(func(n *int) {\n\t\t*n = -*n\n\t})\n\tvar b []int\n\tl.ForEach(func(n int) {\n\t\tb = append(b, n)\n\t})\n\texpectEq(t, len(b), 3)\n\tfor i := range b {\n\t\texpectEq(t, a[i], -b[i])\n\t}\n}\n\nfunc Test_DList_ForEachMutableIf(t *testing.T) {\n\tl := DListOf(1, 2, 3)\n\tc := 0\n\tl.ForEachMutableIf(func(n *int) bool {\n\t\tc = *n\n\t\treturn *n != 2\n\t})\n\texpectEq(t, c, 2)\n}\n\nfunc Test_DList_ForEach_EmptyOK(t *testing.T) {\n\tl := DList[int]{}\n\tl.ForEach(func(n int) {})\n\tl.ForEachIf(func(n int) bool { return true })\n\tl.ForEachMutable(func(n *int) {})\n\tl.ForEachMutableIf(func(n *int) bool { return true })\n}\n\nfunc Benchmark_DList_Iterate(b *testing.B) {\n\tl := DListOf(Range(1, 10000)...)\n\tb.Run(\"Iterator\", func(b *testing.B) {\n\t\tsum := 0\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n\t\t\t\tsum += it.Value()\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"ForEach\", func(b *testing.B) {\n\t\tsum := 0\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tl.ForEach(func(val int) { sum += val })\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "doc.go",
    "content": "// Package stl4go is a generic container and algorithm library for go.\npackage stl4go\n"
  },
  {
    "path": "functor.go",
    "content": "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// Greater wraps the '>' operator for ordered types.\nfunc Greater[T Ordered](a, b T) bool {\n\treturn a > b\n}\n\n// OrderedCompare provide default CompareFn for ordered types.\nfunc OrderedCompare[T Ordered](a, b T) int {\n\tif a < b {\n\t\treturn -1\n\t}\n\tif a > b {\n\t\treturn 1\n\t}\n\treturn 0\n}\n"
  },
  {
    "path": "generate.go",
    "content": "package stl4go\n\n// Range make a []T filled with values in the `[first, last)` sequence.\n// NOTE: the last is not included in the result.\n//\n// Complexity: O(last-first).\nfunc Range[T Numeric](first, last T) []T {\n\ta := make([]T, 0, int(last-first))\n\tfor v := first; v < last; v++ {\n\t\ta = append(a, v)\n\t}\n\treturn a\n}\n\n// Generate fill each element of `a`` with `gen()`.\n//\n// Complexity: O(len(a)).\nfunc Generate[T any](a []T, gen func() T) {\n\tfor i := range a {\n\t\ta[i] = gen()\n\t}\n}\n"
  },
  {
    "path": "generate_test.go",
    "content": "package stl4go\n\nimport \"testing\"\n\nfunc Test_Range(t *testing.T) {\n\ta := Range(0, 100)\n\texpectEq(t, len(a), 100)\n\texpectEq(t, a[0], 0)\n\texpectEq(t, a[99], 99)\n}\n\nfunc Test_Generate(t *testing.T) {\n\ta := make([]int, 100)\n\ti := -1\n\tGenerate(a, func() int { i++; return i })\n\tfor i, v := range a {\n\t\texpectEq(t, v, i)\n\t}\n}\n"
  },
  {
    "path": "generated_doc.md",
    "content": "<!-- markdownlint-disable -->\n<!-- gomarkdoc:embed:start -->\n\n<!-- Code generated by gomarkdoc. DO NOT EDIT -->\n\n# stl4go\n\n```go\nimport \"github.com/chen3feng/stl4go\"\n```\n\nPackage stl4go is a generic container and algorithm library for go.\n\n## Index\n\n- [func AllOf\\[T any\\]\\(a \\[\\]T, pred func\\(T\\) bool\\) bool](<#AllOf>)\n- [func AnyOf\\[T any\\]\\(a \\[\\]T, pred func\\(T\\) bool\\) bool](<#AnyOf>)\n- [func Average\\[T Numeric\\]\\(a \\[\\]T\\) T](<#Average>)\n- [func AverageAs\\[R, T Numeric\\]\\(a \\[\\]T\\) R](<#AverageAs>)\n- [func BinarySearch\\[T Ordered\\]\\(a \\[\\]T, value T\\) \\(index int, ok bool\\)](<#BinarySearch>)\n- [func BinarySearchFunc\\[T any\\]\\(a \\[\\]T, value T, less LessFn\\[T\\]\\) \\(index int, ok bool\\)](<#BinarySearchFunc>)\n- [func Compare\\[E Ordered\\]\\(a, b \\[\\]E\\) int](<#Compare>)\n- [func Copy\\[T any\\]\\(a \\[\\]T\\) \\[\\]T](<#Copy>)\n- [func CopyTo\\[T any\\]\\(a \\[\\]T, to \\[\\]T\\) \\[\\]T](<#CopyTo>)\n- [func Count\\[T comparable\\]\\(a \\[\\]T, x T\\) int](<#Count>)\n- [func CountIf\\[T comparable\\]\\(a \\[\\]T, pred func\\(T\\) bool\\) int](<#CountIf>)\n- [func DescSort\\[T Ordered\\]\\(a \\[\\]T\\)](<#DescSort>)\n- [func DescStableSort\\[T Ordered\\]\\(a \\[\\]T\\)](<#DescStableSort>)\n- [func Equal\\[T comparable\\]\\(a, b \\[\\]T\\) bool](<#Equal>)\n- [func Fill\\[T any\\]\\(a \\[\\]T, v T\\)](<#Fill>)\n- [func FillPattern\\[T any\\]\\(a \\[\\]T, pattern \\[\\]T\\)](<#FillPattern>)\n- [func FillZero\\[T any\\]\\(a \\[\\]T\\)](<#FillZero>)\n- [func Find\\[T comparable\\]\\(a \\[\\]T, x T\\) \\(index int, ok bool\\)](<#Find>)\n- [func FindIf\\[T any\\]\\(a \\[\\]T, cond func\\(T\\) bool\\) \\(index int, ok bool\\)](<#FindIf>)\n- [func Generate\\[T any\\]\\(a \\[\\]T, gen func\\(\\) T\\)](<#Generate>)\n- [func Greater\\[T Ordered\\]\\(a, b T\\) bool](<#Greater>)\n- [func Index\\[T comparable\\]\\(a \\[\\]T, x T\\) int](<#Index>)\n- [func IsDescSorted\\[T Ordered\\]\\(a \\[\\]T\\) bool](<#IsDescSorted>)\n- [func IsHeapFunc\\[T any\\]\\(array \\[\\]T, less LessFn\\[T\\]\\) bool](<#IsHeapFunc>)\n- [func IsMinHeap\\[T Ordered\\]\\(array \\[\\]T\\) bool](<#IsMinHeap>)\n- [func IsSorted\\[T Ordered\\]\\(a \\[\\]T\\) bool](<#IsSorted>)\n- [func Less\\[T Ordered\\]\\(a, b T\\) bool](<#Less>)\n- [func LowerBound\\[T Ordered\\]\\(a \\[\\]T, value T\\) int](<#LowerBound>)\n- [func LowerBoundFunc\\[T any\\]\\(a \\[\\]T, value T, less LessFn\\[T\\]\\) int](<#LowerBoundFunc>)\n- [func MakeHeapFunc\\[T any\\]\\(array \\[\\]T, less LessFn\\[T\\]\\)](<#MakeHeapFunc>)\n- [func MakeMinHeap\\[T Ordered\\]\\(array \\[\\]T\\)](<#MakeMinHeap>)\n- [func Max\\[T Ordered\\]\\(a, b T\\) T](<#Max>)\n- [func MaxN\\[T Ordered\\]\\(a ...T\\) T](<#MaxN>)\n- [func Min\\[T Ordered\\]\\(a, b T\\) T](<#Min>)\n- [func MinMax\\[T Ordered\\]\\(a, b T\\) \\(min, max T\\)](<#MinMax>)\n- [func MinMaxN\\[T Ordered\\]\\(a ...T\\) \\(min, max T\\)](<#MinMaxN>)\n- [func MinN\\[T Ordered\\]\\(a ...T\\) T](<#MinN>)\n- [func NoneOf\\[T any\\]\\(a \\[\\]T, pred func\\(T\\) bool\\) bool](<#NoneOf>)\n- [func OrderedCompare\\[T Ordered\\]\\(a, b T\\) int](<#OrderedCompare>)\n- [func PopHeapFunc\\[T any\\]\\(heap \\*\\[\\]T, less LessFn\\[T\\]\\) T](<#PopHeapFunc>)\n- [func PopMinHeap\\[T Ordered\\]\\(heap \\*\\[\\]T\\) T](<#PopMinHeap>)\n- [func PushHeapFunc\\[T any\\]\\(heap \\*\\[\\]T, v T, less LessFn\\[T\\]\\)](<#PushHeapFunc>)\n- [func PushMinHeap\\[T Ordered\\]\\(heap \\*\\[\\]T, v T\\)](<#PushMinHeap>)\n- [func Range\\[T Numeric\\]\\(first, last T\\) \\[\\]T](<#Range>)\n- [func Remove\\[T comparable\\]\\(a \\[\\]T, x T\\) \\[\\]T](<#Remove>)\n- [func RemoveCopy\\[T comparable\\]\\(a \\[\\]T, x T\\) \\[\\]T](<#RemoveCopy>)\n- [func RemoveHeapFunc\\[T any\\]\\(heap \\*\\[\\]T, i int, less LessFn\\[T\\]\\) T](<#RemoveHeapFunc>)\n- [func RemoveIf\\[T any\\]\\(a \\[\\]T, cond func\\(T\\) bool\\) \\[\\]T](<#RemoveIf>)\n- [func RemoveIfCopy\\[T any\\]\\(a \\[\\]T, cond func\\(T\\) bool\\) \\[\\]T](<#RemoveIfCopy>)\n- [func RemoveMinHeap\\[T Ordered\\]\\(heap \\*\\[\\]T, i int\\) T](<#RemoveMinHeap>)\n- [func Replace\\[T comparable\\]\\(a \\[\\]T, old, new T\\)](<#Replace>)\n- [func ReplaceIf\\[T any\\]\\(a \\[\\]T, pred func\\(v T\\) bool, new T\\)](<#ReplaceIf>)\n- [func Reverse\\[T any\\]\\(a \\[\\]T\\)](<#Reverse>)\n- [func ReverseCopy\\[T any\\]\\(a \\[\\]T\\) \\[\\]T](<#ReverseCopy>)\n- [func Shuffle\\[T any\\]\\(a \\[\\]T\\)](<#Shuffle>)\n- [func Sort\\[T Ordered\\]\\(a \\[\\]T\\)](<#Sort>)\n- [func SortFunc\\[T any\\]\\(a \\[\\]T, less func\\(x, y T\\) bool\\)](<#SortFunc>)\n- [func StableSort\\[T Ordered\\]\\(a \\[\\]T\\)](<#StableSort>)\n- [func StableSortFunc\\[T any\\]\\(a \\[\\]T, less func\\(x, y T\\) bool\\)](<#StableSortFunc>)\n- [func Sum\\[T Numeric\\]\\(a \\[\\]T\\) T](<#Sum>)\n- [func SumAs\\[R, T Numeric\\]\\(a \\[\\]T\\) R](<#SumAs>)\n- [func Transform\\[T any\\]\\(a \\[\\]T, op func\\(T\\) T\\)](<#Transform>)\n- [func TransformCopy\\[R any, T any\\]\\(a \\[\\]T, op func\\(T\\) R\\) \\[\\]R](<#TransformCopy>)\n- [func TransformTo\\[R any, T any\\]\\(a \\[\\]T, op func\\(T\\) R, b \\[\\]R\\) \\[\\]R](<#TransformTo>)\n- [func Unique\\[T comparable\\]\\(a \\[\\]T\\) \\[\\]T](<#Unique>)\n- [func UniqueCopy\\[T comparable\\]\\(a \\[\\]T\\) \\[\\]T](<#UniqueCopy>)\n- [func UpperBound\\[T Ordered\\]\\(a \\[\\]T, value T\\) int](<#UpperBound>)\n- [func UpperBoundFunc\\[T any\\]\\(a \\[\\]T, value T, less LessFn\\[T\\]\\) int](<#UpperBoundFunc>)\n- [type BuiltinSet](<#BuiltinSet>)\n  - [func SetOf\\[K comparable\\]\\(ks ...K\\) BuiltinSet\\[K\\]](<#SetOf>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Clear\\(\\)](<#BuiltinSet[K].Clear>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Delete\\(k K\\)](<#BuiltinSet[K].Delete>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Difference\\(other BuiltinSet\\[K\\]\\) BuiltinSet\\[K\\]](<#BuiltinSet[K].Difference>)\n  - [func \\(s BuiltinSet\\[K\\]\\) ForEach\\(cb func\\(k K\\)\\)](<#BuiltinSet[K].ForEach>)\n  - [func \\(s BuiltinSet\\[K\\]\\) ForEachIf\\(cb func\\(k K\\) bool\\)](<#BuiltinSet[K].ForEachIf>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Has\\(k K\\) bool](<#BuiltinSet[K].Has>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Insert\\(k K\\) bool](<#BuiltinSet[K].Insert>)\n  - [func \\(s BuiltinSet\\[K\\]\\) InsertN\\(ks ...K\\) int](<#BuiltinSet[K].InsertN>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Intersection\\(other BuiltinSet\\[K\\]\\) BuiltinSet\\[K\\]](<#BuiltinSet[K].Intersection>)\n  - [func \\(s BuiltinSet\\[K\\]\\) IsDisjointOf\\(other BuiltinSet\\[K\\]\\) bool](<#BuiltinSet[K].IsDisjointOf>)\n  - [func \\(s BuiltinSet\\[K\\]\\) IsEmpty\\(\\) bool](<#BuiltinSet[K].IsEmpty>)\n  - [func \\(s BuiltinSet\\[K\\]\\) IsSubsetOf\\(other BuiltinSet\\[K\\]\\) bool](<#BuiltinSet[K].IsSubsetOf>)\n  - [func \\(s BuiltinSet\\[K\\]\\) IsSupersetOf\\(other BuiltinSet\\[K\\]\\) bool](<#BuiltinSet[K].IsSupersetOf>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Keys\\(\\) \\[\\]K](<#BuiltinSet[K].Keys>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Len\\(\\) int](<#BuiltinSet[K].Len>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Remove\\(k K\\) bool](<#BuiltinSet[K].Remove>)\n  - [func \\(s BuiltinSet\\[K\\]\\) RemoveN\\(ks ...K\\) int](<#BuiltinSet[K].RemoveN>)\n  - [func \\(s BuiltinSet\\[K\\]\\) String\\(\\) string](<#BuiltinSet[K].String>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Union\\(other BuiltinSet\\[K\\]\\) BuiltinSet\\[K\\]](<#BuiltinSet[K].Union>)\n  - [func \\(s BuiltinSet\\[K\\]\\) Update\\(other BuiltinSet\\[K\\]\\)](<#BuiltinSet[K].Update>)\n- [type CompareFn](<#CompareFn>)\n- [type Container](<#Container>)\n- [type DList](<#DList>)\n  - [func DListOf\\[T any\\]\\(vs ...T\\) DList\\[T\\]](<#DListOf>)\n  - [func \\(l \\*DList\\[T\\]\\) Back\\(\\) T](<#DList[T].Back>)\n  - [func \\(l \\*DList\\[T\\]\\) Clear\\(\\)](<#DList[T].Clear>)\n  - [func \\(l \\*DList\\[T\\]\\) ForEach\\(cb func\\(val T\\)\\)](<#DList[T].ForEach>)\n  - [func \\(l \\*DList\\[T\\]\\) ForEachIf\\(cb func\\(val T\\) bool\\)](<#DList[T].ForEachIf>)\n  - [func \\(l \\*DList\\[T\\]\\) ForEachMutable\\(cb func\\(val \\*T\\)\\)](<#DList[T].ForEachMutable>)\n  - [func \\(l \\*DList\\[T\\]\\) ForEachMutableIf\\(cb func\\(val \\*T\\) bool\\)](<#DList[T].ForEachMutableIf>)\n  - [func \\(l \\*DList\\[T\\]\\) Front\\(\\) T](<#DList[T].Front>)\n  - [func \\(l \\*DList\\[T\\]\\) IsEmpty\\(\\) bool](<#DList[T].IsEmpty>)\n  - [func \\(l \\*DList\\[T\\]\\) Iterate\\(\\) MutableIterator\\[T\\]](<#DList[T].Iterate>)\n  - [func \\(l \\*DList\\[T\\]\\) Len\\(\\) int](<#DList[T].Len>)\n  - [func \\(l \\*DList\\[T\\]\\) PopBack\\(\\) T](<#DList[T].PopBack>)\n  - [func \\(l \\*DList\\[T\\]\\) PopFront\\(\\) T](<#DList[T].PopFront>)\n  - [func \\(l \\*DList\\[T\\]\\) PushBack\\(val T\\)](<#DList[T].PushBack>)\n  - [func \\(l \\*DList\\[T\\]\\) PushFront\\(val T\\)](<#DList[T].PushFront>)\n  - [func \\(l \\*DList\\[T\\]\\) String\\(\\) string](<#DList[T].String>)\n  - [func \\(l \\*DList\\[T\\]\\) TryPopBack\\(\\) \\(T, bool\\)](<#DList[T].TryPopBack>)\n  - [func \\(l \\*DList\\[T\\]\\) TryPopFront\\(\\) \\(T, bool\\)](<#DList[T].TryPopFront>)\n- [type DListQueue](<#DListQueue>)\n  - [func NewDListQueue\\[T any\\]\\(\\) \\*DListQueue\\[T\\]](<#NewDListQueue>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) Back\\(\\) T](<#DListQueue[T].Back>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) Clear\\(\\)](<#DListQueue[T].Clear>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) Front\\(\\) T](<#DListQueue[T].Front>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) IsEmpty\\(\\) bool](<#DListQueue[T].IsEmpty>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) Len\\(\\) int](<#DListQueue[T].Len>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) PopBack\\(\\) T](<#DListQueue[T].PopBack>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) PopFront\\(\\) T](<#DListQueue[T].PopFront>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) PushBack\\(val T\\)](<#DListQueue[T].PushBack>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) PushFront\\(val T\\)](<#DListQueue[T].PushFront>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) String\\(\\) string](<#DListQueue[T].String>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) TryPopBack\\(\\) \\(T, bool\\)](<#DListQueue[T].TryPopBack>)\n  - [func \\(q \\*DListQueue\\[T\\]\\) TryPopFront\\(\\) \\(T, bool\\)](<#DListQueue[T].TryPopFront>)\n- [type Deque](<#Deque>)\n- [type Float](<#Float>)\n- [type HashFn](<#HashFn>)\n- [type Integer](<#Integer>)\n- [type Iterator](<#Iterator>)\n- [type LessFn](<#LessFn>)\n- [type Map](<#Map>)\n- [type MapIterator](<#MapIterator>)\n- [type MutableIterator](<#MutableIterator>)\n- [type MutableMapIterator](<#MutableMapIterator>)\n- [type Numeric](<#Numeric>)\n- [type Ordered](<#Ordered>)\n- [type Pool](<#Pool>)\n  - [func MakePool\\[T any\\]\\(\\) Pool\\[T\\]](<#MakePool>)\n  - [func MakePoolWithNew\\[T any\\]\\(new func\\(\\) \\*T\\) Pool\\[T\\]](<#MakePoolWithNew>)\n  - [func \\(pool \\*Pool\\[T\\]\\) Get\\(\\) \\*T](<#Pool[T].Get>)\n  - [func \\(pool \\*Pool\\[T\\]\\) Put\\(x \\*T\\)](<#Pool[T].Put>)\n- [type PriorityQueue](<#PriorityQueue>)\n  - [func NewPriorityQueue\\[T Ordered\\]\\(\\) \\*PriorityQueue\\[T\\]](<#NewPriorityQueue>)\n  - [func NewPriorityQueueFunc\\[T any\\]\\(less LessFn\\[T\\]\\) \\*PriorityQueue\\[T\\]](<#NewPriorityQueueFunc>)\n  - [func NewPriorityQueueOf\\[T Ordered\\]\\(elements ...T\\) \\*PriorityQueue\\[T\\]](<#NewPriorityQueueOf>)\n  - [func NewPriorityQueueOn\\[T Ordered\\]\\(slice \\[\\]T\\) \\*PriorityQueue\\[T\\]](<#NewPriorityQueueOn>)\n  - [func \\(pq \\*PriorityQueue\\[T\\]\\) Clear\\(\\)](<#PriorityQueue[T].Clear>)\n  - [func \\(pq \\*PriorityQueue\\[T\\]\\) IsEmpty\\(\\) bool](<#PriorityQueue[T].IsEmpty>)\n  - [func \\(pq \\*PriorityQueue\\[T\\]\\) Len\\(\\) int](<#PriorityQueue[T].Len>)\n  - [func \\(pq \\*PriorityQueue\\[T\\]\\) Pop\\(\\) T](<#PriorityQueue[T].Pop>)\n  - [func \\(pq \\*PriorityQueue\\[T\\]\\) Push\\(v T\\)](<#PriorityQueue[T].Push>)\n  - [func \\(pq \\*PriorityQueue\\[T\\]\\) Top\\(\\) T](<#PriorityQueue[T].Top>)\n- [type Queue](<#Queue>)\n- [type SList](<#SList>)\n  - [func SListOf\\[T any\\]\\(values ...T\\) SList\\[T\\]](<#SListOf>)\n  - [func \\(l \\*SList\\[T\\]\\) Back\\(\\) T](<#SList[T].Back>)\n  - [func \\(l \\*SList\\[T\\]\\) Clear\\(\\)](<#SList[T].Clear>)\n  - [func \\(l \\*SList\\[T\\]\\) ForEach\\(cb func\\(T\\)\\)](<#SList[T].ForEach>)\n  - [func \\(l \\*SList\\[T\\]\\) ForEachIf\\(cb func\\(T\\) bool\\)](<#SList[T].ForEachIf>)\n  - [func \\(l \\*SList\\[T\\]\\) ForEachMutable\\(cb func\\(\\*T\\)\\)](<#SList[T].ForEachMutable>)\n  - [func \\(l \\*SList\\[T\\]\\) ForEachMutableIf\\(cb func\\(\\*T\\) bool\\)](<#SList[T].ForEachMutableIf>)\n  - [func \\(l \\*SList\\[T\\]\\) Front\\(\\) T](<#SList[T].Front>)\n  - [func \\(l \\*SList\\[T\\]\\) IsEmpty\\(\\) bool](<#SList[T].IsEmpty>)\n  - [func \\(l \\*SList\\[T\\]\\) Iterate\\(\\) MutableIterator\\[T\\]](<#SList[T].Iterate>)\n  - [func \\(l \\*SList\\[T\\]\\) Len\\(\\) int](<#SList[T].Len>)\n  - [func \\(l \\*SList\\[T\\]\\) PopFront\\(\\) T](<#SList[T].PopFront>)\n  - [func \\(l \\*SList\\[T\\]\\) PushBack\\(v T\\)](<#SList[T].PushBack>)\n  - [func \\(l \\*SList\\[T\\]\\) PushFront\\(v T\\)](<#SList[T].PushFront>)\n  - [func \\(l \\*SList\\[T\\]\\) Reverse\\(\\)](<#SList[T].Reverse>)\n  - [func \\(l \\*SList\\[T\\]\\) Values\\(\\) \\[\\]T](<#SList[T].Values>)\n- [type Set](<#Set>)\n- [type Signed](<#Signed>)\n- [type SkipList](<#SkipList>)\n  - [func NewSkipList\\[K Ordered, V any\\]\\(\\) \\*SkipList\\[K, V\\]](<#NewSkipList>)\n  - [func NewSkipListFromMap\\[K Ordered, V any\\]\\(m map\\[K\\]V\\) \\*SkipList\\[K, V\\]](<#NewSkipListFromMap>)\n  - [func NewSkipListFunc\\[K any, V any\\]\\(keyCmp CompareFn\\[K\\]\\) \\*SkipList\\[K, V\\]](<#NewSkipListFunc>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) Clear\\(\\)](<#SkipList[K, V].Clear>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) Find\\(key K\\) \\*V](<#SkipList[K, V].Find>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) FindRange\\(first, last K\\) MutableMapIterator\\[K, V\\]](<#SkipList[K, V].FindRange>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) ForEach\\(op func\\(K, V\\)\\)](<#SkipList[K, V].ForEach>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) ForEachIf\\(op func\\(K, V\\) bool\\)](<#SkipList[K, V].ForEachIf>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) ForEachMutable\\(op func\\(K, \\*V\\)\\)](<#SkipList[K, V].ForEachMutable>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) ForEachMutableIf\\(op func\\(K, \\*V\\) bool\\)](<#SkipList[K, V].ForEachMutableIf>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) Has\\(key K\\) bool](<#SkipList[K, V].Has>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) Insert\\(key K, value V\\)](<#SkipList[K, V].Insert>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) IsEmpty\\(\\) bool](<#SkipList[K, V].IsEmpty>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) Iterate\\(\\) MutableMapIterator\\[K, V\\]](<#SkipList[K, V].Iterate>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) Len\\(\\) int](<#SkipList[K, V].Len>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) LowerBound\\(key K\\) MutableMapIterator\\[K, V\\]](<#SkipList[K, V].LowerBound>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) Remove\\(key K\\) bool](<#SkipList[K, V].Remove>)\n  - [func \\(sl \\*SkipList\\[K, V\\]\\) UpperBound\\(key K\\) MutableMapIterator\\[K, V\\]](<#SkipList[K, V].UpperBound>)\n- [type SkipListSet](<#SkipListSet>)\n  - [func NewSkipListSet\\[K Ordered\\]\\(\\) \\*SkipListSet\\[K\\]](<#NewSkipListSet>)\n  - [func NewSkipListSetFunc\\[K any\\]\\(cmp CompareFn\\[K\\]\\) \\*SkipListSet\\[K\\]](<#NewSkipListSetFunc>)\n  - [func NewSkipListSetOf\\[K Ordered\\]\\(elements ...K\\) \\*SkipListSet\\[K\\]](<#NewSkipListSetOf>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) Clear\\(\\)](<#SkipListSet[K].Clear>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) FindRange\\(first, last K\\) Iterator\\[K\\]](<#SkipListSet[K].FindRange>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) ForEach\\(f func\\(K\\)\\)](<#SkipListSet[K].ForEach>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) ForEachIf\\(f func\\(K\\) bool\\)](<#SkipListSet[K].ForEachIf>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) Has\\(key K\\) bool](<#SkipListSet[K].Has>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) Insert\\(key K\\) bool](<#SkipListSet[K].Insert>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) InsertN\\(keys ...K\\) int](<#SkipListSet[K].InsertN>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) IsEmpty\\(\\) bool](<#SkipListSet[K].IsEmpty>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) Keys\\(\\) \\[\\]K](<#SkipListSet[K].Keys>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) Len\\(\\) int](<#SkipListSet[K].Len>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) LowerBound\\(key K\\) Iterator\\[K\\]](<#SkipListSet[K].LowerBound>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) Remove\\(key K\\) bool](<#SkipListSet[K].Remove>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) RemoveN\\(keys ...K\\) int](<#SkipListSet[K].RemoveN>)\n  - [func \\(s \\*SkipListSet\\[K\\]\\) UpperBound\\(key K\\) Iterator\\[K\\]](<#SkipListSet[K].UpperBound>)\n- [type SortedMap](<#SortedMap>)\n- [type SortedSet](<#SortedSet>)\n- [type Stack](<#Stack>)\n  - [func NewStack\\[T any\\]\\(\\) \\*Stack\\[T\\]](<#NewStack>)\n  - [func NewStackCap\\[T any\\]\\(capicity int\\) \\*Stack\\[T\\]](<#NewStackCap>)\n  - [func \\(s Stack\\[T\\]\\) Cap\\(\\) int](<#Stack[T].Cap>)\n  - [func \\(s \\*Stack\\[T\\]\\) Clear\\(\\)](<#Stack[T].Clear>)\n  - [func \\(s Stack\\[T\\]\\) IsEmpty\\(\\) bool](<#Stack[T].IsEmpty>)\n  - [func \\(s Stack\\[T\\]\\) Len\\(\\) int](<#Stack[T].Len>)\n  - [func \\(s \\*Stack\\[T\\]\\) Pop\\(\\) T](<#Stack[T].Pop>)\n  - [func \\(s \\*Stack\\[T\\]\\) Push\\(t T\\)](<#Stack[T].Push>)\n  - [func \\(s Stack\\[T\\]\\) Top\\(\\) T](<#Stack[T].Top>)\n  - [func \\(s \\*Stack\\[T\\]\\) TryPop\\(\\) \\(val T, ok bool\\)](<#Stack[T].TryPop>)\n- [type Unsigned](<#Unsigned>)\n- [type Vector](<#Vector>)\n  - [func AsVector\\[T any\\]\\(s \\[\\]T\\) Vector\\[T\\]](<#AsVector>)\n  - [func MakeVector\\[T any\\]\\(\\) Vector\\[T\\]](<#MakeVector>)\n  - [func MakeVectorCap\\[T any\\]\\(c int\\) Vector\\[T\\]](<#MakeVectorCap>)\n  - [func VectorOf\\[T any\\]\\(v ...T\\) Vector\\[T\\]](<#VectorOf>)\n  - [func \\(v \\*Vector\\[T\\]\\) Append\\(x ...T\\)](<#Vector[T].Append>)\n  - [func \\(v \\*Vector\\[T\\]\\) At\\(i int\\) T](<#Vector[T].At>)\n  - [func \\(v Vector\\[T\\]\\) Back\\(\\) T](<#Vector[T].Back>)\n  - [func \\(v \\*Vector\\[T\\]\\) Cap\\(\\) int](<#Vector[T].Cap>)\n  - [func \\(v \\*Vector\\[T\\]\\) Clear\\(\\)](<#Vector[T].Clear>)\n  - [func \\(v Vector\\[T\\]\\) ForEach\\(cb func\\(val T\\)\\)](<#Vector[T].ForEach>)\n  - [func \\(v Vector\\[T\\]\\) ForEachIf\\(cb func\\(val T\\) bool\\)](<#Vector[T].ForEachIf>)\n  - [func \\(v Vector\\[T\\]\\) ForEachMutable\\(cb func\\(val \\*T\\)\\)](<#Vector[T].ForEachMutable>)\n  - [func \\(v Vector\\[T\\]\\) ForEachMutableIf\\(cb func\\(val \\*T\\) bool\\)](<#Vector[T].ForEachMutableIf>)\n  - [func \\(v \\*Vector\\[T\\]\\) Insert\\(i int, x ...T\\)](<#Vector[T].Insert>)\n  - [func \\(v \\*Vector\\[T\\]\\) IsEmpty\\(\\) bool](<#Vector[T].IsEmpty>)\n  - [func \\(v Vector\\[T\\]\\) Iterate\\(\\) MutableIterator\\[T\\]](<#Vector[T].Iterate>)\n  - [func \\(v Vector\\[T\\]\\) IterateRange\\(i, j int\\) MutableIterator\\[T\\]](<#Vector[T].IterateRange>)\n  - [func \\(v \\*Vector\\[T\\]\\) Len\\(\\) int](<#Vector[T].Len>)\n  - [func \\(v \\*Vector\\[T\\]\\) PopBack\\(\\) T](<#Vector[T].PopBack>)\n  - [func \\(v \\*Vector\\[T\\]\\) PushBack\\(x T\\)](<#Vector[T].PushBack>)\n  - [func \\(v \\*Vector\\[T\\]\\) Remove\\(i int\\)](<#Vector[T].Remove>)\n  - [func \\(v \\*Vector\\[T\\]\\) RemoveIf\\(cond func\\(T\\) bool\\)](<#Vector[T].RemoveIf>)\n  - [func \\(v \\*Vector\\[T\\]\\) RemoveLength\\(i int, len int\\)](<#Vector[T].RemoveLength>)\n  - [func \\(v \\*Vector\\[T\\]\\) RemoveRange\\(i, j int\\)](<#Vector[T].RemoveRange>)\n  - [func \\(v \\*Vector\\[T\\]\\) Reserve\\(l int\\)](<#Vector[T].Reserve>)\n  - [func \\(v \\*Vector\\[T\\]\\) Set\\(i int, x T\\)](<#Vector[T].Set>)\n  - [func \\(v \\*Vector\\[T\\]\\) Shrink\\(\\)](<#Vector[T].Shrink>)\n  - [func \\(v \\*Vector\\[T\\]\\) TryPopBack\\(\\) \\(T, bool\\)](<#Vector[T].TryPopBack>)\n\n\n<a name=\"AllOf\"></a>\n## func [AllOf](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L130>)\n\n```go\nfunc AllOf[T any](a []T, pred func(T) bool) bool\n```\n\nAllOf return true if pred\\(e\\) returns true for all elements e in a.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"AnyOf\"></a>\n## func [AnyOf](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L142>)\n\n```go\nfunc AnyOf[T any](a []T, pred func(T) bool) bool\n```\n\nAnyOf return true if pred\\(e\\) returns true for any elements e in a.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Average\"></a>\n## func [Average](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L42>)\n\n```go\nfunc Average[T Numeric](a []T) T\n```\n\nAverage returns the average value of a.\n\n<a name=\"AverageAs\"></a>\n## func [AverageAs](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L37>)\n\n```go\nfunc AverageAs[R, T Numeric](a []T) R\n```\n\nAverageAs returns the average value of a as type R.\n\n<a name=\"BinarySearch\"></a>\n## func [BinarySearch](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L100>)\n\n```go\nfunc BinarySearch[T Ordered](a []T, value T) (index int, ok bool)\n```\n\nBinarySearch 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.\n\nComplexity: O\\(log\\(len\\(a\\)\\)\\).\n\n<a name=\"BinarySearchFunc\"></a>\n## func [BinarySearchFunc](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L115>)\n\n```go\nfunc BinarySearchFunc[T any](a []T, value T, less LessFn[T]) (index int, ok bool)\n```\n\nBinarySearchFunc 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.\n\nThe elements in the slice a should sorted according with compare func less.\n\nComplexity: O\\(log\\(len\\(a\\)\\)\\).\n\n<a name=\"Compare\"></a>\n## func [Compare](<https://github.com/chen3feng/stl4go/blob/master/compare.go#L26>)\n\n```go\nfunc Compare[E Ordered](a, b []E) int\n```\n\nCompare compares each elements in a and b.\n\nreturn 0 if they are equals, return 1 if a \\> b, return \\-1 if a \\< b.\n\nComplexity: O\\(min\\(len\\(a\\), len\\(b\\)\\)\\).\n\n<a name=\"Copy\"></a>\n## func [Copy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L8>)\n\n```go\nfunc Copy[T any](a []T) []T\n```\n\nCopy make a copy of slice a.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"CopyTo\"></a>\n## func [CopyTo](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L16>)\n\n```go\nfunc CopyTo[T any](a []T, to []T) []T\n```\n\nCopyTo copies all elements in slice a to slice to, return the copied slice. if slice to is large enough, no memory allocation occurs.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Count\"></a>\n## func [Count](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L59>)\n\n```go\nfunc Count[T comparable](a []T, x T) int\n```\n\nCount returns the number of elements in the slice equals to x.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"CountIf\"></a>\n## func [CountIf](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L72>)\n\n```go\nfunc CountIf[T comparable](a []T, pred func(T) bool) int\n```\n\nCountIf returns the number of elements in the slice which pred returns true.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"DescSort\"></a>\n## func [DescSort](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L73>)\n\n```go\nfunc DescSort[T Ordered](a []T)\n```\n\nDescSort sorts data in descending order. The order of equal elements is not guaranteed to be preserved.\n\nComplexity: O\\(N\\*log\\(N\\)\\), N=len\\(a\\).\n\n<a name=\"DescStableSort\"></a>\n## func [DescStableSort](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L81>)\n\n```go\nfunc DescStableSort[T Ordered](a []T)\n```\n\nDescStableSort sorts data in descending order stably. The order of equivalent elements is guaranteed to be preserved.\n\nComplexity: O\\(N\\*log\\(N\\)\\), N=len\\(a\\).\n\n<a name=\"Equal\"></a>\n## func [Equal](<https://github.com/chen3feng/stl4go/blob/master/compare.go#L7>)\n\n```go\nfunc Equal[T comparable](a, b []T) bool\n```\n\nEqual returns whether two slices are equal. Return true if they are the same length and all elements are equal.\n\nComplexity: O\\(min\\(len\\(a\\), len\\(b\\)\\)\\).\n\n<a name=\"Fill\"></a>\n## func [Fill](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L24>)\n\n```go\nfunc Fill[T any](a []T, v T)\n```\n\nFill fills each element in slice a with new value v.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"FillPattern\"></a>\n## func [FillPattern](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L42>)\n\n```go\nfunc FillPattern[T any](a []T, pattern []T)\n```\n\nFillPattern fills elements in slice a with specified pattern.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"FillZero\"></a>\n## func [FillZero](<https://github.com/chen3feng/stl4go/blob/master/transform_fillzero_clear.go#L9>)\n\n```go\nfunc FillZero[T any](a []T)\n```\n\nFillZero fills each element in slice a with zero value.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Find\"></a>\n## func [Find](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L90>)\n\n```go\nfunc Find[T comparable](a []T, x T) (index int, ok bool)\n```\n\nFind find the first value x in the given slice a linearly. return \\(index, true\\) if found, return \\(\\_, false\\) if not found.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"FindIf\"></a>\n## func [FindIf](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L104>)\n\n```go\nfunc FindIf[T any](a []T, cond func(T) bool) (index int, ok bool)\n```\n\nFindIf find the first value x satisfying function cond in the given slice a linearly. return \\(index, true\\) if found, return \\(\\_, false\\) if not found.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Generate\"></a>\n## func [Generate](<https://github.com/chen3feng/stl4go/blob/master/generate.go#L18>)\n\n```go\nfunc Generate[T any](a []T, gen func() T)\n```\n\nGenerate fill each element of \\`a“ with \\`gen\\(\\)\\`.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Greater\"></a>\n## func [Greater](<https://github.com/chen3feng/stl4go/blob/master/functor.go#L9>)\n\n```go\nfunc Greater[T Ordered](a, b T) bool\n```\n\nGreater wraps the '\\>' operator for ordered types.\n\n<a name=\"Index\"></a>\n## func [Index](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L118>)\n\n```go\nfunc Index[T comparable](a []T, x T) int\n```\n\nIndex find the value x in the given slice a linearly.\n\nReturn index if found, \\-1 if not found.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"IsDescSorted\"></a>\n## func [IsDescSorted](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L27>)\n\n```go\nfunc IsDescSorted[T Ordered](a []T) bool\n```\n\nIsDescSorted returns whether the slice a is sorted in descending order.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"IsHeapFunc\"></a>\n## func [IsHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L118>)\n\n```go\nfunc IsHeapFunc[T any](array []T, less LessFn[T]) bool\n```\n\nIsHeapFunc checks whether the elements in slice array are a min heap \\(accord to less\\).\n\nComplexity: O\\(len\\(array\\)\\).\n\n<a name=\"IsMinHeap\"></a>\n## func [IsMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L19>)\n\n```go\nfunc IsMinHeap[T Ordered](array []T) bool\n```\n\nIsMinHeap checks whether the elements in slice array are a min heap.\n\nComplexity: O\\(len\\(array\\)\\).\n\n<a name=\"IsSorted\"></a>\n## func [IsSorted](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L10>)\n\n```go\nfunc IsSorted[T Ordered](a []T) bool\n```\n\nIsSorted returns whether the slice a is sorted in ascending order.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Less\"></a>\n## func [Less](<https://github.com/chen3feng/stl4go/blob/master/functor.go#L4>)\n\n```go\nfunc Less[T Ordered](a, b T) bool\n```\n\nLess wraps the '\\<' operator for ordered types.\n\n<a name=\"LowerBound\"></a>\n## func [LowerBound](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L8>)\n\n```go\nfunc LowerBound[T Ordered](a []T, value T) int\n```\n\nLowerBound 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.\n\nComplexity: O\\(log\\(len\\(a\\)\\)\\).\n\n<a name=\"LowerBoundFunc\"></a>\n## func [LowerBoundFunc](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L32>)\n\n```go\nfunc LowerBoundFunc[T any](a []T, value T, less LessFn[T]) int\n```\n\nLowerBoundFunc 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.\n\nThe elements in the slice a should sorted according with compare func less.\n\nComplexity: O\\(log\\(len\\(a\\)\\)\\).\n\n<a name=\"MakeHeapFunc\"></a>\n## func [MakeHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L107>)\n\n```go\nfunc MakeHeapFunc[T any](array []T, less LessFn[T])\n```\n\nMakeHeapFunc build a min\\-heap on slice array with compare function less.\n\nComplexity: O\\(len\\(array\\)\\)\n\n<a name=\"MakeMinHeap\"></a>\n## func [MakeMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L8>)\n\n```go\nfunc MakeMinHeap[T Ordered](array []T)\n```\n\nMakeMinHeap build a min\\-heap on slice array.\n\nComplexity: O\\(len\\(array\\)\\)\n\n<a name=\"Max\"></a>\n## func [Max](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L6>)\n\n```go\nfunc Max[T Ordered](a, b T) T\n```\n\nMax return the larger value between \\`a\\` and \\`b\\`.\n\nComplexity: O\\(1\\).\n\n<a name=\"MaxN\"></a>\n## func [MaxN](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L26>)\n\n```go\nfunc MaxN[T Ordered](a ...T) T\n```\n\nMaxN return the maximum value in the sequence \\`a\\`.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Min\"></a>\n## func [Min](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L16>)\n\n```go\nfunc Min[T Ordered](a, b T) T\n```\n\nMin return the smaller value between \\`a\\` and \\`b\\`.\n\nComplexity: O\\(1\\).\n\n<a name=\"MinMax\"></a>\n## func [MinMax](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L58>)\n\n```go\nfunc MinMax[T Ordered](a, b T) (min, max T)\n```\n\nMinMax returns both min and max between a and b.\n\nComplexity: O\\(1\\).\n\n<a name=\"MinMaxN\"></a>\n## func [MinMaxN](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L68>)\n\n```go\nfunc MinMaxN[T Ordered](a ...T) (min, max T)\n```\n\nMinMaxN returns both min and max in slice a.\n\nComplexity: O\\(len\\(a\\)\\)\n\n<a name=\"MinN\"></a>\n## func [MinN](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L42>)\n\n```go\nfunc MinN[T Ordered](a ...T) T\n```\n\nMinN return the minimum value in the sequence \\`a\\`.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"NoneOf\"></a>\n## func [NoneOf](<https://github.com/chen3feng/stl4go/blob/master/lookup.go#L154>)\n\n```go\nfunc NoneOf[T any](a []T, pred func(T) bool) bool\n```\n\nNoneOf return true pred\\(e\\) returns true for none elements e in a.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"OrderedCompare\"></a>\n## func [OrderedCompare](<https://github.com/chen3feng/stl4go/blob/master/functor.go#L14>)\n\n```go\nfunc OrderedCompare[T Ordered](a, b T) int\n```\n\nOrderedCompare provide default CompareFn for ordered types.\n\n<a name=\"PopHeapFunc\"></a>\n## func [PopHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L144>)\n\n```go\nfunc PopHeapFunc[T any](heap *[]T, less LessFn[T]) T\n```\n\nPopHeapFunc removes and returns the minimum \\(according to less\\) element from the heap.\n\nComplexity: O\\(log n\\) where n = len\\(\\*heap\\).\n\n<a name=\"PopMinHeap\"></a>\n## func [PopMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L44>)\n\n```go\nfunc PopMinHeap[T Ordered](heap *[]T) T\n```\n\nPopMinHeap removes and returns the minimum element from the heap.\n\nComplexity: O\\(log n\\) where n = len\\(\\*heap\\).\n\n<a name=\"PushHeapFunc\"></a>\n## func [PushHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L136>)\n\n```go\nfunc PushHeapFunc[T any](heap *[]T, v T, less LessFn[T])\n```\n\nPushHeapFunc pushes a element v into the heap.\n\nComplexity: O\\(log\\(len\\(\\*heap\\)\\)\\).\n\n<a name=\"PushMinHeap\"></a>\n## func [PushMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L36>)\n\n```go\nfunc PushMinHeap[T Ordered](heap *[]T, v T)\n```\n\nPushMinHeap pushes a element v into the min heap.\n\nComplexity: O\\(log\\(len\\(\\*heap\\)\\)\\).\n\n<a name=\"Range\"></a>\n## func [Range](<https://github.com/chen3feng/stl4go/blob/master/generate.go#L7>)\n\n```go\nfunc Range[T Numeric](first, last T) []T\n```\n\nRange make a \\[\\]T filled with values in the \\`\\[first, last\\)\\` sequence. NOTE: the last is not included in the result.\n\nComplexity: O\\(last\\-first\\).\n\n<a name=\"Remove\"></a>\n## func [Remove](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L154>)\n\n```go\nfunc Remove[T comparable](a []T, x T) []T\n```\n\nRemove remove the elements which equals to x from the input slice. return the processed slice with new length.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"RemoveCopy\"></a>\n## func [RemoveCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L169>)\n\n```go\nfunc RemoveCopy[T comparable](a []T, x T) []T\n```\n\nRemoveCopy remove all elements which equals to x from the input slice. return a new slice with processed results. The input slice is kept unchanged.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"RemoveHeapFunc\"></a>\n## func [RemoveHeapFunc](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L156>)\n\n```go\nfunc RemoveHeapFunc[T any](heap *[]T, i int, less LessFn[T]) T\n```\n\nRemoveHeapFunc removes and returns the element at index i from the heap.\n\nComplexity: is O\\(log\\(n\\)\\) where n = len\\(\\*heap\\).\n\n<a name=\"RemoveIf\"></a>\n## func [RemoveIf](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L183>)\n\n```go\nfunc RemoveIf[T any](a []T, cond func(T) bool) []T\n```\n\nRemoveIf remove each element which make cond\\(x\\) returns true from the input slice, copy other elements to a new slice and return it.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"RemoveIfCopy\"></a>\n## func [RemoveIfCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L198>)\n\n```go\nfunc RemoveIfCopy[T any](a []T, cond func(T) bool) []T\n```\n\nRemoveIfCopy 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.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"RemoveMinHeap\"></a>\n## func [RemoveMinHeap](<https://github.com/chen3feng/stl4go/blob/master/heap.go#L56>)\n\n```go\nfunc RemoveMinHeap[T Ordered](heap *[]T, i int) T\n```\n\nRemoveMinHeap removes and returns the element at index i from the min heap.\n\nComplexity: is O\\(log\\(n\\)\\) where n = len\\(\\*heap\\).\n\n<a name=\"Replace\"></a>\n## func [Replace](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L91>)\n\n```go\nfunc Replace[T comparable](a []T, old, new T)\n```\n\nReplace replaces every element that equals to old with new.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"ReplaceIf\"></a>\n## func [ReplaceIf](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L102>)\n\n```go\nfunc ReplaceIf[T any](a []T, pred func(v T) bool, new T)\n```\n\nReplaceIf replaces every element that make preq returns true with new.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Reverse\"></a>\n## func [Reverse](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L220>)\n\n```go\nfunc Reverse[T any](a []T)\n```\n\nReverse reverses the order of the elements in the slice a.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"ReverseCopy\"></a>\n## func [ReverseCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L229>)\n\n```go\nfunc ReverseCopy[T any](a []T) []T\n```\n\nReverseCopy returns a reversed copy of slice a.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Shuffle\"></a>\n## func [Shuffle](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L211>)\n\n```go\nfunc Shuffle[T any](a []T)\n```\n\nShuffle pseudo\\-randomizes the order of elements.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Sort\"></a>\n## func [Sort](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L51>)\n\n```go\nfunc Sort[T Ordered](a []T)\n```\n\nSort sorts data in ascending order. The order of equal elements is not guaranteed to be preserved.\n\nComplexity: O\\(N\\*log\\(N\\)\\), where N=len\\(a\\).\n\n<a name=\"SortFunc\"></a>\n## func [SortFunc](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L98>)\n\n```go\nfunc SortFunc[T any](a []T, less func(x, y T) bool)\n```\n\nSortFunc sorts data in ascending order with compare func less. The order of equal elements is not guaranteed to be preserved.\n\nComplexity: O\\(N\\*log\\(N\\)\\), N=len\\(a\\).\n\n<a name=\"StableSort\"></a>\n## func [StableSort](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L59>)\n\n```go\nfunc StableSort[T Ordered](a []T)\n```\n\nStableSort sorts data in ascending order stably. The order of equivalent elements is guaranteed to be preserved.\n\nComplexity: O\\(N\\*log\\(N\\)^2\\), where N=len\\(a\\).\n\n<a name=\"StableSortFunc\"></a>\n## func [StableSortFunc](<https://github.com/chen3feng/stl4go/blob/master/sort.go#L106>)\n\n```go\nfunc StableSortFunc[T any](a []T, less func(x, y T) bool)\n```\n\nStableSortFunc sorts data in ascending order with compare func less stably. The order of equivalent elements is guaranteed to be preserved.\n\nComplexity: O\\(N\\*log\\(N\\)\\), N=len\\(a\\).\n\n<a name=\"Sum\"></a>\n## func [Sum](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L32>)\n\n```go\nfunc Sum[T Numeric](a []T) T\n```\n\nSum 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\\)\\).\n\n<a name=\"SumAs\"></a>\n## func [SumAs](<https://github.com/chen3feng/stl4go/blob/master/compute.go#L6>)\n\n```go\nfunc SumAs[R, T Numeric](a []T) R\n```\n\nSumAs 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\\)\\).\n\n<a name=\"Transform\"></a>\n## func [Transform](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L71>)\n\n```go\nfunc Transform[T any](a []T, op func(T) T)\n```\n\nTransform applies the function op to each element in slice a and set it back to the same place in a.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"TransformCopy\"></a>\n## func [TransformCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L80>)\n\n```go\nfunc TransformCopy[R any, T any](a []T, op func(T) R) []R\n```\n\nTransformCopy applies the function op to each element in slice a and return all the result as a slice.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"TransformTo\"></a>\n## func [TransformTo](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L60>)\n\n```go\nfunc TransformTo[R any, T any](a []T, op func(T) R, b []R) []R\n```\n\nTransformTo 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.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"Unique\"></a>\n## func [Unique](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L114>)\n\n```go\nfunc Unique[T comparable](a []T) []T\n```\n\nUnique remove adjacent repeated elements from the input slice. return the processed slice with new length.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"UniqueCopy\"></a>\n## func [UniqueCopy](<https://github.com/chen3feng/stl4go/blob/master/transform.go#L134>)\n\n```go\nfunc UniqueCopy[T comparable](a []T) []T\n```\n\nUniqueCopy remove adjacent repeated elements from the input slice. return the result slice, and the input slice is kept unchanged.\n\nComplexity: O\\(len\\(a\\)\\).\n\n<a name=\"UpperBound\"></a>\n## func [UpperBound](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L54>)\n\n```go\nfunc UpperBound[T Ordered](a []T, value T) int\n```\n\nUpperBound 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.\n\nComplexity: O\\(log\\(len\\(a\\)\\)\\).\n\n<a name=\"UpperBoundFunc\"></a>\n## func [UpperBoundFunc](<https://github.com/chen3feng/stl4go/blob/master/binary_search.go#L78>)\n\n```go\nfunc UpperBoundFunc[T any](a []T, value T, less LessFn[T]) int\n```\n\nUpperBoundFunc 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.\n\nThe elements in the slice a should sorted according with compare func less.\n\nComplexity: O\\(log\\(len\\(a\\)\\)\\).\n\n<a name=\"BuiltinSet\"></a>\n## type [BuiltinSet](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L8>)\n\nBuiltinSet is an associative container that contains an unordered set of unique objects of type K.\n\n```go\ntype BuiltinSet[K comparable] map[K]struct{}\n```\n\n<a name=\"SetOf\"></a>\n### func [SetOf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L11>)\n\n```go\nfunc SetOf[K comparable](ks ...K) BuiltinSet[K]\n```\n\nSetOf creates a new BuiltinSet object with the initial content from ks.\n\n<a name=\"BuiltinSet[K].Clear\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L28>)\n\n```go\nfunc (s BuiltinSet[K]) Clear()\n```\n\nClear implements the Container interface.\n\n<a name=\"BuiltinSet[K].Delete\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Delete](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L65>)\n\n```go\nfunc (s BuiltinSet[K]) Delete(k K)\n```\n\nDelete deletes an element from the set. It returns nothing, so it's faster than Remove.\n\n<a name=\"BuiltinSet[K].Difference\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Difference](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L143>)\n\n```go\nfunc (s BuiltinSet[K]) Difference(other BuiltinSet[K]) BuiltinSet[K]\n```\n\nDifference returns a new set with elements in the set that are not in other.\n\n<a name=\"BuiltinSet[K].ForEach\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L88>)\n\n```go\nfunc (s BuiltinSet[K]) ForEach(cb func(k K))\n```\n\nForEach implements the Set interface.\n\n<a name=\"BuiltinSet[K].ForEachIf\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L95>)\n\n```go\nfunc (s BuiltinSet[K]) ForEachIf(cb func(k K) bool)\n```\n\nForEachIf implements the Container interface.\n\n<a name=\"BuiltinSet[K].Has\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Has](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L35>)\n\n```go\nfunc (s BuiltinSet[K]) Has(k K) bool\n```\n\nHas implements the Set interface.\n\n<a name=\"BuiltinSet[K].Insert\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Insert](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L41>)\n\n```go\nfunc (s BuiltinSet[K]) Insert(k K) bool\n```\n\nInsert implements the Set interface.\n\n<a name=\"BuiltinSet[K].InsertN\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [InsertN](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L48>)\n\n```go\nfunc (s BuiltinSet[K]) InsertN(ks ...K) int\n```\n\nInsertN implements the Set interface.\n\n<a name=\"BuiltinSet[K].Intersection\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Intersection](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L131>)\n\n```go\nfunc (s BuiltinSet[K]) Intersection(other BuiltinSet[K]) BuiltinSet[K]\n```\n\nIntersection returns a new set with elements common to the set and other.\n\n<a name=\"BuiltinSet[K].IsDisjointOf\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [IsDisjointOf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L155>)\n\n```go\nfunc (s BuiltinSet[K]) IsDisjointOf(other BuiltinSet[K]) bool\n```\n\nIsDisjointOf 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.\n\n<a name=\"BuiltinSet[K].IsEmpty\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L18>)\n\n```go\nfunc (s BuiltinSet[K]) IsEmpty() bool\n```\n\nIsEmpty implements the Container interface.\n\n<a name=\"BuiltinSet[K].IsSubsetOf\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [IsSubsetOf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L166>)\n\n```go\nfunc (s BuiltinSet[K]) IsSubsetOf(other BuiltinSet[K]) bool\n```\n\nIsSubsetOf tests whether every element in the set is in other.\n\n<a name=\"BuiltinSet[K].IsSupersetOf\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [IsSupersetOf](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L179>)\n\n```go\nfunc (s BuiltinSet[K]) IsSupersetOf(other BuiltinSet[K]) bool\n```\n\nIsSupersetOf tests whether every element in other is in the set.\n\n<a name=\"BuiltinSet[K].Keys\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Keys](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L79>)\n\n```go\nfunc (s BuiltinSet[K]) Keys() []K\n```\n\nKeys return a copy of all keys as a slice.\n\n<a name=\"BuiltinSet[K].Len\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L23>)\n\n```go\nfunc (s BuiltinSet[K]) Len() int\n```\n\nLen implements the Container interface.\n\n<a name=\"BuiltinSet[K].Remove\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Remove](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L57>)\n\n```go\nfunc (s BuiltinSet[K]) Remove(k K) bool\n```\n\nRemove implements the Set interface.\n\n<a name=\"BuiltinSet[K].RemoveN\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [RemoveN](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L70>)\n\n```go\nfunc (s BuiltinSet[K]) RemoveN(ks ...K) int\n```\n\nRemoveN implements the Set interface.\n\n<a name=\"BuiltinSet[K].String\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [String](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L104>)\n\n```go\nfunc (s BuiltinSet[K]) String() string\n```\n\nString implements the fmt.Stringer interface.\n\n<a name=\"BuiltinSet[K].Union\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Union](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L116>)\n\n```go\nfunc (s BuiltinSet[K]) Union(other BuiltinSet[K]) BuiltinSet[K]\n```\n\nUnion returns a new set with elements from the set and other.\n\n<a name=\"BuiltinSet[K].Update\"></a>\n### func \\(BuiltinSet\\[K\\]\\) [Update](<https://github.com/chen3feng/stl4go/blob/master/builtin_set.go#L109>)\n\n```go\nfunc (s BuiltinSet[K]) Update(other BuiltinSet[K])\n```\n\nUpdate adds all elements from other to set. set |= other.\n\n<a name=\"CompareFn\"></a>\n## type [CompareFn](<https://github.com/chen3feng/stl4go/blob/master/types.go#L51>)\n\nCompareFn is a 3 way compare function that returns 1 if a \\> b, returns 0 if a == b, returns \\-1 if a \\< b.\n\n```go\ntype CompareFn[T any] func(a, b T) int\n```\n\n<a name=\"Container\"></a>\n## type [Container](<https://github.com/chen3feng/stl4go/blob/master/container.go#L4-L8>)\n\nContainer is a holder object that stores a collection of other objects.\n\n```go\ntype Container interface {\n    IsEmpty() bool // IsEmpty checks if the container has no elements.\n    Len() int      // Len returns the number of elements in the container.\n    Clear()        // Clear erases all elements from the container. After this call, Len() returns zero.\n}\n```\n\n<a name=\"DList\"></a>\n## type [DList](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L6-L9>)\n\nDList is a doubly linked list.\n\n```go\ntype DList[T any] struct {\n    // contains filtered or unexported fields\n}\n```\n\n<a name=\"DListOf\"></a>\n### func [DListOf](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L17>)\n\n```go\nfunc DListOf[T any](vs ...T) DList[T]\n```\n\nDListOf make a new DList from a serial of values.\n\n<a name=\"DList[T].Back\"></a>\n### func \\(\\*DList\\[T\\]\\) [Back](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L88>)\n\n```go\nfunc (l *DList[T]) Back() T\n```\n\nBack returns the last element in the container.\n\n<a name=\"DList[T].Clear\"></a>\n### func \\(\\*DList\\[T\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L26>)\n\n```go\nfunc (l *DList[T]) Clear()\n```\n\nClear cleanup the list.\n\n<a name=\"DList[T].ForEach\"></a>\n### func \\(\\*DList\\[T\\]\\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L164>)\n\n```go\nfunc (l *DList[T]) ForEach(cb func(val T))\n```\n\nForEach iterate the list, apply each element to the cb callback function.\n\n<a name=\"DList[T].ForEachIf\"></a>\n### func \\(\\*DList\\[T\\]\\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L175>)\n\n```go\nfunc (l *DList[T]) ForEachIf(cb func(val T) bool)\n```\n\nForEachIf iterate the list, apply each element to the cb callback function, stop if cb returns false.\n\n<a name=\"DList[T].ForEachMutable\"></a>\n### func \\(\\*DList\\[T\\]\\) [ForEachMutable](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L187>)\n\n```go\nfunc (l *DList[T]) ForEachMutable(cb func(val *T))\n```\n\nForEachMutable iterate the list, apply pointer of each element to the cb callback function.\n\n<a name=\"DList[T].ForEachMutableIf\"></a>\n### func \\(\\*DList\\[T\\]\\) [ForEachMutableIf](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L198>)\n\n```go\nfunc (l *DList[T]) ForEachMutableIf(cb func(val *T) bool)\n```\n\nForEachMutableIf iterate the list, apply pointer of each element to the cb callback function, stop if cb returns false.\n\n<a name=\"DList[T].Front\"></a>\n### func \\(\\*DList\\[T\\]\\) [Front](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L80>)\n\n```go\nfunc (l *DList[T]) Front() T\n```\n\nFront returns the first element in the container.\n\n<a name=\"DList[T].IsEmpty\"></a>\n### func \\(\\*DList\\[T\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L40>)\n\n```go\nfunc (l *DList[T]) IsEmpty() bool\n```\n\nIsEmpty return whether the list is empty.\n\n<a name=\"DList[T].Iterate\"></a>\n### func \\(\\*DList\\[T\\]\\) [Iterate](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L71>)\n\n```go\nfunc (l *DList[T]) Iterate() MutableIterator[T]\n```\n\nIterate returns an iterator to the first element in the list.\n\n<a name=\"DList[T].Len\"></a>\n### func \\(\\*DList\\[T\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L35>)\n\n```go\nfunc (l *DList[T]) Len() int\n```\n\nLen return the length of the list.\n\n<a name=\"DList[T].PopBack\"></a>\n### func \\(\\*DList\\[T\\]\\) [PopBack](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L123>)\n\n```go\nfunc (l *DList[T]) PopBack() T\n```\n\nPopBack popups an element from the back of the list.\n\n<a name=\"DList[T].PopFront\"></a>\n### func \\(\\*DList\\[T\\]\\) [PopFront](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L114>)\n\n```go\nfunc (l *DList[T]) PopFront() T\n```\n\nPopFront popups an element from the front of the list.\n\n<a name=\"DList[T].PushBack\"></a>\n### func \\(\\*DList\\[T\\]\\) [PushBack](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L105>)\n\n```go\nfunc (l *DList[T]) PushBack(val T)\n```\n\nPushBack pushes an element at the back of the list.\n\n<a name=\"DList[T].PushFront\"></a>\n### func \\(\\*DList\\[T\\]\\) [PushFront](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L96>)\n\n```go\nfunc (l *DList[T]) PushFront(val T)\n```\n\nPushFront pushes an element at the front of the list.\n\n<a name=\"DList[T].String\"></a>\n### func \\(\\*DList\\[T\\]\\) [String](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L45>)\n\n```go\nfunc (l *DList[T]) String() string\n```\n\nString convert the list to string.\n\n<a name=\"DList[T].TryPopBack\"></a>\n### func \\(\\*DList\\[T\\]\\) [TryPopBack](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L148>)\n\n```go\nfunc (l *DList[T]) TryPopBack() (T, bool)\n```\n\nTryPopBack tries to pop up an element from the back of the list.\n\n<a name=\"DList[T].TryPopFront\"></a>\n### func \\(\\*DList\\[T\\]\\) [TryPopFront](<https://github.com/chen3feng/stl4go/blob/master/dlist.go#L132>)\n\n```go\nfunc (l *DList[T]) TryPopFront() (T, bool)\n```\n\nTryPopFront tries to pop up an element from the front of the list.\n\n<a name=\"DListQueue\"></a>\n## type [DListQueue](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L8-L10>)\n\nDListQueue is a FIFO container\n\n```go\ntype DListQueue[T any] struct {\n    // contains filtered or unexported fields\n}\n```\n\n<a name=\"NewDListQueue\"></a>\n### func [NewDListQueue](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L13>)\n\n```go\nfunc NewDListQueue[T any]() *DListQueue[T]\n```\n\nNewDListQueue create a new Queue object.\n\n<a name=\"DListQueue[T].Back\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [Back](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L44>)\n\n```go\nfunc (q *DListQueue[T]) Back() T\n```\n\nBack returns the last element in the container.\n\n<a name=\"DListQueue[T].Clear\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L29>)\n\n```go\nfunc (q *DListQueue[T]) Clear()\n```\n\nClear implements the Container interface.\n\n<a name=\"DListQueue[T].Front\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [Front](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L39>)\n\n```go\nfunc (q *DListQueue[T]) Front() T\n```\n\nFront returns the first element in the container.\n\n<a name=\"DListQueue[T].IsEmpty\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L24>)\n\n```go\nfunc (q *DListQueue[T]) IsEmpty() bool\n```\n\nIsEmpty implements the Container interface.\n\n<a name=\"DListQueue[T].Len\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L19>)\n\n```go\nfunc (q *DListQueue[T]) Len() int\n```\n\nLen implements the Container interface.\n\n<a name=\"DListQueue[T].PopBack\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [PopBack](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L64>)\n\n```go\nfunc (q *DListQueue[T]) PopBack() T\n```\n\nPopBack popups an element from the back of the queue.\n\n<a name=\"DListQueue[T].PopFront\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [PopFront](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L59>)\n\n```go\nfunc (q *DListQueue[T]) PopFront() T\n```\n\nPopFront popups an element from the front of the queue.\n\n<a name=\"DListQueue[T].PushBack\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [PushBack](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L54>)\n\n```go\nfunc (q *DListQueue[T]) PushBack(val T)\n```\n\nPushBack pushed an element to the back of the queue.\n\n<a name=\"DListQueue[T].PushFront\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [PushFront](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L49>)\n\n```go\nfunc (q *DListQueue[T]) PushFront(val T)\n```\n\nPushFront pushed an element to the front of the queue.\n\n<a name=\"DListQueue[T].String\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [String](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L34>)\n\n```go\nfunc (q *DListQueue[T]) String() string\n```\n\nLen implements the fmt.Stringer interface.\n\n<a name=\"DListQueue[T].TryPopBack\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [TryPopBack](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L74>)\n\n```go\nfunc (q *DListQueue[T]) TryPopBack() (T, bool)\n```\n\nTryPopBack tries popuping an element from the back of the queue.\n\n<a name=\"DListQueue[T].TryPopFront\"></a>\n### func \\(\\*DListQueue\\[T\\]\\) [TryPopFront](<https://github.com/chen3feng/stl4go/blob/master/dlist_queue.go#L69>)\n\n```go\nfunc (q *DListQueue[T]) TryPopFront() (T, bool)\n```\n\nTryPopFront tries popuping an element from the front of the queue.\n\n<a name=\"Deque\"></a>\n## type [Deque](<https://github.com/chen3feng/stl4go/blob/master/container.go#L81-L91>)\n\nDeque is a container that can add and remove elements from both ends.\n\n```go\ntype Deque[T any] interface {\n    Container\n    Front() T               // Front returns the first element in the container.\n    Back() T                // Back returns the last element in the container.\n    PushFront(T)            // PushBack pushes an element at the front of the container.\n    PushBack(T)             // PushBack pushes an element at the back of the container.\n    PopFront() T            // PopBack popups a front from the back of the container.\n    PopBack() T             // PopBack popups a element from the back of the container.\n    TryPopFront() (T, bool) // TryPopFront tries to popup a element from the front of the container.\n    TryPopBack() (T, bool)  // TryPopBack tries to popup a element from the back of the container.\n}\n```\n\n<a name=\"Float\"></a>\n## type [Float](<https://github.com/chen3feng/stl4go/blob/master/types.go#L27-L29>)\n\nFloat 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.\n\n```go\ntype Float interface {\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"HashFn\"></a>\n## type [HashFn](<https://github.com/chen3feng/stl4go/blob/master/types.go#L54>)\n\nHashFn is a function that returns the hash of 't'.\n\n```go\ntype HashFn[T any] func(t T) uint64\n```\n\n<a name=\"Integer\"></a>\n## type [Integer](<https://github.com/chen3feng/stl4go/blob/master/types.go#L20-L22>)\n\nInteger 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.\n\n```go\ntype Integer interface {\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"Iterator\"></a>\n## type [Iterator](<https://github.com/chen3feng/stl4go/blob/master/iterator.go#L4-L8>)\n\nIterator is the interface for container's iterator.\n\n```go\ntype Iterator[T any] interface {\n    IsNotEnd() bool // Whether it is point to the end of the range.\n    MoveToNext()    // Let it point to the next element.\n    Value() T       // Return the value of current element.\n}\n```\n\n<a name=\"LessFn\"></a>\n## type [LessFn](<https://github.com/chen3feng/stl4go/blob/master/types.go#L45>)\n\nLessFn is a function that returns whether 'a' is less than 'b'.\n\n```go\ntype LessFn[T any] func(a, b T) bool\n```\n\n<a name=\"Map\"></a>\n## type [Map](<https://github.com/chen3feng/stl4go/blob/master/container.go#L11-L21>)\n\nMap is a associative container that contains key\\-value pairs with unique keys.\n\n```go\ntype Map[K any, V any] interface {\n    Container\n    Has(K) bool                        // Checks whether the container contains element with specific key.\n    Find(K) *V                         // Finds element with specific key.\n    Insert(K, V)                       // Inserts a key-value pair in to the container or replace existing value.\n    Remove(K) bool                     // Remove element with specific key.\n    ForEach(func(K, V))                // Iterate the container.\n    ForEachIf(func(K, V) bool)         // Iterate the container, stops when the callback returns false.\n    ForEachMutable(func(K, *V))        // Iterate the container, *V is mutable.\n    ForEachMutableIf(func(K, *V) bool) // Iterate the container, *V is mutable, stops when the callback returns false.\n}\n```\n\n<a name=\"MapIterator\"></a>\n## type [MapIterator](<https://github.com/chen3feng/stl4go/blob/master/iterator.go#L17-L20>)\n\nMapIterator is the interface for map's iterator.\n\n```go\ntype MapIterator[K any, V any] interface {\n    Key() K // The key of the element\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"MutableIterator\"></a>\n## type [MutableIterator](<https://github.com/chen3feng/stl4go/blob/master/iterator.go#L11-L14>)\n\nMutableIterator is the interface for container's mutable iterator.\n\n```go\ntype MutableIterator[T any] interface {\n    Pointer() *T // Return the pointer to the value of current element.\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"MutableMapIterator\"></a>\n## type [MutableMapIterator](<https://github.com/chen3feng/stl4go/blob/master/iterator.go#L23-L26>)\n\nMutableMapIterator is the interface for map's mutable iterator.\n\n```go\ntype MutableMapIterator[K any, V any] interface {\n    Key() K // The key of the element\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"Numeric\"></a>\n## type [Numeric](<https://github.com/chen3feng/stl4go/blob/master/types.go#L40-L42>)\n\nNumeric is a constraint that permits any numeric type.\n\n```go\ntype Numeric interface {\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"Ordered\"></a>\n## type [Ordered](<https://github.com/chen3feng/stl4go/blob/master/types.go#L35-L37>)\n\nOrdered 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.\n\n```go\ntype Ordered interface {\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"Pool\"></a>\n## type [Pool](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L6>)\n\nPool is a type safed sync.Pool.\n\n```go\ntype Pool[T any] sync.Pool\n```\n\n<a name=\"MakePool\"></a>\n### func [MakePool](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L9>)\n\n```go\nfunc MakePool[T any]() Pool[T]\n```\n\nMakePool returns a Pool object\n\n<a name=\"MakePoolWithNew\"></a>\n### func [MakePoolWithNew](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L14>)\n\n```go\nfunc MakePoolWithNew[T any](new func() *T) Pool[T]\n```\n\nMakePoolWithNew returns a Pool object with specified new function.\n\n<a name=\"Pool[T].Get\"></a>\n### func \\(\\*Pool\\[T\\]\\) [Get](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L22>)\n\n```go\nfunc (pool *Pool[T]) Get() *T\n```\n\nGet selects an arbitrary item from the Pool, removes it from the Pool, and returns it to the caller.\n\n<a name=\"Pool[T].Put\"></a>\n### func \\(\\*Pool\\[T\\]\\) [Put](<https://github.com/chen3feng/stl4go/blob/master/pool.go#L31>)\n\n```go\nfunc (pool *Pool[T]) Put(x *T)\n```\n\nPut puts x to the pool.\n\n<a name=\"PriorityQueue\"></a>\n## type [PriorityQueue](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L6-L9>)\n\nPriorityQueue 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.\n\n```go\ntype PriorityQueue[T any] struct {\n    // contains filtered or unexported fields\n}\n```\n\n<details><summary>Example</summary>\n<p>\n\nThis example inserts several ints into an IntHeap, checks the minimum, and removes them in order of priority.\n\n```go\nh := NewPriorityQueue[int]()\nh.Push(3)\nh.Push(2)\nh.Push(1)\nh.Push(5)\nfmt.Printf(\"minimum: %d\\n\", h.Top())\n\nfor h.Len() > 0 {\n\tfmt.Printf(\"%d \", h.Pop())\n}\n// Output:\n// minimum: 1\n// 1 2 3 5\n```\n\n#### Output\n\n```\nminimum: 1\n1 2 3 5\n```\n\n</p>\n</details>\n\n<a name=\"NewPriorityQueue\"></a>\n### func [NewPriorityQueue](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L12>)\n\n```go\nfunc NewPriorityQueue[T Ordered]() *PriorityQueue[T]\n```\n\nNewPriorityQueue creates an empty priority object.\n\n<a name=\"NewPriorityQueueFunc\"></a>\n### func [NewPriorityQueueFunc](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L34>)\n\n```go\nfunc NewPriorityQueueFunc[T any](less LessFn[T]) *PriorityQueue[T]\n```\n\nNewPriorityQueueFunc creates an empty priority object with specified compare function less.\n\n<a name=\"NewPriorityQueueOf\"></a>\n### func [NewPriorityQueueOf](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L29>)\n\n```go\nfunc NewPriorityQueueOf[T Ordered](elements ...T) *PriorityQueue[T]\n```\n\nNewPriorityQueueOf creates a new priority object with specified initial elements.\n\n<a name=\"NewPriorityQueueOn\"></a>\n### func [NewPriorityQueueOn](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L20>)\n\n```go\nfunc NewPriorityQueueOn[T Ordered](slice []T) *PriorityQueue[T]\n```\n\nNewPriorityQueueOn creates a new priority object on the specified slices. The slice become a heap after the call.\n\n<a name=\"PriorityQueue[T].Clear\"></a>\n### func \\(\\*PriorityQueue\\[T\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L52>)\n\n```go\nfunc (pq *PriorityQueue[T]) Clear()\n```\n\nClear clear the priority queue.\n\n<a name=\"PriorityQueue[T].IsEmpty\"></a>\n### func \\(\\*PriorityQueue\\[T\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L47>)\n\n```go\nfunc (pq *PriorityQueue[T]) IsEmpty() bool\n```\n\nIsEmpty checks whether priority queue has no elements.\n\n<a name=\"PriorityQueue[T].Len\"></a>\n### func \\(\\*PriorityQueue\\[T\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L42>)\n\n```go\nfunc (pq *PriorityQueue[T]) Len() int\n```\n\nLen returns the number of elements in the priority queue.\n\n<a name=\"PriorityQueue[T].Pop\"></a>\n### func \\(\\*PriorityQueue\\[T\\]\\) [Pop](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L67>)\n\n```go\nfunc (pq *PriorityQueue[T]) Pop() T\n```\n\nPop removes the top element in the priority queue.\n\n<a name=\"PriorityQueue[T].Push\"></a>\n### func \\(\\*PriorityQueue\\[T\\]\\) [Push](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L62>)\n\n```go\nfunc (pq *PriorityQueue[T]) Push(v T)\n```\n\nPush pushes the given element v to the priority queue.\n\n<a name=\"PriorityQueue[T].Top\"></a>\n### func \\(\\*PriorityQueue\\[T\\]\\) [Top](<https://github.com/chen3feng/stl4go/blob/master/priority_queue.go#L57>)\n\n```go\nfunc (pq *PriorityQueue[T]) Top() T\n```\n\nTop returns the top element in the priority queue.\n\n<a name=\"Queue\"></a>\n## type [Queue](<https://github.com/chen3feng/stl4go/blob/master/container.go#L71-L78>)\n\nQueue is a container that can add elements to one end and remove elements from the other end.\n\n```go\ntype Queue[T any] interface {\n    Container\n    Front()            // Front returns the first element in the container.\n    Back()             // Back returns the last element in the container.\n    Push(T)            // Push pushes an element at the back of the container.\n    Pop() T            // Pop popups a front from the back of the container.\n    TryPop() (T, bool) // TryPop tries to popup a element from the front of the container.\n}\n```\n\n<a name=\"SList\"></a>\n## type [SList](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L4-L8>)\n\nSList is a singly linked list.\n\n```go\ntype SList[T any] struct {\n    // contains filtered or unexported fields\n}\n```\n\n<a name=\"SListOf\"></a>\n### func [SListOf](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L16>)\n\n```go\nfunc SListOf[T any](values ...T) SList[T]\n```\n\nSListOf return a SList that contains values.\n\n<a name=\"SList[T].Back\"></a>\n### func \\(\\*SList\\[T\\]\\) [Back](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L50>)\n\n```go\nfunc (l *SList[T]) Back() T\n```\n\nBack returns the last element in the list.\n\n<a name=\"SList[T].Clear\"></a>\n### func \\(\\*SList\\[T\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L35>)\n\n```go\nfunc (l *SList[T]) Clear()\n```\n\nClear erases all elements from the container. After this call, Len\\(\\) returns zero.\n\n<a name=\"SList[T].ForEach\"></a>\n### func \\(\\*SList\\[T\\]\\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L134>)\n\n```go\nfunc (l *SList[T]) ForEach(cb func(T))\n```\n\nForEach iterate the list, apply each element to the cb callback function.\n\n<a name=\"SList[T].ForEachIf\"></a>\n### func \\(\\*SList\\[T\\]\\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L142>)\n\n```go\nfunc (l *SList[T]) ForEachIf(cb func(T) bool)\n```\n\nForEachIf iterate the container, apply each element to the cb callback function, stop if cb returns false.\n\n<a name=\"SList[T].ForEachMutable\"></a>\n### func \\(\\*SList\\[T\\]\\) [ForEachMutable](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L151>)\n\n```go\nfunc (l *SList[T]) ForEachMutable(cb func(*T))\n```\n\nForEachMutable iterate the container, apply pointer of each element to the cb callback function.\n\n<a name=\"SList[T].ForEachMutableIf\"></a>\n### func \\(\\*SList\\[T\\]\\) [ForEachMutableIf](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L159>)\n\n```go\nfunc (l *SList[T]) ForEachMutableIf(cb func(*T) bool)\n```\n\nForEachMutableIf iterate the container, apply pointer of each element to the cb callback function, stop if cb returns false.\n\n<a name=\"SList[T].Front\"></a>\n### func \\(\\*SList\\[T\\]\\) [Front](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L42>)\n\n```go\nfunc (l *SList[T]) Front() T\n```\n\nFront returns the first element in the list.\n\n<a name=\"SList[T].IsEmpty\"></a>\n### func \\(\\*SList\\[T\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L25>)\n\n```go\nfunc (l *SList[T]) IsEmpty() bool\n```\n\nIsEmpty checks if the container has no elements.\n\n<a name=\"SList[T].Iterate\"></a>\n### func \\(\\*SList\\[T\\]\\) [Iterate](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L168>)\n\n```go\nfunc (l *SList[T]) Iterate() MutableIterator[T]\n```\n\nIterate returns an iterator to the whole container.\n\n<a name=\"SList[T].Len\"></a>\n### func \\(\\*SList\\[T\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L30>)\n\n```go\nfunc (l *SList[T]) Len() int\n```\n\nLen returns the number of elements in the container.\n\n<a name=\"SList[T].PopFront\"></a>\n### func \\(\\*SList\\[T\\]\\) [PopFront](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L82>)\n\n```go\nfunc (l *SList[T]) PopFront() T\n```\n\nPopFront popups an element from the front of the list. The list must be non\\-empty\\!\n\n<a name=\"SList[T].PushBack\"></a>\n### func \\(\\*SList\\[T\\]\\) [PushBack](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L68>)\n\n```go\nfunc (l *SList[T]) PushBack(v T)\n```\n\nPushBack pushed an element to the tail of the list.\n\n<a name=\"SList[T].PushFront\"></a>\n### func \\(\\*SList\\[T\\]\\) [PushFront](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L58>)\n\n```go\nfunc (l *SList[T]) PushFront(v T)\n```\n\nPushFront pushed an element to the front of the list.\n\n<a name=\"SList[T].Reverse\"></a>\n### func \\(\\*SList\\[T\\]\\) [Reverse](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L97>)\n\n```go\nfunc (l *SList[T]) Reverse()\n```\n\nReverse reverses the order of all elements in the container.\n\n<a name=\"SList[T].Values\"></a>\n### func \\(\\*SList\\[T\\]\\) [Values](<https://github.com/chen3feng/stl4go/blob/master/slist.go#L113>)\n\n```go\nfunc (l *SList[T]) Values() []T\n```\n\nValues copies all elements in the container to a slice and return it.\n\n<a name=\"Set\"></a>\n## type [Set](<https://github.com/chen3feng/stl4go/blob/master/container.go#L24-L33>)\n\nSet is a containers that store unique elements.\n\n```go\ntype Set[K any] interface {\n    Container\n    Has(K) bool             // Checks whether the container contains element with specific key.\n    Insert(K) bool          // Inserts a element in to the container or replace existing value.\n    InsertN(...K) int       // Inserts multiple elements in to the container or replace existing value.\n    Remove(K) bool          // Remove specific element, return true if element was in the container.\n    RemoveN(...K) int       // Remove multiple elements, return the number of removed elements.\n    ForEach(func(K))        // Iterate the container.\n    ForEachIf(func(K) bool) // Iterate the container, stops when the callback returns false.\n}\n```\n\n<a name=\"Signed\"></a>\n## type [Signed](<https://github.com/chen3feng/stl4go/blob/master/types.go#L6-L8>)\n\nSigned 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.\n\n```go\ntype Signed interface {\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"SkipList\"></a>\n## type [SkipList](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L28-L37>)\n\nSkipList 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.\n\nSee https://en.wikipedia.org/wiki/Skip_list for more details.\n\n```go\ntype SkipList[K any, V any] struct {\n    // contains filtered or unexported fields\n}\n```\n\n<a name=\"NewSkipList\"></a>\n### func [NewSkipList](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L40>)\n\n```go\nfunc NewSkipList[K Ordered, V any]() *SkipList[K, V]\n```\n\nNewSkipList creates a new SkipList for Ordered key type.\n\n<a name=\"NewSkipListFromMap\"></a>\n### func [NewSkipListFromMap](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L48>)\n\n```go\nfunc NewSkipListFromMap[K Ordered, V any](m map[K]V) *SkipList[K, V]\n```\n\nNewSkipListFromMap creates a new SkipList from a map.\n\n<a name=\"NewSkipListFunc\"></a>\n### func [NewSkipListFunc](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L57>)\n\n```go\nfunc NewSkipListFunc[K any, V any](keyCmp CompareFn[K]) *SkipList[K, V]\n```\n\nNewSkipListFunc creates a new SkipList with specified compare function keyCmp.\n\n<a name=\"SkipList[K, V].Clear\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L76>)\n\n```go\nfunc (sl *SkipList[K, V]) Clear()\n```\n\nClear implements the Container interface.\n\n<a name=\"SkipList[K, V].Find\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [Find](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L122>)\n\n```go\nfunc (sl *SkipList[K, V]) Find(key K) *V\n```\n\nFind returns the value associated with the passed key if the key is in the skiplist, otherwise returns nil.\n\n<a name=\"SkipList[K, V].FindRange\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [FindRange](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L150>)\n\n```go\nfunc (sl *SkipList[K, V]) FindRange(first, last K) MutableMapIterator[K, V]\n```\n\nFindRange returns an iterator in range \\[first, last\\) \\(last is not included\\).\n\n<a name=\"SkipList[K, V].ForEach\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L173>)\n\n```go\nfunc (sl *SkipList[K, V]) ForEach(op func(K, V))\n```\n\nForEach implements the Map interface.\n\n<a name=\"SkipList[K, V].ForEachIf\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L187>)\n\n```go\nfunc (sl *SkipList[K, V]) ForEachIf(op func(K, V) bool)\n```\n\nForEachIf implements the Map interface.\n\n<a name=\"SkipList[K, V].ForEachMutable\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [ForEachMutable](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L180>)\n\n```go\nfunc (sl *SkipList[K, V]) ForEachMutable(op func(K, *V))\n```\n\nForEachMutable implements the Map interface.\n\n<a name=\"SkipList[K, V].ForEachMutableIf\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [ForEachMutableIf](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L196>)\n\n```go\nfunc (sl *SkipList[K, V]) ForEachMutableIf(op func(K, *V) bool)\n```\n\nForEachMutableIf implements the Map interface.\n\n<a name=\"SkipList[K, V].Has\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [Has](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L131>)\n\n```go\nfunc (sl *SkipList[K, V]) Has(key K) bool\n```\n\nHas implement the Map interface.\n\n<a name=\"SkipList[K, V].Insert\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [Insert](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L91>)\n\n```go\nfunc (sl *SkipList[K, V]) Insert(key K, value V)\n```\n\nInsert inserts a key\\-value pair into the skiplist. If the key is already in the skip list, it's value will be updated.\n\n<a name=\"SkipList[K, V].IsEmpty\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L66>)\n\n```go\nfunc (sl *SkipList[K, V]) IsEmpty() bool\n```\n\nIsEmpty implements the Container interface.\n\n<a name=\"SkipList[K, V].Iterate\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [Iterate](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L85>)\n\n```go\nfunc (sl *SkipList[K, V]) Iterate() MutableMapIterator[K, V]\n```\n\nIterate return an iterator to the skiplist.\n\n<a name=\"SkipList[K, V].Len\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L71>)\n\n```go\nfunc (sl *SkipList[K, V]) Len() int\n```\n\nLen implements the Container interface.\n\n<a name=\"SkipList[K, V].LowerBound\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [LowerBound](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L138>)\n\n```go\nfunc (sl *SkipList[K, V]) LowerBound(key K) MutableMapIterator[K, V]\n```\n\nLowerBound 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.\n\n<a name=\"SkipList[K, V].Remove\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [Remove](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L156>)\n\n```go\nfunc (sl *SkipList[K, V]) Remove(key K) bool\n```\n\nRemove removes the key\\-value pair associated with the passed key and returns true if the key is in the skiplist, otherwise returns false.\n\n<a name=\"SkipList[K, V].UpperBound\"></a>\n### func \\(\\*SkipList\\[K, V\\]\\) [UpperBound](<https://github.com/chen3feng/stl4go/blob/master/skiplist.go#L145>)\n\n```go\nfunc (sl *SkipList[K, V]) UpperBound(key K) MutableMapIterator[K, V]\n```\n\nUpperBound 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.\n\n<a name=\"SkipListSet\"></a>\n## type [SkipListSet](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L4>)\n\nSkipListSet is a SortedSet implemented with skiplist.\n\n```go\ntype SkipListSet[K any] SkipList[K, struct{}]\n```\n\n<a name=\"NewSkipListSet\"></a>\n### func [NewSkipListSet](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L7>)\n\n```go\nfunc NewSkipListSet[K Ordered]() *SkipListSet[K]\n```\n\nNewSkipListSet creates a new SkipListSet object.\n\n<a name=\"NewSkipListSetFunc\"></a>\n### func [NewSkipListSetFunc](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L12>)\n\n```go\nfunc NewSkipListSetFunc[K any](cmp CompareFn[K]) *SkipListSet[K]\n```\n\nNewSkipListSetFunc creates a new SkipListSet object with specified compare function.\n\n<a name=\"NewSkipListSetOf\"></a>\n### func [NewSkipListSetOf](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L17>)\n\n```go\nfunc NewSkipListSetOf[K Ordered](elements ...K) *SkipListSet[K]\n```\n\nNewSkipListSetOf creates a new SkipListSet object with specified elements.\n\n<a name=\"SkipListSet[K].Clear\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L36>)\n\n```go\nfunc (s *SkipListSet[K]) Clear()\n```\n\nClear implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].FindRange\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [FindRange](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L103>)\n\n```go\nfunc (s *SkipListSet[K]) FindRange(first, last K) Iterator[K]\n```\n\nFindRange implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].ForEach\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L83>)\n\n```go\nfunc (s *SkipListSet[K]) ForEach(f func(K))\n```\n\nForEach implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].ForEachIf\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L88>)\n\n```go\nfunc (s *SkipListSet[K]) ForEachIf(f func(K) bool)\n```\n\nForEachIf implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].Has\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [Has](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L41>)\n\n```go\nfunc (s *SkipListSet[K]) Has(key K) bool\n```\n\nHas implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].Insert\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [Insert](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L46>)\n\n```go\nfunc (s *SkipListSet[K]) Insert(key K) bool\n```\n\nInsert implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].InsertN\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [InsertN](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L53>)\n\n```go\nfunc (s *SkipListSet[K]) InsertN(keys ...K) int\n```\n\nInsertN implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].IsEmpty\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L26>)\n\n```go\nfunc (s *SkipListSet[K]) IsEmpty() bool\n```\n\nIsEmpty implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].Keys\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [Keys](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L76>)\n\n```go\nfunc (s *SkipListSet[K]) Keys() []K\n```\n\nKeys return a copy of sorted keys as slice.\n\n<a name=\"SkipListSet[K].Len\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L31>)\n\n```go\nfunc (s *SkipListSet[K]) Len() int\n```\n\nLen implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].LowerBound\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [LowerBound](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L93>)\n\n```go\nfunc (s *SkipListSet[K]) LowerBound(key K) Iterator[K]\n```\n\nLowerBound implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].Remove\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [Remove](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L62>)\n\n```go\nfunc (s *SkipListSet[K]) Remove(key K) bool\n```\n\nRemove implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].RemoveN\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [RemoveN](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L67>)\n\n```go\nfunc (s *SkipListSet[K]) RemoveN(keys ...K) int\n```\n\nRemoveN implements the SortedSet interface.\n\n<a name=\"SkipListSet[K].UpperBound\"></a>\n### func \\(\\*SkipListSet\\[K\\]\\) [UpperBound](<https://github.com/chen3feng/stl4go/blob/master/skiplist_set.go#L98>)\n\n```go\nfunc (s *SkipListSet[K]) UpperBound(key K) Iterator[K]\n```\n\nUpperBound implements the SortedSet interface.\n\n<a name=\"SortedMap\"></a>\n## type [SortedMap](<https://github.com/chen3feng/stl4go/blob/master/container.go#L36-L50>)\n\nSortedMap is a Map that provides a total ordering on its keys.\n\n```go\ntype SortedMap[K any, V any] interface {\n\n    // LowerBound returns an iterator to the first element in the container that\n    // does not satisfy element.key < value (i.e. greater or equal to),\n    // or a end iterator if no such element is found.\n    LowerBound(K) MutableMapIterator[K, V]\n\n    // UpperBound returns an iterator to the first element in the container that\n    // does not satisfy value < element.key (i.e. strictly greater),\n    // or a end iterator if no such element is found.\n    UpperBound(K) MutableMapIterator[K, V]\n\n    // FindRange returns an iterator in range [first, last) (last is not included).\n    FindRange(K, K) MutableMapIterator[K, V]\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"SortedSet\"></a>\n## type [SortedSet](<https://github.com/chen3feng/stl4go/blob/master/container.go#L53-L68>)\n\nSortedSet is a Set that provides a total ordering on its elements.\n\n```go\ntype SortedSet[K any] interface {\n\n    // LowerBound returns an iterator to the first element in the container that\n    // does not satisfy element < value (i.e. greater or equal to),\n    // or a end iterator if no such element is found.\n    LowerBound(K) Iterator[K]\n\n    // UpperBound returns an iterator to the first element in the container that\n    // does not satisfy value < element (i.e. strictly greater),\n    // or a end iterator if no such element is found.\n    UpperBound(K) Iterator[K]\n\n    // FindRange returns an iterator in range [first, last) (last is not included).\n    FindRange(K, K) Iterator[K]\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"Stack\"></a>\n## type [Stack](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L5-L7>)\n\nStack s is a container adaptor that provides the functionality of a stack, a LIFO \\(last\\-in, first\\-out\\) data structure.\n\n```go\ntype Stack[T any] struct {\n    // contains filtered or unexported fields\n}\n```\n\n<a name=\"NewStack\"></a>\n### func [NewStack](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L10>)\n\n```go\nfunc NewStack[T any]() *Stack[T]\n```\n\nNewStack creates a new Stack object.\n\n<a name=\"NewStackCap\"></a>\n### func [NewStackCap](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L15>)\n\n```go\nfunc NewStackCap[T any](capicity int) *Stack[T]\n```\n\nNewStackCap creates a new Stack object with the specified capicity.\n\n<a name=\"Stack[T].Cap\"></a>\n### func \\(Stack\\[T\\]\\) [Cap](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L30>)\n\n```go\nfunc (s Stack[T]) Cap() int\n```\n\nCap returns the capacity of the stack.\n\n<a name=\"Stack[T].Clear\"></a>\n### func \\(\\*Stack\\[T\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L35>)\n\n```go\nfunc (s *Stack[T]) Clear()\n```\n\nClear implements the Container interface.\n\n<a name=\"Stack[T].IsEmpty\"></a>\n### func \\(Stack\\[T\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L20>)\n\n```go\nfunc (s Stack[T]) IsEmpty() bool\n```\n\nIsEmpty implements the Container interface.\n\n<a name=\"Stack[T].Len\"></a>\n### func \\(Stack\\[T\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L25>)\n\n```go\nfunc (s Stack[T]) Len() int\n```\n\nLen implements the Container interface.\n\n<a name=\"Stack[T].Pop\"></a>\n### func \\(\\*Stack\\[T\\]\\) [Pop](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L58>)\n\n```go\nfunc (s *Stack[T]) Pop() T\n```\n\nPop popups an element from the top of the stack. It must be called when IsEmpty\\(\\) returned false, otherwise it will panic.\n\n<a name=\"Stack[T].Push\"></a>\n### func \\(\\*Stack\\[T\\]\\) [Push](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L40>)\n\n```go\nfunc (s *Stack[T]) Push(t T)\n```\n\nPush pushes the element to the top of the stack.\n\n<a name=\"Stack[T].Top\"></a>\n### func \\(Stack\\[T\\]\\) [Top](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L67>)\n\n```go\nfunc (s Stack[T]) Top() T\n```\n\nTop returns the top element in the stack. It must be called when s.IsEmpty\\(\\) returned false, otherwise it will panic.\n\n<a name=\"Stack[T].TryPop\"></a>\n### func \\(\\*Stack\\[T\\]\\) [TryPop](<https://github.com/chen3feng/stl4go/blob/master/stack.go#L45>)\n\n```go\nfunc (s *Stack[T]) TryPop() (val T, ok bool)\n```\n\nTryPop tries to popup an element from the top of the stack.\n\n<a name=\"Unsigned\"></a>\n## type [Unsigned](<https://github.com/chen3feng/stl4go/blob/master/types.go#L13-L15>)\n\nUnsigned 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.\n\n```go\ntype Unsigned interface {\n    // contains filtered or unexported methods\n}\n```\n\n<a name=\"Vector\"></a>\n## type [Vector](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L7>)\n\nVector is a sequence container representing array that can change in size.\n\n```go\ntype Vector[T any] []T\n```\n\n<a name=\"AsVector\"></a>\n### func [AsVector](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L26>)\n\n```go\nfunc AsVector[T any](s []T) Vector[T]\n```\n\nAsVector casts a slice as a Vector object.\n\n<a name=\"MakeVector\"></a>\n### func [MakeVector](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L10>)\n\n```go\nfunc MakeVector[T any]() Vector[T]\n```\n\nMakeVector creates an empty Vector object.\n\n<a name=\"MakeVectorCap\"></a>\n### func [MakeVectorCap](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L15>)\n\n```go\nfunc MakeVectorCap[T any](c int) Vector[T]\n```\n\nMakeVectorCap creates an empty Vector object with specified capacity.\n\n<a name=\"VectorOf\"></a>\n### func [VectorOf](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L21>)\n\n```go\nfunc VectorOf[T any](v ...T) Vector[T]\n```\n\nVectorOf creates a Vector object with initial values.\n\n<a name=\"Vector[T].Append\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Append](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L120>)\n\n```go\nfunc (v *Vector[T]) Append(x ...T)\n```\n\nAppend appends the values x... to the tail of the vector.\n\n<a name=\"Vector[T].At\"></a>\n### func \\(\\*Vector\\[T\\]\\) [At](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L75>)\n\n```go\nfunc (v *Vector[T]) At(i int) T\n```\n\nAt returns the element value at the index i. You can also use the \\[\\] operator, and it's better.\n\n<a name=\"Vector[T].Back\"></a>\n### func \\(Vector\\[T\\]\\) [Back](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L115>)\n\n```go\nfunc (v Vector[T]) Back() T\n```\n\nBack returns the element at the end of the vector. It must be called when IsEmpty\\(\\) returned false, otherwise it will panic.\n\n<a name=\"Vector[T].Cap\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Cap](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L41>)\n\n```go\nfunc (v *Vector[T]) Cap() int\n```\n\nCap returns the capacity of the vector.\n\n<a name=\"Vector[T].Clear\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Clear](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L47>)\n\n```go\nfunc (v *Vector[T]) Clear()\n```\n\nClear erases all elements from the vector. After this call, Len\\(\\) returns zero. Leaves the Cap\\(\\) of the vector unchanged.\n\n<a name=\"Vector[T].ForEach\"></a>\n### func \\(Vector\\[T\\]\\) [ForEach](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L166>)\n\n```go\nfunc (v Vector[T]) ForEach(cb func(val T))\n```\n\nForEach iterate the container, apply each element to the cb callback function.\n\n<a name=\"Vector[T].ForEachIf\"></a>\n### func \\(Vector\\[T\\]\\) [ForEachIf](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L174>)\n\n```go\nfunc (v Vector[T]) ForEachIf(cb func(val T) bool)\n```\n\nForEachIf iterate the container, apply each element to the cb callback function, stop if cb returns false.\n\n<a name=\"Vector[T].ForEachMutable\"></a>\n### func \\(Vector\\[T\\]\\) [ForEachMutable](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L183>)\n\n```go\nfunc (v Vector[T]) ForEachMutable(cb func(val *T))\n```\n\nForEachMutable iterate the container, apply pointer of each element to the cb callback function.\n\n<a name=\"Vector[T].ForEachMutableIf\"></a>\n### func \\(Vector\\[T\\]\\) [ForEachMutableIf](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L191>)\n\n```go\nfunc (v Vector[T]) ForEachMutableIf(cb func(val *T) bool)\n```\n\nForEachMutableIf iterate the container, apply pointer of each element to the cb callback function, stop if cb returns false.\n\n<a name=\"Vector[T].Insert\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Insert](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L129>)\n\n```go\nfunc (v *Vector[T]) Insert(i int, x ...T)\n```\n\nInsert 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.\n\nComplexity: O\\(len\\(s\\) \\+ len\\(v\\)\\).\n\n<a name=\"Vector[T].IsEmpty\"></a>\n### func \\(\\*Vector\\[T\\]\\) [IsEmpty](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L31>)\n\n```go\nfunc (v *Vector[T]) IsEmpty() bool\n```\n\nIsEmpty implements the Container interface.\n\n<a name=\"Vector[T].Iterate\"></a>\n### func \\(Vector\\[T\\]\\) [Iterate](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L200>)\n\n```go\nfunc (v Vector[T]) Iterate() MutableIterator[T]\n```\n\nIterate returns an iterator to the whole container.\n\n<a name=\"Vector[T].IterateRange\"></a>\n### func \\(Vector\\[T\\]\\) [IterateRange](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L205>)\n\n```go\nfunc (v Vector[T]) IterateRange(i, j int) MutableIterator[T]\n```\n\nIterateRange returns an iterator to the range \\[i, j\\) of the container.\n\n<a name=\"Vector[T].Len\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Len](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L36>)\n\n```go\nfunc (v *Vector[T]) Len() int\n```\n\nLen implements the Container interface.\n\n<a name=\"Vector[T].PopBack\"></a>\n### func \\(\\*Vector\\[T\\]\\) [PopBack](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L95>)\n\n```go\nfunc (v *Vector[T]) PopBack() T\n```\n\nPopBack popups an element from the end of the vector. It must be called when IsEmpty\\(\\) returned false, otherwise it will panic.\n\n<a name=\"Vector[T].PushBack\"></a>\n### func \\(\\*Vector\\[T\\]\\) [PushBack](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L88>)\n\n```go\nfunc (v *Vector[T]) PushBack(x T)\n```\n\nPushBack pushs an element to the end of the vector.\n\nComplexity: O\\(1\\) if v.Len\\(\\) \\< v.Cap\\(\\), therwise O\\(len\\(v\\)\\).\n\n<a name=\"Vector[T].Remove\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Remove](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L149>)\n\n```go\nfunc (v *Vector[T]) Remove(i int)\n```\n\nRemove removes 1 element in the vector.\n\nComplexity: O\\(len\\(s\\) \\- i\\).\n\n<a name=\"Vector[T].RemoveLength\"></a>\n### func \\(\\*Vector\\[T\\]\\) [RemoveLength](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L161>)\n\n```go\nfunc (v *Vector[T]) RemoveLength(i int, len int)\n```\n\nRemoveLength removes the elements in the range\\[i, i\\+len\\) from the vector.\n\n<a name=\"Vector[T].RemoveRange\"></a>\n### func \\(\\*Vector\\[T\\]\\) [RemoveRange](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L154>)\n\n```go\nfunc (v *Vector[T]) RemoveRange(i, j int)\n```\n\nRemoveRange removes the elements in the range\\[i, j\\) from the vector.\n\n<a name=\"Vector[T].Reserve\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Reserve](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L58>)\n\n```go\nfunc (v *Vector[T]) Reserve(l int)\n```\n\nReserve 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.\n\nReserve\\(\\) does not change the size of the vector.\n\n<a name=\"Vector[T].Set\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Set](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L81>)\n\n```go\nfunc (v *Vector[T]) Set(i int, x T)\n```\n\nSet sets the value of the element at the index i. You can also use the \\[\\] operator, and it's better.\n\n<a name=\"Vector[T].Shrink\"></a>\n### func \\(\\*Vector\\[T\\]\\) [Shrink](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L67>)\n\n```go\nfunc (v *Vector[T]) Shrink()\n```\n\nShrink removes unused capacity from the vector.\n\n<a name=\"Vector[T].TryPopBack\"></a>\n### func \\(\\*Vector\\[T\\]\\) [TryPopBack](<https://github.com/chen3feng/stl4go/blob/master/vector.go#L104>)\n\n```go\nfunc (v *Vector[T]) TryPopBack() (T, bool)\n```\n\nTryPopBack popups an element from the end of the vector.\n\nGenerated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)\n\n\n<!-- gomarkdoc:embed:end -->\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/chen3feng/stl4go\n\ngo 1.18\n"
  },
  {
    "path": "go.sum",
    "content": ""
  },
  {
    "path": "heap.go",
    "content": "// Fast generic heap algorithms, faster than [container/heap]\n\npackage stl4go\n\n// MakeMinHeap build a min-heap on slice array.\n//\n// Complexity: O(len(array))\nfunc MakeMinHeap[T Ordered](array []T) {\n\t// heapify\n\tn := len(array)\n\tfor i := n/2 - 1; i >= 0; i-- {\n\t\theapDown(array, i, n)\n\t}\n}\n\n// IsMinHeap checks whether the elements in slice array are a min heap.\n//\n// Complexity: O(len(array)).\nfunc IsMinHeap[T Ordered](array []T) bool {\n\tparent := 0\n\tfor child := 1; child < len(array); child++ {\n\t\tif array[parent] > array[child] {\n\t\t\treturn false\n\t\t}\n\n\t\tif (child & 1) == 0 {\n\t\t\tparent++\n\t\t}\n\t}\n\treturn true\n}\n\n// PushMinHeap pushes a element v into the min heap.\n//\n// Complexity: O(log(len(*heap))).\nfunc PushMinHeap[T Ordered](heap *[]T, v T) {\n\t*heap = append(*heap, v)\n\theapUp(*heap, len(*heap)-1)\n}\n\n// PopMinHeap removes and returns the minimum element from the heap.\n//\n// Complexity: O(log n) where n = len(*heap).\nfunc PopMinHeap[T Ordered](heap *[]T) T {\n\th := *heap\n\tn := len(h) - 1\n\theapSwap(h, 0, n)\n\theapDown(h, 0, n)\n\t*heap = h[0:n]\n\treturn h[n]\n}\n\n// RemoveMinHeap removes and returns the element at index i from the min heap.\n//\n// Complexity: is O(log(n)) where n = len(*heap).\nfunc RemoveMinHeap[T Ordered](heap *[]T, i int) T {\n\th := *heap\n\tn := len(h) - 1\n\tif n != i {\n\t\theapSwap(h, i, n)\n\t\tif !heapDown(h, i, n) {\n\t\t\theapUp(h, i)\n\t\t}\n\t}\n\t*heap = h[0:n]\n\treturn h[n]\n}\n\nfunc heapSwap[T any](heap []T, i, j int) {\n\theap[i], heap[j] = heap[j], heap[i]\n}\n\nfunc heapUp[T Ordered](heap []T, j int) {\n\tfor {\n\t\ti := (j - 1) / 2 // parent\n\t\tif i == j || !(heap[j] < heap[i]) {\n\t\t\tbreak\n\t\t}\n\t\theapSwap(heap, i, j)\n\t\tj = i\n\t}\n}\n\nfunc heapDown[T Ordered](heap []T, i0, n int) bool {\n\ti := i0\n\tfor {\n\t\tj1 := 2*i + 1\n\t\tif j1 >= n || j1 < 0 { // j1 < 0 after int overflow\n\t\t\tbreak\n\t\t}\n\t\tj := j1 // left child\n\t\tif j2 := j1 + 1; j2 < n && heap[j2] < heap[j1] {\n\t\t\tj = j2 // = 2*i + 2  // right child\n\t\t}\n\t\tif !(heap[j] < heap[i]) {\n\t\t\tbreak\n\t\t}\n\t\theapSwap(heap, i, j)\n\t\ti = j\n\t}\n\treturn i > i0\n}\n\n// MakeHeapFunc build a min-heap on slice array with compare function less.\n//\n// Complexity: O(len(array))\nfunc MakeHeapFunc[T any](array []T, less LessFn[T]) {\n\t// heapify\n\tn := len(array)\n\tfor i := n/2 - 1; i >= 0; i-- {\n\t\theapDownFunc(array, i, n, less)\n\t}\n}\n\n// IsHeapFunc checks whether the elements in slice array are a min heap (accord to less).\n//\n// Complexity: O(len(array)).\nfunc IsHeapFunc[T any](array []T, less LessFn[T]) bool {\n\tparent := 0\n\tfor child := 1; child < len(array); child++ {\n\t\tif !less(array[parent], array[child]) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (child & 1) == 0 {\n\t\t\tparent++\n\t\t}\n\n\t}\n\treturn true\n}\n\n// PushHeapFunc pushes a element v into the heap.\n//\n// Complexity: O(log(len(*heap))).\nfunc PushHeapFunc[T any](heap *[]T, v T, less LessFn[T]) {\n\t*heap = append(*heap, v)\n\theapUpFunc(*heap, len(*heap)-1, less)\n}\n\n// PopHeapFunc removes and returns the minimum (according to less) element from the heap.\n//\n// Complexity: O(log n) where n = len(*heap).\nfunc PopHeapFunc[T any](heap *[]T, less LessFn[T]) T {\n\th := *heap\n\tn := len(h) - 1\n\theapSwap(h, 0, n)\n\theapDownFunc(h, 0, n, less)\n\t*heap = h[0:n]\n\treturn h[n]\n}\n\n// RemoveHeapFunc removes and returns the element at index i from the heap.\n//\n// Complexity: is O(log(n)) where n = len(*heap).\nfunc RemoveHeapFunc[T any](heap *[]T, i int, less LessFn[T]) T {\n\th := *heap\n\tn := len(h) - 1\n\tif n != i {\n\t\theapSwap(h, i, n)\n\t\tif !heapDownFunc(h, i, n, less) {\n\t\t\theapUpFunc(h, i, less)\n\t\t}\n\t}\n\t*heap = h[0:n]\n\treturn h[n]\n}\n\nfunc heapUpFunc[T any](heap []T, j int, less LessFn[T]) {\n\tfor {\n\t\ti := (j - 1) / 2 // parent\n\t\tif i == j || !less(heap[j], heap[i]) {\n\t\t\tbreak\n\t\t}\n\t\theapSwap(heap, i, j)\n\t\tj = i\n\t}\n}\n\nfunc heapDownFunc[T any](heap []T, i0, n int, less LessFn[T]) bool {\n\ti := i0\n\tfor {\n\t\tj1 := 2*i + 1\n\t\tif j1 >= n || j1 < 0 { // j1 < 0 after int overflow\n\t\t\tbreak\n\t\t}\n\t\tj := j1 // left child\n\t\tif j2 := j1 + 1; j2 < n && less(heap[j2], heap[j1]) {\n\t\t\tj = j2 // = 2*i + 2  // right child\n\t\t}\n\t\tif !less(heap[j], heap[i]) {\n\t\t\tbreak\n\t\t}\n\t\theapSwap(heap, i, j)\n\t\ti = j\n\t}\n\treturn i > i0\n}\n"
  },
  {
    "path": "heap.md",
    "content": "# Heap\n\nstl4go provides a group of [heap](https://en.wikipedia.org/wiki/Heap_(data_structure)) algorithms.\n\n## Easy to use\n\nFor ordered types, you can easily use the heap algorithms, for example, with `int` type:\n\n```go\nfunc Example() {\n    heap := []int {5, 4, 3, 2, 1}\n    stl4go.MakeMinHeap(heap)\n    stl4go.PushMinHeap(&heap, 6)\n    n := stl4go.PopMinHeap(&heap) // get 1\n}\n```\n\nPlease compare it with [container/heap](https://pkg.go.dev/container/heap#example-package-IntHeap):\n\n```go\n// This example demonstrates an integer heap built using the heap interface.\npackage main\n\nimport (\n\t\"container/heap\"\n\t\"fmt\"\n)\n\n// An IntHeap is a min-heap of ints.\ntype IntHeap []int\n\nfunc (h IntHeap) Len() int           { return len(h) }\nfunc (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }\nfunc (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }\n\nfunc (h *IntHeap) Push(x any) {\n\t// Push and Pop use pointer receivers because they modify the slice's length,\n\t// not just its contents.\n\t*h = append(*h, x.(int))\n}\n\nfunc (h *IntHeap) Pop() any {\n\told := *h\n\tn := len(old)\n\tx := old[n-1]\n\t*h = old[0 : n-1]\n\treturn x\n}\n\n// This example inserts several ints into an IntHeap, checks the minimum,\n// and removes them in order of priority.\nfunc main() {\n\th := &IntHeap{2, 1, 5}\n\theap.Init(h)\n\theap.Push(h, 3)\n\tfmt.Printf(\"minimum: %d\\n\", (*h)[0])\n\tfor h.Len() > 0 {\n\t\tfmt.Printf(\"%d \", heap.Pop(h))\n\t}\n}\n```\n\nYou must define a new type `IntHeap` and five methods before to use the standard library,\nthese boilerplate codes are verbose, tedious, and boring.\n\n## Benchmark\n\nThe heap algorithms are also much faster than `container/heap`, even for the `Func` version.:\n\n```console\n% go test -bench BenchmarkHeap -benchmem\ngoos: darwin\ngoarch: arm64\npkg: github.com/chen3feng/stl4go\nBenchmarkHeapInit/container/heap.Init-10                  360126              3195 ns/op               0 B/op          0 allocs/op\nBenchmarkHeapInit/stlgo.MakeMinHeap-10                    998325              1127 ns/op               0 B/op          0 allocs/op\nBenchmarkHeapInit/stlgo.MakeHeapFunc-10                   488419              2355 ns/op               0 B/op          0 allocs/op\n...\nBenchmarkHeapPush/container/heap.Push-10                  101260             11630 ns/op            5952 B/op        744 allocs/op\nBenchmarkHeapPush/stlgo.PushMinHeap-10                    511680              2261 ns/op               0 B/op          0 allocs/op\nBenchmarkHeapPush/stlgo.PushHeapFunc-10                   445850              2625 ns/op               0 B/op          0 allocs/op\n...\nBenchmarkHeapPop/container/heap.Pop-10                     14709             81153 ns/op            5952 B/op        744 allocs/op\nBenchmarkHeapPop/stlgo.PopMinHeap-10                       61608             19516 ns/op               0 B/op          0 allocs/op\nBenchmarkHeapPop/stlgo.PopHeapFunc-10                      22887             52440 ns/op               0 B/op          0 allocs/op\nPASS\nok      github.com/chen3feng/stl4go     19.827s\n```\n"
  },
  {
    "path": "heap_bench_test.go",
    "content": "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 (h intHeap) Len() int           { return len(h) }\nfunc (h intHeap) Less(i, j int) bool { return h[i] < h[j] }\nfunc (h intHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }\nfunc (h *intHeap) Push(x any)        { *h = append(*h, x.(int)) }\n\nfunc (h *intHeap) Pop() any {\n\told := *h\n\tn := len(old)\n\tx := old[n-1]\n\t*h = old[0 : n-1]\n\treturn x\n}\n\nfunc BenchmarkHeapInit(b *testing.B) {\n\tdata := Range(1, 1000)\n\tShuffle(data)\n\tb.Run(\"container/heap.Init\", func(b *testing.B) {\n\t\tdata = Copy(data)\n\t\th := intHeap(data)\n\t\tb.ResetTimer()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\theap.Init(&h)\n\t\t}\n\t})\n\tb.Run(\"stlgo.MakeMinHeap\", func(b *testing.B) {\n\t\tdata = Copy(data)\n\t\tb.ResetTimer()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tMakeMinHeap(data)\n\t\t}\n\t})\n\tb.Run(\"stlgo.MakeHeapFunc\", func(b *testing.B) {\n\t\tdata = Copy(data)\n\t\tb.ResetTimer()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tMakeHeapFunc(data, Less[int])\n\t\t}\n\t})\n}\n\nfunc BenchmarkHeapPush(b *testing.B) {\n\tconst count = 1000\n\tb.Run(\"container/heap.Push\", func(b *testing.B) {\n\t\th := intHeap([]int{})\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\th = h[0:0]\n\t\t\tfor n := 0; n < count; n++ {\n\t\t\t\theap.Push(&h, n)\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"stlgo.PushMinHeap\", func(b *testing.B) {\n\t\th := []int{}\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\th = h[0:0]\n\t\t\tfor n := 0; n < count; n++ {\n\t\t\t\tPushMinHeap(&h, n)\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"stlgo.PushHeapFunc\", func(b *testing.B) {\n\t\th := []int{}\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\th = h[0:0]\n\t\t\tfor n := 0; n < count; n++ {\n\t\t\t\tPushHeapFunc(&h, n, Less[int])\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc BenchmarkHeapPop(b *testing.B) {\n\ts := Range(1, 1000)\n\tb.Run(\"container/heap.Pop\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tb.StopTimer()\n\t\t\th := intHeap(Copy(s))\n\t\t\theap.Init(&h)\n\t\t\tb.StartTimer()\n\t\t\tfor len(h) > 0 {\n\t\t\t\t_ = heap.Pop(&h).(int)\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"stlgo.PopMinHeap\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tb.StopTimer()\n\t\t\th := Copy(s)\n\t\t\tMakeMinHeap(h)\n\t\t\tb.StartTimer()\n\t\t\tfor len(h) > 0 {\n\t\t\t\t_ = PopMinHeap(&h)\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"stlgo.PopHeapFunc\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tb.StopTimer()\n\t\t\th := Copy(s)\n\t\t\tMakeMinHeap(h)\n\t\t\tb.StartTimer()\n\t\t\tfor len(h) > 0 {\n\t\t\t\t_ = PopHeapFunc(&h, Less[int])\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "heap_test.go",
    "content": "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, IsMinHeap(data))\n\tMakeMinHeap(data)\n\texpectTrue(t, IsMinHeap(data))\n}\n\nfunc TestIsMinHeap(t *testing.T) {\n\theap := []int{}\n\texpectTrue(t, IsMinHeap(heap))\n\theap = append(heap, 1)\n\texpectTrue(t, IsMinHeap(heap))\n}\n\nfunc TestMakeHeapFunc(t *testing.T) {\n\tdata := []int{1, 2, 3, 4, 5}\n\texpectFalse(t, IsHeapFunc(data, Greater[int]))\n\tMakeHeapFunc(data, Greater[int])\n\texpectTrue(t, IsHeapFunc(data, Greater[int]))\n}\n\nfunc Test_MinHeap_PushPop(t *testing.T) {\n\theap := []int{}\n\tPushMinHeap(&heap, 1)\n\texpectEq(t, PopMinHeap(&heap), 1)\n\texpectTrue(t, IsMinHeap(heap))\n}\n\nfunc Test_HeapFunc_PushPop(t *testing.T) {\n\theap := []int{}\n\tcmp := Greater[int]\n\tPushHeapFunc(&heap, 1, cmp)\n\texpectTrue(t, IsHeapFunc(heap, cmp))\n\texpectEq(t, PopHeapFunc(&heap, cmp), 1)\n\texpectTrue(t, IsHeapFunc(heap, cmp))\n}\n\nfunc Test_MinHeap_Remove(t *testing.T) {\n\theap := []int{5, 4, 3, 2, 1}\n\tMakeMinHeap(heap)\n\tRemoveMinHeap(&heap, 1)\n\texpectTrue(t, IsMinHeap(heap))\n}\n\nfunc Test_HeapFunc_Remove(t *testing.T) {\n\theap := []int{1, 2, 3, 4, 5}\n\tcmp := Greater[int]\n\tMakeHeapFunc(heap, cmp)\n\tRemoveHeapFunc(&heap, 1, cmp)\n\texpectTrue(t, IsHeapFunc(heap, cmp))\n}\n"
  },
  {
    "path": "helper.go",
    "content": "package stl4go\n\nimport (\n\t\"reflect\"\n)\n\n// nameOfType return type name as a string.\nfunc nameOfType[T any]() string {\n\tvar t *T\n\treturn reflect.TypeOf(t).String()[1:]\n}\n"
  },
  {
    "path": "iterator.go",
    "content": "package stl4go\n\n// Iterator is the interface for container's iterator.\ntype Iterator[T any] interface {\n\tIsNotEnd() bool // Whether it is point to the end of the range.\n\tMoveToNext()    // Let it point to the next element.\n\tValue() T       // Return the value of current element.\n}\n\n// MutableIterator is the interface for container's mutable iterator.\ntype MutableIterator[T any] interface {\n\tIterator[T]\n\tPointer() *T // Return the pointer to the value of current element.\n}\n\n// MapIterator is the interface for map's iterator.\ntype MapIterator[K any, V any] interface {\n\tIterator[V]\n\tKey() K // The key of the element\n}\n\n// MutableMapIterator is the interface for map's mutable iterator.\ntype MutableMapIterator[K any, V any] interface {\n\tMutableIterator[V]\n\tKey() K // The key of the element\n}\n"
  },
  {
    "path": "lookup.go",
    "content": "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) T {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n\n// Min return the smaller value between `a` and `b`.\n//\n// Complexity: O(1).\nfunc Min[T Ordered](a, b T) T {\n\tif a < b {\n\t\treturn a\n\t}\n\treturn b\n}\n\n// MaxN return the maximum value in the sequence `a`.\n//\n// Complexity: O(len(a)).\nfunc MaxN[T Ordered](a ...T) T {\n\tif len(a) == 0 {\n\t\tpanic(\"can't call MaxN() with empty arguments list\")\n\t}\n\tv := a[0]\n\tfor i := 1; i < len(a); i++ {\n\t\tif a[i] > v {\n\t\t\tv = a[i]\n\t\t}\n\t}\n\treturn v\n}\n\n// MinN return the minimum value in the sequence `a`.\n//\n// Complexity: O(len(a)).\nfunc MinN[T Ordered](a ...T) T {\n\tif len(a) == 0 {\n\t\tpanic(\"can't call MaxN() with empty arguments list\")\n\t}\n\tv := a[0]\n\tfor i := 1; i < len(a); i++ {\n\t\tif a[i] < v {\n\t\t\tv = a[i]\n\t\t}\n\t}\n\treturn v\n}\n\n// MinMax returns both min and max between a and b.\n//\n// Complexity: O(1).\nfunc MinMax[T Ordered](a, b T) (min, max T) {\n\tif a < b {\n\t\treturn a, b\n\t}\n\treturn b, a\n}\n\n// MinMaxN returns both min and max in slice a.\n//\n// Complexity: O(len(a))\nfunc MinMaxN[T Ordered](a ...T) (min, max T) {\n\tif len(a) == 0 {\n\t\tpanic(\"can't call MaxN() with empty arguments list\")\n\t}\n\tmin = a[0]\n\tmax = a[0]\n\tfor i := 1; i < len(a); i++ {\n\t\tif a[i] < min {\n\t\t\tmin = a[i]\n\t\t}\n\t\tif a[i] > max {\n\t\t\tmax = a[i]\n\t\t}\n\t}\n\treturn\n}\n\n// Find find the first value x in the given slice a linearly.\n// return (index, true) if found,\n// return (_, false) if not found.\n//\n// Complexity: O(len(a)).\nfunc Find[T comparable](a []T, x T) (index int, ok bool) {\n\tfor i, v := range a {\n\t\tif v == x {\n\t\t\treturn i, true\n\t\t}\n\t}\n\treturn -1, false\n}\n\n// FindIf find the first value x satisfying function cond in the given slice a linearly.\n// return (index, true) if found,\n// return (_, false) if not found.\n//\n// Complexity: O(len(a)).\nfunc FindIf[T any](a []T, cond func(T) bool) (index int, ok bool) {\n\tfor i, v := range a {\n\t\tif cond(v) {\n\t\t\treturn i, true\n\t\t}\n\t}\n\treturn -1, false\n}\n\n// Index find the value x in the given slice a linearly.\n//\n// Return index if found, -1 if not found.\n//\n// Complexity: O(len(a)).\nfunc Index[T comparable](a []T, x T) int {\n\tfor i, v := range a {\n\t\tif v == x {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// AllOf return true if pred(e) returns true for all elements e in a.\n//\n// Complexity: O(len(a)).\nfunc AllOf[T any](a []T, pred func(T) bool) bool {\n\tfor _, v := range a {\n\t\tif !pred(v) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// AnyOf return true if pred(e) returns true for any elements e in a.\n//\n// Complexity: O(len(a)).\nfunc AnyOf[T any](a []T, pred func(T) bool) bool {\n\tfor _, v := range a {\n\t\tif pred(v) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// NoneOf return true pred(e) returns true for none elements e in a.\n//\n// Complexity: O(len(a)).\nfunc NoneOf[T any](a []T, pred func(T) bool) bool {\n\treturn !AnyOf(a, pred)\n}\n"
  },
  {
    "path": "lookup_test.go",
    "content": "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\texpectEq(t, Min(1, 1), 1)\n\texpectEq(t, Min(\"hello\", \"world\"), \"hello\")\n}\n\nfunc Test_Max(t *testing.T) {\n\texpectEq(t, Max(1, 2), 2)\n\texpectEq(t, Max(2, 1), 2)\n\texpectEq(t, Max(2, 2), 2)\n\texpectEq(t, Max(\"hello\", \"world\"), \"world\")\n}\n\nfunc Test_MinN(t *testing.T) {\n\texpectEq(t, MinN(1, 2, 3), 1)\n\texpectEq(t, MinN(2, 1, 3), 1)\n\texpectEq(t, MinN(1, 1, 1), 1)\n\texpectEq(t, MinN(\"hello\", \"world\"), \"hello\")\n\texpectPanic(t, func() { MinN(emptyInts...) })\n}\n\nfunc Test_MaxN(t *testing.T) {\n\texpectEq(t, MaxN(1, 2), 2)\n\texpectEq(t, MaxN(2, 1), 2)\n\texpectEq(t, MaxN(2, 2), 2)\n\texpectEq(t, MaxN(\"hello\", \"world\"), \"world\")\n\texpectPanic(t, func() { MaxN(emptyInts...) })\n}\n\nfunc Test_MinMax(t *testing.T) {\n\tmin, max := MinMax(1, 2)\n\texpectEq(t, min, 1)\n\texpectEq(t, max, 2)\n\tmin, max = MinMax(2, 1)\n\texpectEq(t, min, 1)\n\texpectEq(t, max, 2)\n}\n\nfunc Test_MinMaxN(t *testing.T) {\n\tmin, max := MinMaxN(3, 4, 1, 2)\n\texpectEq(t, min, 1)\n\texpectEq(t, max, 4)\n\texpectPanic(t, func() { MinMaxN(emptyInts...) })\n}\n\nfunc Test_Find(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 3}\n\ti, ok := Find(a, 3)\n\texpectTrue(t, ok)\n\texpectEq(t, i, 2)\n\ti, ok = Find(a, 5)\n\texpectFalse(t, ok)\n}\n\nfunc Test_FindIf(t *testing.T) {\n\tisNeg := func(x int) bool { return x < 0 }\n\ta := []int{1, 2, -3, 4, 3}\n\ti, ok := FindIf(a, isNeg)\n\texpectTrue(t, ok)\n\texpectEq(t, i, 2)\n\ti, ok = FindIf([]int{1, 2, 3, 4, 3}, isNeg)\n\texpectFalse(t, ok)\n}\n\nfunc Test_Index(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 3}\n\texpectEq(t, Index(a, 3), 2)\n\texpectEq(t, Index(a, 5), -1)\n}\n\nvar (\n\tpos = []int{1, 2, 3, 4, 5}\n\tneg = []int{-1, -2, -3, -4, -5}\n\tmix = []int{1, -2, 3, -4, 5}\n)\n\nfunc isNegative(n int) bool { return n < 0 }\n\nfunc Test_AllOf(t *testing.T) {\n\texpectFalse(t, AllOf(pos, isNegative))\n\texpectTrue(t, AllOf(neg, isNegative))\n\texpectFalse(t, AllOf(mix, isNegative))\n}\n\nfunc Test_AnyOf(t *testing.T) {\n\texpectFalse(t, AnyOf(pos, isNegative))\n\texpectTrue(t, AnyOf(neg, isNegative))\n\texpectTrue(t, AnyOf(mix, isNegative))\n}\n\nfunc Test_NoneOf(t *testing.T) {\n\texpectTrue(t, NoneOf(pos, isNegative))\n\texpectFalse(t, NoneOf(neg, isNegative))\n\texpectFalse(t, NoneOf(mix, isNegative))\n}\n"
  },
  {
    "path": "mlc_config.json",
    "content": "{\n    \"aliveStatusCodes\": [\n        400,\n        429,\n        200\n    ]\n}\n"
  },
  {
    "path": "pool.go",
    "content": "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 object\nfunc MakePool[T any]() Pool[T] {\n\treturn Pool[T]{New: func() any { return new(T) }}\n}\n\n// MakePoolWithNew returns a Pool object with specified new function.\nfunc MakePoolWithNew[T any](new func() *T) Pool[T] {\n\tif new != nil {\n\t\treturn Pool[T]{New: func() any { return new() }}\n\t}\n\treturn Pool[T]{}\n}\n\n// Get selects an arbitrary item from the Pool, removes it from the Pool, and returns it to the caller.\nfunc (pool *Pool[T]) Get() *T {\n\ti := pool.untyped().Get()\n\tif i == nil {\n\t\treturn nil\n\t}\n\treturn i.(*T)\n}\n\n// Put puts x to the pool.\nfunc (pool *Pool[T]) Put(x *T) {\n\tif x != nil {\n\t\tpool.untyped().Put(x)\n\t}\n}\n\nfunc (pool *Pool[T]) untyped() *sync.Pool {\n\treturn (*sync.Pool)(pool)\n}\n"
  },
  {
    "path": "pool_test.go",
    "content": "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 TestMakePoolWithNew(t *testing.T) {\n\tp := MakePoolWithNew(func() *int { return new(int) })\n\tx := p.Get()\n\tp.Put(x)\n}\n\nfunc TestMakePoolNil(t *testing.T) {\n\tp := MakePoolWithNew[int](nil)\n\tx := p.Get()\n\texpectEq(t, x, nil)\n\tp.Put(x)\n}\n"
  },
  {
    "path": "priority_queue.go",
    "content": "package stl4go\n\n// PriorityQueue is an queue with priority.\n// The elements of the priority queue are ordered according to their natural ordering,\n// or by a less function provided at construction time, depending on which constructor is used.\ntype PriorityQueue[T any] struct {\n\theap []T\n\timpl pqImpl[T]\n}\n\n// NewPriorityQueue creates an empty priority object.\nfunc NewPriorityQueue[T Ordered]() *PriorityQueue[T] {\n\tpq := pqOrdered[T]{}\n\tpq.impl = (pqImpl[T])(&pq)\n\treturn &pq.PriorityQueue\n}\n\n// NewPriorityQueueOn creates a new priority object on the specified slices.\n// The slice become a heap after the call.\nfunc NewPriorityQueueOn[T Ordered](slice []T) *PriorityQueue[T] {\n\tMakeMinHeap(slice)\n\tpq := pqOrdered[T]{}\n\tpq.heap = slice\n\tpq.impl = pqImpl[T](&pq)\n\treturn &pq.PriorityQueue\n}\n\n// NewPriorityQueueOf creates a new priority object with specified initial elements.\nfunc NewPriorityQueueOf[T Ordered](elements ...T) *PriorityQueue[T] {\n\treturn NewPriorityQueueOn(elements)\n}\n\n// NewPriorityQueueFunc creates an empty priority object with specified compare function less.\nfunc NewPriorityQueueFunc[T any](less LessFn[T]) *PriorityQueue[T] {\n\tpq := pqFunc[T]{}\n\tpq.less = less\n\tpq.impl = (pqImpl[T])(&pq)\n\treturn &pq.PriorityQueue\n}\n\n// Len returns the number of elements in the priority queue.\nfunc (pq *PriorityQueue[T]) Len() int {\n\treturn len(pq.heap)\n}\n\n// IsEmpty checks whether priority queue has no elements.\nfunc (pq *PriorityQueue[T]) IsEmpty() bool {\n\treturn len(pq.heap) == 0\n}\n\n// Clear clear the priority queue.\nfunc (pq *PriorityQueue[T]) Clear() {\n\tpq.heap = pq.heap[0:0]\n}\n\n// Top returns the top element in the priority queue.\nfunc (pq *PriorityQueue[T]) Top() T {\n\treturn pq.heap[0]\n}\n\n// Push pushes the given element v to the priority queue.\nfunc (pq *PriorityQueue[T]) Push(v T) {\n\tpq.impl.Push(v)\n}\n\n// Pop removes the top element in the priority queue.\nfunc (pq *PriorityQueue[T]) Pop() T {\n\treturn pq.impl.Pop()\n}\n\ntype pqImpl[T any] interface {\n\tPush(v T)\n\tPop() T\n}\n\ntype pqOrdered[T Ordered] struct {\n\tPriorityQueue[T]\n}\n\nfunc (pq *pqOrdered[T]) Push(v T) {\n\tPushMinHeap(&pq.heap, v)\n}\n\nfunc (pq *pqOrdered[T]) Pop() T {\n\treturn PopMinHeap(&pq.heap)\n}\n\n// funcHeap is a min-heap of T compared with less.\ntype pqFunc[T any] struct {\n\tPriorityQueue[T]\n\tless LessFn[T]\n}\n\nfunc (pq *pqFunc[T]) Push(v T) {\n\tPushHeapFunc(&pq.heap, v, pq.less)\n}\n\nfunc (pq *pqFunc[T]) Pop() T {\n\treturn PopHeapFunc(&pq.heap, pq.less)\n}\n"
  },
  {
    "path": "priority_queue_test.go",
    "content": "package stl4go\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestInterface(t *testing.T) {\n\t_ = (Container)(NewPriorityQueue[int]())\n}\n\nfunc TestNewPriorityQueue(t *testing.T) {\n\tpq := NewPriorityQueue[int]()\n\texpectTrue(t, pq.IsEmpty())\n\texpectEq(t, pq.Len(), 0)\n}\n\nfunc TestNewPriorityQueueOf(t *testing.T) {\n\tpq := NewPriorityQueueOf(5, 4, 3, 2, 1)\n\texpectEq(t, pq.Len(), 5)\n}\n\nfunc TestPriorityQueue_PushPop(t *testing.T) {\n\tless := Less[int]\n\tpq := NewPriorityQueueFunc(less)\n\tfor i := 5; i > 0; i-- {\n\t\tpq.Push(i)\n\t\texpectFalse(t, pq.IsEmpty())\n\t}\n\tvar elements []int\n\tfor !pq.IsEmpty() {\n\t\telements = append(elements, pq.Pop())\n\t}\n\texpectTrue(t, pq.IsEmpty())\n\texpectTrue(t, IsSorted(elements))\n\texpectEq(t, len(elements), 5)\n}\n\nfunc TestPriorityQueueFunc_PushPop(t *testing.T) {\n\tpq := NewPriorityQueueFunc(Less[int])\n\tfor i := 5; i > 0; i-- {\n\t\tpq.Push(i)\n\t}\n\tvar elements []int\n\tfor !pq.IsEmpty() {\n\t\telements = append(elements, pq.Pop())\n\t}\n\texpectTrue(t, pq.IsEmpty())\n\texpectTrue(t, IsSorted(elements))\n\texpectEq(t, len(elements), 5)\n}\n\nfunc TestPriorityQueue_Clear(t *testing.T) {\n\tpq := NewPriorityQueue[int]()\n\tpq.Clear()\n\texpectTrue(t, pq.IsEmpty())\n\texpectEq(t, pq.Len(), 0)\n\tpq = NewPriorityQueueOf(1, 2, 3)\n\tpq.Clear()\n\texpectTrue(t, pq.IsEmpty())\n\texpectEq(t, pq.Len(), 0)\n}\n\n// This example inserts several ints into an IntHeap, checks the minimum,\n// and removes them in order of priority.\nfunc ExamplePriorityQueue() {\n\th := NewPriorityQueue[int]()\n\th.Push(3)\n\th.Push(2)\n\th.Push(1)\n\th.Push(5)\n\tfmt.Printf(\"minimum: %d\\n\", h.Top())\n\n\tfor h.Len() > 0 {\n\t\tfmt.Printf(\"%d \", h.Pop())\n\t}\n\t// Output:\n\t// minimum: 1\n\t// 1 2 3 5\n}\n"
  },
  {
    "path": "skiplist.go",
    "content": "// This implementation is based on https://github.com/liyue201/gostl/tree/master/ds/skiplist\n// (many thanks), added many optimizations, such as:\n//\n//  - adaptive level\n//  - lesser search for prevs when key already exists.\n//  - reduce memory allocations\n//  - richer interface.\n//\n// etc.\n\npackage stl4go\n\nimport (\n\t\"math/bits\"\n\t\"math/rand\"\n\t\"time\"\n)\n\nconst (\n\tskipListMaxLevel = 40\n)\n\n// SkipList is a probabilistic data structure that seem likely to supplant balanced trees as the\n// implementation method of choice for many applications. Skip list algorithms have the same\n// asymptotic expected time bounds as balanced trees and are simpler, faster and use less space.\n//\n// See https://en.wikipedia.org/wiki/Skip_list for more details.\ntype SkipList[K any, V any] struct {\n\tlevel int                // Current level, may increase dynamically during insertion\n\tlen   int                // Total elements number in the skiplist.\n\thead  skipListNode[K, V] // head.next[level] is the head of each level.\n\t// This cache is used to save the previous nodes when modifying the skip list to avoid\n\t// allocating memory each time it is called.\n\tprevsCache []*skipListNode[K, V]\n\trander     *rand.Rand\n\timpl       skipListImpl[K, V]\n}\n\n// NewSkipList creates a new SkipList for Ordered key type.\nfunc NewSkipList[K Ordered, V any]() *SkipList[K, V] {\n\tsl := skipListOrdered[K, V]{}\n\tsl.init()\n\tsl.impl = (skipListImpl[K, V])(&sl)\n\treturn &sl.SkipList\n}\n\n// NewSkipListFromMap creates a new SkipList from a map.\nfunc NewSkipListFromMap[K Ordered, V any](m map[K]V) *SkipList[K, V] {\n\tsl := NewSkipList[K, V]()\n\tfor k, v := range m {\n\t\tsl.Insert(k, v)\n\t}\n\treturn sl\n}\n\n// NewSkipListFunc creates a new SkipList with specified compare function keyCmp.\nfunc NewSkipListFunc[K any, V any](keyCmp CompareFn[K]) *SkipList[K, V] {\n\tsl := skipListFunc[K, V]{}\n\tsl.init()\n\tsl.keyCmp = keyCmp\n\tsl.impl = skipListImpl[K, V](&sl)\n\treturn &sl.SkipList\n}\n\n// IsEmpty implements the Container interface.\nfunc (sl *SkipList[K, V]) IsEmpty() bool {\n\treturn sl.len == 0\n}\n\n// Len implements the Container interface.\nfunc (sl *SkipList[K, V]) Len() int {\n\treturn sl.len\n}\n\n// Clear implements the Container interface.\nfunc (sl *SkipList[K, V]) Clear() {\n\tfor i := range sl.head.next {\n\t\tsl.head.next[i] = nil\n\t}\n\tsl.level = 1\n\tsl.len = 0\n}\n\n// Iterate return an iterator to the skiplist.\nfunc (sl *SkipList[K, V]) Iterate() MutableMapIterator[K, V] {\n\treturn &skipListIterator[K, V]{sl.head.next[0], nil}\n}\n\n// Insert inserts a key-value pair into the skiplist.\n// If the key is already in the skip list, it's value will be updated.\nfunc (sl *SkipList[K, V]) Insert(key K, value V) {\n\tnode, prevs := sl.impl.findInsertPoint(key)\n\n\tif node != nil {\n\t\t// Already exist, update the value\n\t\tnode.value = value\n\t\treturn\n\t}\n\n\tlevel := sl.randomLevel()\n\tnode = newSkipListNode(level, key, value)\n\n\t// Insert node to each level\n\tfor i := 0; i < Min(level, sl.level); i++ {\n\t\tnode.next[i] = prevs[i].next[i]\n\t\tprevs[i].next[i] = node\n\t}\n\n\tif level > sl.level {\n\t\t// Increase the level\n\t\tfor i := sl.level; i < level; i++ {\n\t\t\tsl.head.next[i] = node\n\t\t}\n\t\tsl.level = level\n\t}\n\n\tsl.len++\n}\n\n// Find returns the value associated with the passed key if the key is in the skiplist, otherwise\n// returns nil.\nfunc (sl *SkipList[K, V]) Find(key K) *V {\n\tnode := sl.impl.findNode(key)\n\tif node != nil {\n\t\treturn &node.value\n\t}\n\treturn nil\n}\n\n// Has implement the Map interface.\nfunc (sl *SkipList[K, V]) Has(key K) bool {\n\treturn sl.impl.findNode(key) != nil\n}\n\n// LowerBound returns an iterator to the first element in the skiplist that\n// does not satisfy element < value (i.e. greater or equal to),\n// or a end iterator if no such element is found.\nfunc (sl *SkipList[K, V]) LowerBound(key K) MutableMapIterator[K, V] {\n\treturn &skipListIterator[K, V]{sl.impl.lowerBound(key), nil}\n}\n\n// UpperBound returns an iterator to the first element in the skiplist that\n// does not satisfy value < element (i.e. strictly greater),\n// or a end iterator if no such element is found.\nfunc (sl *SkipList[K, V]) UpperBound(key K) MutableMapIterator[K, V] {\n\treturn &skipListIterator[K, V]{sl.impl.upperBound(key), nil}\n}\n\n// FindRange returns an iterator in range [first, last) (last is not included).\nfunc (sl *SkipList[K, V]) FindRange(first, last K) MutableMapIterator[K, V] {\n\treturn &skipListIterator[K, V]{sl.impl.lowerBound(first), sl.impl.upperBound(last)}\n}\n\n// Remove removes the key-value pair associated with the passed key and returns true if the key is\n// in the skiplist, otherwise returns false.\nfunc (sl *SkipList[K, V]) Remove(key K) bool {\n\tnode, prevs := sl.impl.findRemovePoint(key)\n\tif node == nil {\n\t\treturn false\n\t}\n\tfor i, v := range node.next { // Nomove the node from each level's links.\n\t\tprevs[i].next[i] = v\n\t}\n\t// Decrease the level if the top level become empty\n\tfor sl.level > 1 && sl.head.next[sl.level-1] == nil {\n\t\tsl.level--\n\t}\n\tsl.len--\n\treturn true\n}\n\n// ForEach implements the Map interface.\nfunc (sl *SkipList[K, V]) ForEach(op func(K, V)) {\n\tfor e := sl.head.next[0]; e != nil; e = e.next[0] {\n\t\top(e.key, e.value)\n\t}\n}\n\n// ForEachMutable implements the Map interface.\nfunc (sl *SkipList[K, V]) ForEachMutable(op func(K, *V)) {\n\tfor e := sl.head.next[0]; e != nil; e = e.next[0] {\n\t\top(e.key, &e.value)\n\t}\n}\n\n// ForEachIf implements the Map interface.\nfunc (sl *SkipList[K, V]) ForEachIf(op func(K, V) bool) {\n\tfor e := sl.head.next[0]; e != nil; e = e.next[0] {\n\t\tif !op(e.key, e.value) {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// ForEachMutableIf implements the Map interface.\nfunc (sl *SkipList[K, V]) ForEachMutableIf(op func(K, *V) bool) {\n\tfor e := sl.head.next[0]; e != nil; e = e.next[0] {\n\t\tif !op(e.key, &e.value) {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n/// SkipList implementation part.\n\ntype skipListNode[K any, V any] struct {\n\tkey   K\n\tvalue V\n\tnext  []*skipListNode[K, V]\n}\n\n//go:generate bash ./skiplist_newnode_generate.sh skipListMaxLevel skiplist_newnode.go\n// func newSkipListNode[K Ordered, V any](level int, key K, value V) *skipListNode[K, V]\n\ntype skipListIterator[K any, V any] struct {\n\tnode, end *skipListNode[K, V]\n}\n\nfunc (it *skipListIterator[K, V]) IsNotEnd() bool {\n\treturn it.node != it.end\n}\n\nfunc (it *skipListIterator[K, V]) MoveToNext() {\n\tit.node = it.node.next[0]\n}\n\nfunc (it *skipListIterator[K, V]) Key() K {\n\treturn it.node.key\n}\n\nfunc (it *skipListIterator[K, V]) Value() V {\n\treturn it.node.value\n}\n\nfunc (it *skipListIterator[K, V]) Pointer() *V {\n\treturn &it.node.value\n}\n\n// skipListImpl is an interface to provide different implementation for Ordered key or CompareFn.\n//\n// We can use CompareFn to compare Ordered keys, but a separated implementation is much faster.\n// We don't make the whole skip list an interface, in order to share the type independented method.\n// And because these methods are called directly without going through the interface, they are also\n// much faster.\ntype skipListImpl[K any, V any] interface {\n\tfindNode(key K) *skipListNode[K, V]\n\tlowerBound(key K) *skipListNode[K, V]\n\tupperBound(key K) *skipListNode[K, V]\n\tfindInsertPoint(key K) (*skipListNode[K, V], []*skipListNode[K, V])\n\tfindRemovePoint(key K) (*skipListNode[K, V], []*skipListNode[K, V])\n}\n\nfunc (sl *SkipList[K, V]) init() {\n\tsl.level = 1\n\t// #nosec G404 -- This is not a security condition\n\tsl.rander = rand.New(rand.NewSource(time.Now().Unix()))\n\tsl.prevsCache = make([]*skipListNode[K, V], skipListMaxLevel)\n\tsl.head.next = make([]*skipListNode[K, V], skipListMaxLevel)\n}\n\nfunc (sl *SkipList[K, V]) randomLevel() int {\n\ttotal := uint64(1)<<uint64(skipListMaxLevel) - 1 // 2^n-1\n\tk := sl.rander.Uint64() & total\n\tlevel := skipListMaxLevel - bits.Len64(k) + 1\n\t// Since levels are randomly generated, most should be less than log2(s.len).\n\t// Then make a limit according to sl.len to avoid unexpectedly large value.\n\tfor level > 3 && 1<<(level-3) > sl.len {\n\t\tlevel--\n\t}\n\tif (level > skipListMaxLevel) {\n\t\tlevel = skipListMaxLevel\n\t}\n\n\treturn level\n}\n\n/// skipListOrdered part\n\n// skipListOrdered is the skip list implementation for Ordered types.\ntype skipListOrdered[K Ordered, V any] struct {\n\tSkipList[K, V]\n}\n\nfunc (sl *skipListOrdered[K, V]) findNode(key K) *skipListNode[K, V] {\n\treturn sl.doFindNode(key, true)\n}\n\nfunc (sl *skipListOrdered[K, V]) doFindNode(key K, eq bool) *skipListNode[K, V] {\n\t// This function execute the job of findNode if eq is true, otherwise lowBound.\n\t// Passing the control variable eq is ugly but it's faster than testing node\n\t// again outside the function in findNode.\n\tprev := &sl.head\n\tfor i := sl.level - 1; i >= 0; i-- {\n\t\tfor cur := prev.next[i]; cur != nil; cur = cur.next[i] {\n\t\t\tif cur.key == key {\n\t\t\t\treturn cur\n\t\t\t}\n\t\t\tif cur.key > key {\n\t\t\t\t// All other node in this level must be greater than the key,\n\t\t\t\t// search the next level.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprev = cur\n\t\t}\n\t}\n\tif eq {\n\t\treturn nil\n\t}\n\treturn prev.next[0]\n}\n\nfunc (sl *skipListOrdered[K, V]) lowerBound(key K) *skipListNode[K, V] {\n\treturn sl.doFindNode(key, false)\n}\n\nfunc (sl *skipListOrdered[K, V]) upperBound(key K) *skipListNode[K, V] {\n\tnode := sl.lowerBound(key)\n\tif node != nil && node.key == key {\n\t\treturn node.next[0]\n\t}\n\treturn node\n}\n\n// findInsertPoint returns (*node, nil) to the existed node if the key exists,\n// or (nil, []*node) to the previous nodes if the key doesn't exist\nfunc (sl *skipListOrdered[K, V]) findInsertPoint(key K) (*skipListNode[K, V], []*skipListNode[K, V]) {\n\tprevs := sl.prevsCache[0:sl.level]\n\tprev := &sl.head\n\tfor i := sl.level - 1; i >= 0; i-- {\n\t\tfor next := prev.next[i]; next != nil; next = next.next[i] {\n\t\t\tif next.key == key {\n\t\t\t\t// The key is already existed, prevs are useless because no new node insertion.\n\t\t\t\t// stop searching.\n\t\t\t\treturn next, nil\n\t\t\t}\n\t\t\tif next.key > key {\n\t\t\t\t// All other node in this level must be greater than the key,\n\t\t\t\t// search the next level.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprev = next\n\t\t}\n\t\tprevs[i] = prev\n\t}\n\treturn nil, prevs\n}\n\n// findRemovePoint finds the node which match the key and it's previous nodes.\nfunc (sl *skipListOrdered[K, V]) findRemovePoint(key K) (*skipListNode[K, V], []*skipListNode[K, V]) {\n\tprevs := sl.findPrevNodes(key)\n\tnode := prevs[0].next[0]\n\tif node == nil || node.key != key {\n\t\treturn nil, nil\n\t}\n\treturn node, prevs\n}\n\nfunc (sl *skipListOrdered[K, V]) findPrevNodes(key K) []*skipListNode[K, V] {\n\tprevs := sl.prevsCache[0:sl.level]\n\tprev := &sl.head\n\tfor i := sl.level - 1; i >= 0; i-- {\n\t\tfor next := prev.next[i]; next != nil; next = next.next[i] {\n\t\t\tif next.key >= key {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprev = next\n\t\t}\n\t\tprevs[i] = prev\n\t}\n\treturn prevs\n}\n\n/// skipListFunc part\n\n// skipListFunc is the skip list implementation which compare keys with func.\ntype skipListFunc[K any, V any] struct {\n\tSkipList[K, V]\n\tkeyCmp CompareFn[K]\n}\n\nfunc (sl *skipListFunc[K, V]) findNode(key K) *skipListNode[K, V] {\n\tnode := sl.lowerBound(key)\n\tif node != nil && sl.keyCmp(node.key, key) == 0 {\n\t\treturn node\n\t}\n\treturn nil\n}\n\nfunc (sl *skipListFunc[K, V]) lowerBound(key K) *skipListNode[K, V] {\n\tvar prev = &sl.head\n\tfor i := sl.level - 1; i >= 0; i-- {\n\t\tcur := prev.next[i]\n\t\tfor ; cur != nil; cur = cur.next[i] {\n\t\t\tcmpRet := sl.keyCmp(cur.key, key)\n\t\t\tif cmpRet == 0 {\n\t\t\t\treturn cur\n\t\t\t}\n\t\t\tif cmpRet > 0 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprev = cur\n\t\t}\n\t}\n\treturn prev.next[0]\n}\n\nfunc (sl *skipListFunc[K, V]) upperBound(key K) *skipListNode[K, V] {\n\tnode := sl.lowerBound(key)\n\tif node != nil && sl.keyCmp(node.key, key) == 0 {\n\t\treturn node.next[0]\n\t}\n\treturn node\n}\n\n// findInsertPoint returns (*node, nil) to the existed node if the key exists,\n// or (nil, []*node) to the previous nodes if the key doesn't exist\nfunc (sl *skipListFunc[K, V]) findInsertPoint(key K) (*skipListNode[K, V], []*skipListNode[K, V]) {\n\tprevs := sl.prevsCache[0:sl.level]\n\tprev := &sl.head\n\tfor i := sl.level - 1; i >= 0; i-- {\n\t\tfor cur := prev.next[i]; cur != nil; cur = cur.next[i] {\n\t\t\tr := sl.keyCmp(cur.key, key)\n\t\t\tif r == 0 {\n\t\t\t\t// The key is already existed, prevs are useless because no new node insertion.\n\t\t\t\t// stop searching.\n\t\t\t\treturn cur, nil\n\t\t\t}\n\t\t\tif r > 0 {\n\t\t\t\t// All other node in this level must be greater than the key,\n\t\t\t\t// search the next level.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprev = cur\n\t\t}\n\t\tprevs[i] = prev\n\t}\n\treturn nil, prevs\n}\n\n// findRemovePoint finds the node which match the key and it's previous nodes.\nfunc (sl *skipListFunc[K, V]) findRemovePoint(key K) (*skipListNode[K, V], []*skipListNode[K, V]) {\n\tprevs := sl.findPrevNodes(key)\n\tnode := prevs[0].next[0]\n\tif node == nil || sl.keyCmp(node.key, key) != 0 {\n\t\treturn nil, nil\n\t}\n\treturn node, prevs\n}\n\nfunc (sl *skipListFunc[K, V]) findPrevNodes(key K) []*skipListNode[K, V] {\n\tprevs := sl.prevsCache[0:sl.level]\n\tprev := &sl.head\n\tfor i := sl.level - 1; i >= 0; i-- {\n\t\tfor next := prev.next[i]; next != nil; next = next.next[i] {\n\t\t\tif sl.keyCmp(next.key, key) >= 0 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprev = next\n\t\t}\n\t\tprevs[i] = prev\n\t}\n\treturn prevs\n}\n"
  },
  {
    "path": "skiplist.md",
    "content": "# SkipList\n\nTODO，See tests.\n"
  },
  {
    "path": "skiplist_bench_test.go",
    "content": "package stl4go\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n)\n\nconst (\n\tbenchInitSize  = 1000000\n\tbenchBatchSize = 10\n)\n\nfunc newMapN(n int) map[int]int {\n\tm := map[int]int{}\n\tfor i := 0; i < n; i++ {\n\t\tm[i] = i\n\t}\n\treturn m\n}\n\nfunc BenchmarkSkipList_Iterate(b *testing.B) {\n\tsl := newSkipListN(100)\n\tb.ResetTimer()\n\tfor n := 0; n < b.N; n++ {\n\t\tfor i := sl.Iterate(); i.IsNotEnd(); i.MoveToNext() {\n\t\t\t_, _ = i.Key(), i.Value()\n\t\t}\n\t}\n}\n\nfunc BenchmarkSkipList_Insert(b *testing.B) {\n\tstart := benchInitSize\n\tsl := newSkipListN(start)\n\tb.ResetTimer()\n\tfor n := 0; n < b.N; n++ {\n\t\tfor i := 0; i < benchBatchSize; i++ {\n\t\t\tsl.Insert(start+i, i)\n\t\t}\n\t\tstart += benchBatchSize\n\t}\n}\n\nfunc BenchmarkMap_Insert(b *testing.B) {\n\tstart := benchInitSize\n\tm := newMapN(start)\n\tb.ResetTimer()\n\tfor n := 0; n < b.N; n++ {\n\t\tfor i := 0; i < benchBatchSize; i++ {\n\t\t\tm[start+i] = i\n\t\t}\n\t\tstart += benchBatchSize\n\t}\n}\n\nfunc BenchmarkSkipList_Insert_Dup(b *testing.B) {\n\tsl := newSkipListN(benchInitSize)\n\tb.ResetTimer()\n\tfor n := 0; n < b.N; n++ {\n\t\tfor i := 0; i < benchBatchSize; i++ {\n\t\t\tsl.Insert(i, i)\n\t\t}\n\t}\n}\n\nfunc BenchmarkMap_Insert_Dup(b *testing.B) {\n\tm := newMapN(benchInitSize)\n\tb.ResetTimer()\n\tfor n := 0; n < b.N; n++ {\n\t\tfor i := 0; i < benchBatchSize; i++ {\n\t\t\tm[i] = i\n\t\t}\n\t}\n}\n\nfunc BenchmarkMap_Find(b *testing.B) {\n\tm := newMapN(benchInitSize)\n\tb.ResetTimer()\n\tfor n := 0; n < b.N; n++ {\n\t\tfor i := 0; i < benchBatchSize; i++ {\n\t\t\t_, _ = m[i]\n\t\t}\n\t}\n}\n\nfunc BenchmarkSkipList_Find(b *testing.B) {\n\tsl := newSkipListN(benchInitSize)\n\tb.ResetTimer()\n\tb.Run(\"Find\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor n := 0; n < benchBatchSize; n++ {\n\t\t\t\t_ = sl.Find(n)\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"LowerBound\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor n := 0; n < benchBatchSize; n++ {\n\t\t\t\t_ = sl.impl.lowerBound(n)\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"FindEnd\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor n := 0; n < benchBatchSize; n++ {\n\t\t\t\t_ = sl.Find(benchInitSize)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc BenchmarkSkipListString(b *testing.B) {\n\tsl := NewSkipList[string, int]()\n\tsl.rander.Seed(0)\n\tvar a []string\n\tfor i := 0; i < benchBatchSize; i++ {\n\t\ta = append(a, strconv.Itoa(benchInitSize+i))\n\t}\n\tend := strconv.Itoa(2 * benchInitSize)\n\tb.ResetTimer()\n\tb.Run(\"Insert\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor n := 0; n < benchBatchSize; n++ {\n\t\t\t\tsl.Insert(a[n], n)\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"Find\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor n := 0; n < benchBatchSize; n++ {\n\t\t\t\tsl.Find(a[n])\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"FindEnd\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor n := 0; n < benchBatchSize; n++ {\n\t\t\t\tsl.Find(end)\n\t\t\t}\n\t\t}\n\t})\n\n\tb.Run(\"RemoveEnd\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor n := 0; n < benchBatchSize; n++ {\n\t\t\t\tsl.Remove(end)\n\t\t\t}\n\t\t}\n\t})\n\tb.Run(\"Remove\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfor n := 0; n < benchBatchSize; n++ {\n\t\t\t\tsl.Remove(a[n])\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "skiplist_newnode.go",
    "content": "// AUTO GENERATED CODE, DO NOT EDIT!!!\n// EDIT skiplist_newnode_generate.sh accordingly.\n\npackage stl4go\n\n// newSkipListNode creates a new node initialized with specified key, value and next slice.\nfunc newSkipListNode[K any, V any](level int, key K, value V) *skipListNode[K, V] {\n\t// For nodes with each levels, point their next slice to the nexts array allocated together,\n\t// which can reduce 1 memory allocation and improve performance.\n\t//\n\t// The generics of the golang doesn't support non-type parameters like in C++,\n\t// so we have to generate it manually.\n\tswitch level {\n\tcase 1:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [1]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 2:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [2]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 3:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [3]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 4:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [4]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 5:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [5]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 6:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [6]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 7:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [7]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 8:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [8]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 9:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [9]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 10:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [10]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 11:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [11]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 12:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [12]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 13:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [13]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 14:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [14]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 15:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [15]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 16:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [16]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 17:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [17]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 18:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [18]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 19:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [19]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 20:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [20]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 21:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [21]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 22:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [22]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 23:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [23]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 24:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [24]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 25:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [25]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 26:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [26]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 27:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [27]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 28:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [28]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 29:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [29]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 30:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [30]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 31:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [31]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 32:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [32]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 33:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [33]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 34:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [34]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 35:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [35]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 36:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [36]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 37:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [37]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 38:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [38]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 39:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [39]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\tcase 40:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [40]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\n\t}\n\n\tpanic(\"should not reach here\")\n}\n"
  },
  {
    "path": "skiplist_newnode_generate.sh",
    "content": "#!/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 chars, they are used to follow the go style guides.\n    echo \"package $GOPACKAGE\"\n    echo \"\n// newSkipListNode creates a new node initialized with specified key, value and next slice.\nfunc newSkipListNode[K any, V any](level int, key K, value V) *skipListNode[K, V] {\n\t// For nodes with each levels, point their next slice to the nexts array allocated together,\n\t// which can reduce 1 memory allocation and improve performance.\n\t//\n\t// The generics of the golang doesn't support non-type parameters like in C++,\n\t// so we have to generate it manually.\n\tswitch level {\"\n\n    for i in $(seq 1 $1); do\n        echo \"\\\n\tcase $i:\n\t\tn := struct {\n\t\t\thead  skipListNode[K, V]\n\t\t\tnexts [$i]*skipListNode[K, V]\n\t\t}{head: skipListNode[K, V]{key, value, nil}}\n\t\tn.head.next = n.nexts[:]\n\t\treturn &n.head\"\n    done\n    echo \"\\\n\t}\n\n\tpanic(\\\"should not reach here\\\")\n}\"\n}\n\nmax_level=$(grep -E \"^\\s*$1\\s*=\\s*\\d+\" $GOFILE | grep -Eo \"\\d+\")\noutput_file=$2\n\necho -e \"// AUTO GENERATED CODE, DO NOT EDIT!!!\\n// EDIT $(basename $0) accordingly.\\n\" > $output_file\ngenerate $max_level >> $output_file\n"
  },
  {
    "path": "skiplist_set.go",
    "content": "package stl4go\n\n// SkipListSet is a SortedSet implemented with skiplist.\ntype SkipListSet[K any] SkipList[K, struct{}]\n\n// NewSkipListSet creates a new SkipListSet object.\nfunc NewSkipListSet[K Ordered]() *SkipListSet[K] {\n\treturn (*SkipListSet[K])(NewSkipList[K, struct{}]())\n}\n\n// NewSkipListSetFunc creates a new SkipListSet object with specified compare function.\nfunc NewSkipListSetFunc[K any](cmp CompareFn[K]) *SkipListSet[K] {\n\treturn (*SkipListSet[K])(NewSkipListFunc[K, struct{}](cmp))\n}\n\n// NewSkipListSetOf creates a new SkipListSet object with specified elements.\nfunc NewSkipListSetOf[K Ordered](elements ...K) *SkipListSet[K] {\n\ts := NewSkipListSet[K]()\n\tfor i := range elements {\n\t\ts.Insert(elements[i])\n\t}\n\treturn s\n}\n\n// IsEmpty implements the SortedSet interface.\nfunc (s *SkipListSet[K]) IsEmpty() bool {\n\treturn s.asMap().IsEmpty()\n}\n\n// Len implements the SortedSet interface.\nfunc (s *SkipListSet[K]) Len() int {\n\treturn s.asMap().Len()\n}\n\n// Clear implements the SortedSet interface.\nfunc (s *SkipListSet[K]) Clear() {\n\ts.asMap().Clear()\n}\n\n// Has implements the SortedSet interface.\nfunc (s *SkipListSet[K]) Has(key K) bool {\n\treturn s.asMap().Has(key)\n}\n\n// Insert implements the SortedSet interface.\nfunc (s *SkipListSet[K]) Insert(key K) bool {\n\toldLen := s.Len()\n\ts.asMap().Insert(key, struct{}{})\n\treturn s.Len() > oldLen\n}\n\n// InsertN implements the SortedSet interface.\nfunc (s *SkipListSet[K]) InsertN(keys ...K) int {\n\toldLen := s.Len()\n\tfor i := range keys {\n\t\ts.Insert(keys[i])\n\t}\n\treturn s.Len() - oldLen\n}\n\n// Remove implements the SortedSet interface.\nfunc (s *SkipListSet[K]) Remove(key K) bool {\n\treturn s.asMap().Remove(key)\n}\n\n// RemoveN implements the SortedSet interface.\nfunc (s *SkipListSet[K]) RemoveN(keys ...K) int {\n\toldLen := s.Len()\n\tfor i := range keys {\n\t\ts.Remove(keys[i])\n\t}\n\treturn oldLen - s.Len()\n}\n\n// Keys return a copy of sorted keys as slice.\nfunc (s *SkipListSet[K]) Keys() []K {\n\tkeys := make([]K, 0, s.Len())\n\ts.ForEach(func(k K) { keys = append(keys, k) })\n\treturn keys\n}\n\n// ForEach implements the SortedSet interface.\nfunc (s *SkipListSet[K]) ForEach(f func(K)) {\n\ts.asMap().ForEach(func(k K, s struct{}) { f(k) })\n}\n\n// ForEachIf implements the SortedSet interface.\nfunc (s *SkipListSet[K]) ForEachIf(f func(K) bool) {\n\ts.asMap().ForEachIf(func(k K, s struct{}) bool { return f(k) })\n}\n\n// LowerBound implements the SortedSet interface.\nfunc (s *SkipListSet[K]) LowerBound(key K) Iterator[K] {\n\treturn &skipListSetIterator[K]{s.asMap().impl.lowerBound(key), nil}\n}\n\n// UpperBound implements the SortedSet interface.\nfunc (s *SkipListSet[K]) UpperBound(key K) Iterator[K] {\n\treturn &skipListSetIterator[K]{s.asMap().impl.upperBound(key), nil}\n}\n\n// FindRange implements the SortedSet interface.\nfunc (s *SkipListSet[K]) FindRange(first, last K) Iterator[K] {\n\tm := s.asMap().impl\n\treturn &skipListSetIterator[K]{m.lowerBound(first), m.upperBound(last)}\n}\n\nfunc (s *SkipListSet[K]) asMap() *SkipList[K, struct{}] {\n\treturn (*SkipList[K, struct{}])(s)\n}\n\ntype skipListSetIterator[K any] skipListIterator[K, struct{}]\n\nfunc (it *skipListSetIterator[K]) IsNotEnd() bool {\n\treturn it.node != it.end\n}\n\nfunc (it *skipListSetIterator[K]) MoveToNext() {\n\tit.node = it.node.next[0]\n}\n\nfunc (it *skipListSetIterator[K]) Value() K {\n\treturn it.node.key\n}\n"
  },
  {
    "path": "skiplist_set_test.go",
    "content": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc TestNewSkipList_Interface(t *testing.T) {\n\ts := NewSkipListSet[int]()\n\t_ = SortedSet[int](s)\n}\n\nfunc TestNewSkipListSet(t *testing.T) {\n\ts := NewSkipListSet[int]()\n\texpectTrue(t, s.IsEmpty())\n\texpectEq(t, s.Len(), 0)\n}\n\nfunc TestNewSkipListSetOf(t *testing.T) {\n\ts := NewSkipListSetOf(1, 2, 3, 4, 5)\n\texpectTrue(t, Equal(s.Keys(), []int{1, 2, 3, 4, 5}))\n}\n\nfunc TestNewSkipListSetFunc(t *testing.T) {\n\ts := NewSkipListSetFunc(OrderedCompare[int])\n\ts.InsertN(1, 2, 3, 4, 5)\n\texpectTrue(t, Equal(s.Keys(), []int{1, 2, 3, 4, 5}))\n}\n\nfunc TestNewSkipListSet_Insert_Remove_Has(t *testing.T) {\n\ts := NewSkipListSet[int]()\n\n\texpectFalse(t, s.Remove(1))\n\texpectFalse(t, s.Has(1))\n\n\texpectTrue(t, s.Insert(1))\n\texpectFalse(t, s.Insert(1))\n\texpectTrue(t, s.Has(1))\n\texpectFalse(t, s.IsEmpty())\n\texpectEq(t, s.Len(), 1)\n\n\texpectTrue(t, s.Remove(1))\n\texpectFalse(t, s.Remove(1))\n\texpectFalse(t, s.Has(1))\n\n\texpectTrue(t, s.IsEmpty())\n\texpectEq(t, s.Len(), 0)\n}\n\nfunc TestNewSkipListSet_Clear(t *testing.T) {\n\ts := NewSkipListSetOf(1, 2, 3, 4, 5)\n\ts.Clear()\n\texpectTrue(t, s.IsEmpty())\n\texpectEq(t, s.Len(), 0)\n}\n\nfunc TestNewSkipListSet_InsertN(t *testing.T) {\n\ts := NewSkipListSet[int]()\n\texpectEq(t, s.InsertN(1, 2, 3, 1), 3)\n\texpectFalse(t, s.IsEmpty())\n\texpectEq(t, s.Len(), 3)\n}\n\nfunc TestNewSkipListSet_RemoveN(t *testing.T) {\n\ts := NewSkipListSetOf(1, 2, 3, 4)\n\texpectEq(t, s.RemoveN(2, 4, 6), 2)\n\texpectFalse(t, s.IsEmpty())\n\texpectEq(t, s.Len(), 2)\n\texpectTrue(t, Equal(s.Keys(), []int{1, 3}))\n}\n\nfunc TestNewSkipListSet_ForEach(t *testing.T) {\n\ts := NewSkipListSetOf(1, 2, 3, 4)\n\tvar a []int\n\ts.ForEach(func(i int) { a = append(a, i) })\n\texpectTrue(t, Equal(a, []int{1, 2, 3, 4}))\n}\n\nfunc TestNewSkipListSet_ForEachIf(t *testing.T) {\n\ts := NewSkipListSetOf(1, 2, 3, 4)\n\tvar a []int\n\ts.ForEachIf(func(i int) bool { a = append(a, i); return i < 2 })\n\texpectTrue(t, Equal(a, []int{1, 2}))\n}\n\nfunc TestNewSkipList_Iterate(t *testing.T) {\n\tsl := newSkipListN(10)\n\ti := 0\n\tfor it := sl.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n\t\texpectEq(t, it.Key(), i)\n\t\texpectEq(t, it.Value(), i)\n\t\texpectEq(t, *it.Pointer(), i)\n\t\ti++\n\t}\n}\n\nfunc TestSkipListSet_Iterater(t *testing.T) {\n\ts := NewSkipListSetOf(1, 2, 4)\n\tt.Run(\"LowerBound\", func(t *testing.T) {\n\t\texpectEq(t, s.LowerBound(1).Value(), 1)\n\t\texpectEq(t, s.LowerBound(3).Value(), 4)\n\t\texpectEq(t, s.LowerBound(4).Value(), 4)\n\t\texpectFalse(t, s.LowerBound(5).IsNotEnd())\n\t})\n\n\tt.Run(\"UpperBound\", func(t *testing.T) {\n\t\texpectEq(t, s.UpperBound(0).Value(), 1)\n\t\texpectEq(t, s.UpperBound(1).Value(), 2)\n\t\texpectEq(t, s.UpperBound(3).Value(), 4)\n\t\texpectFalse(t, s.UpperBound(4).IsNotEnd())\n\t\texpectFalse(t, s.UpperBound(5).IsNotEnd())\n\t})\n\n\tt.Run(\"FindRange\", func(t *testing.T) {\n\t\tit := s.FindRange(1, 3)\n\t\texpectEq(t, it.Value(), 1)\n\t\tit.MoveToNext()\n\t\texpectEq(t, it.Value(), 2)\n\t})\n}\n"
  },
  {
    "path": "skiplist_test.go",
    "content": "package stl4go\n\nimport (\n\t\"math\"\n\t\"testing\"\n)\n\nfunc TestSkipList_Interface(t *testing.T) {\n\tsl := NewSkipList[int, int]()\n\t_ = Map[int, int](sl)\n\t_ = SortedMap[int, int](sl)\n\t_ = MapIterator[int, int](sl.Iterate())\n\t_ = MutableMapIterator[int, int](sl.Iterate())\n}\n\nfunc TestNewSkipListString(t *testing.T) {\n\tsl := NewSkipList[string, int]()\n\tsl.Insert(\"hello\", 1)\n\texpectTrue(t, sl.Has(\"hello\"))\n\texpectEq(t, *sl.Find(\"hello\"), 1)\n\texpectFalse(t, sl.Has(\"world\"))\n\texpectEq(t, sl.Find(\"world\"), nil)\n}\n\nfunc testNewSkipListType[T Numeric](t *testing.T) {\n\tsl := NewSkipList[T, int]()\n\tvar n T = 1\n\tsl.Insert(n, 1)\n\texpectTrue(t, sl.Has(n))\n\texpectEq(t, *sl.Find(n), 1)\n\texpectFalse(t, sl.Has(n+1))\n\texpectEq(t, sl.Find(n+1), nil)\n}\n\nfunc TestNewSkipListInt8(t *testing.T)  { testNewSkipListType[int8](t) }\nfunc TestNewSkipListInt16(t *testing.T) { testNewSkipListType[int16](t) }\nfunc TestNewSkipListInt32(t *testing.T) { testNewSkipListType[int32](t) }\nfunc TestNewSkipListInt64(t *testing.T) { testNewSkipListType[int64](t) }\n\nfunc TestNewSkipListUInt8(t *testing.T)  { testNewSkipListType[uint8](t) }\nfunc TestNewSkipListUInt16(t *testing.T) { testNewSkipListType[uint16](t) }\nfunc TestNewSkipListUInt32(t *testing.T) { testNewSkipListType[uint32](t) }\nfunc TestNewSkipListUInt64(t *testing.T) { testNewSkipListType[uint64](t) }\n\nfunc TestNewSkipListUIntPtr(t *testing.T) { testNewSkipListType[uintptr](t) }\n\nfunc TestNewSkipListFloat32(t *testing.T) { testNewSkipListType[float32](t) }\nfunc TestNewSkipListFloat64(t *testing.T) { testNewSkipListType[float64](t) }\n\nfunc TestNewSkipListFunc(t *testing.T) {\n\ttype Person struct {\n\t\tname string\n\t\tage  int\n\t}\n\tpersonCmp := func(a, b Person) int {\n\t\tr := OrderedCompare(a.age, b.age)\n\t\tif r != 0 {\n\t\t\treturn r\n\t\t}\n\t\treturn OrderedCompare(a.name, b.name)\n\t}\n\tsl := NewSkipListFunc[Person, int](personCmp)\n\tsl.Insert(Person{\"zhangsan\", 20}, 1)\n\tsl.Insert(Person{\"lisi\", 20}, 1)\n\tsl.Insert(Person{\"wangwu\", 30}, 1)\n\texpectTrue(t, sl.Has(Person{\"zhangsan\", 20}))\n\texpectFalse(t, sl.Has(Person{\"zhangsan\", 30}))\n\texpectEq(t, sl.Len(), 3)\n\n\tsl.Insert(Person{\"zhangsan\", 20}, 1)\n\texpectEq(t, sl.Len(), 3)\n\n\tvar ps []Person\n\tsl.ForEach(func(p Person, _ int) {\n\t\tps = append(ps, p)\n\t})\n\texpectEq(t, ps[0].name, \"lisi\")\n\texpectEq(t, ps[1].name, \"zhangsan\")\n\texpectEq(t, ps[2].name, \"wangwu\")\n\n\tsl.Remove(Person{\"zhangsan\", 20})\n\texpectEq(t, sl.Len(), 2)\n\n\tsl.Remove(Person{\"zhaoliu\", 40})\n\texpectEq(t, sl.Len(), 2)\n}\n\nfunc TestNewSkipListFromMap(t *testing.T) {\n\tm := map[int]int{1: -1, 2: -2, 3: -3}\n\tsl := NewSkipListFromMap(m)\n\tfor k := range m {\n\t\texpectTrue(t, sl.Has(k))\n\t}\n}\n\nfunc TestSkipList_Iterate(t *testing.T) {\n\tsl := newSkipListN(10)\n\ti := 0\n\tfor it := sl.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n\t\texpectEq(t, it.Key(), i)\n\t\texpectEq(t, it.Value(), i)\n\t\texpectEq(t, *it.Pointer(), i)\n\t\ti++\n\t}\n}\n\nfunc testSkipListIterater(t *testing.T, sl *SkipList[int, int]) {\n\tt.Run(\"LowerBound\", func(t *testing.T) {\n\t\texpectEq(t, sl.LowerBound(1).Key(), 1)\n\t\texpectEq(t, sl.LowerBound(3).Key(), 4)\n\t\texpectEq(t, sl.LowerBound(4).Key(), 4)\n\t\texpectFalse(t, sl.LowerBound(5).IsNotEnd())\n\t})\n\n\tt.Run(\"UpperBound\", func(t *testing.T) {\n\t\texpectEq(t, sl.UpperBound(0).Key(), 1)\n\t\texpectEq(t, sl.UpperBound(1).Key(), 2)\n\t\texpectEq(t, sl.UpperBound(3).Key(), 4)\n\t\texpectFalse(t, sl.UpperBound(4).IsNotEnd())\n\t\texpectFalse(t, sl.UpperBound(5).IsNotEnd())\n\t})\n\n\tt.Run(\"FindRange\", func(t *testing.T) {\n\t\tit := sl.FindRange(1, 3)\n\t\texpectEq(t, it.Key(), 1)\n\t\tit.MoveToNext()\n\t\texpectEq(t, it.Key(), 2)\n\t})\n}\n\nfunc TestSkipList_Iterater(t *testing.T) {\n\tsl := NewSkipListFromMap(map[int]int{1: 1, 2: 2, 4: 4})\n\ttestSkipListIterater(t, sl)\n}\n\nfunc TestSkipList_Func_Iterater(t *testing.T) {\n\tsl := NewSkipListFunc[int, int](OrderedCompare[int])\n\tm := map[int]int{1: 1, 2: 2, 4: 4}\n\tfor k, v := range m {\n\t\tsl.Insert(k, v)\n\t}\n\ttestSkipListIterater(t, sl)\n}\nfunc TestSkipList_Insert(t *testing.T) {\n\tsl := NewSkipList[int, int]()\n\tfor i := 0; i < 100; i++ {\n\t\texpectEq(t, sl.Len(), i)\n\t\tsl.Insert(i, i)\n\t\texpectEq(t, sl.Len(), i+1)\n\t}\n}\n\nfunc TestSkipList_Insert_Reverse(t *testing.T) {\n\tsl := NewSkipList[int, int]()\n\tfor i := 100; i > 0; i-- {\n\t\toldlen := sl.Len()\n\t\tsl.Insert(i, i)\n\t\texpectEq(t, sl.Len(), oldlen+1)\n\t}\n}\n\nfunc TestSkipList_Insert_Dup(t *testing.T) {\n\tsl := NewSkipList[int, int]()\n\tsl.Insert(1, 1)\n\texpectEq(t, sl.Len(), 1)\n\tsl.Insert(1, 2)\n\texpectEq(t, sl.Len(), 1)\n}\n\nfunc newSkipListN(n int) *SkipList[int, int] {\n\tsl := NewSkipList[int, int]()\n\tsl.rander.Seed(0)\n\tfor i := 0; i < n; i++ {\n\t\tsl.Insert(i, i)\n\t}\n\treturn sl\n}\n\nfunc TestSkipList_Remove(t *testing.T) {\n\tsl := newSkipListN(100)\n\tfor i := 0; i < 100; i++ {\n\t\tsl.Remove(i)\n\t}\n\texpectTrue(t, sl.IsEmpty())\n\texpectEq(t, sl.Len(), 0)\n}\n\nfunc TestSkipList_Remove_Nonexist(t *testing.T) {\n\tsl := NewSkipList[int, int]()\n\tsl.Insert(1, 1)\n\tsl.Insert(2, 2)\n\tsl.Remove(0)\n\tsl.Remove(3)\n\texpectEq(t, sl.Len(), 2)\n}\n\nfunc TestSkipList_Remove_Level(t *testing.T) {\n\tsl := newSkipListN(100)\n\texpectGe(t, sl.level, 4)\n\tfor i := 0; i < 100; i++ {\n\t\tsl.Remove(i)\n\t}\n\texpectEq(t, sl.level, 1)\n}\n\nfunc TestSkipList_Clean(t *testing.T) {\n\tsl := NewSkipList[int, int]()\n\tfor i := 0; i < 100; i++ {\n\t\tsl.Insert(i, i)\n\t}\n\tsl.Clear()\n\n\texpectTrue(t, sl.IsEmpty())\n\texpectEq(t, sl.Len(), 0)\n\texpectEq(t, sl.level, 1)\n}\n\nfunc TestSkipList_level(t *testing.T) {\n\tvar diffs []int\n\tfor i := 0; i < 1000; i++ {\n\t\tfor size := 1; size < 10000; size *= 10 {\n\t\t\tsl := newSkipListN(size)\n\t\t\tlog2Len := int(math.Ceil(math.Log2(float64(sl.Len()))))\n\t\t\tdiffs = append(diffs, log2Len-sl.level)\n\t\t}\n\t}\n\texpectLt(t, math.Abs(float64(Average(diffs))), 2)\n}\n\nfunc TestSkipList_newnode(t *testing.T) {\n\tfor level := 1; level <= skipListMaxLevel; level++ {\n\t\tnode := newSkipListNode(level, 1, 1)\n\t\texpectEq(t, len(node.next), level)\n\t}\n\texpectPanic(t, func() { newSkipListNode(0, 1, 1) })\n\texpectPanic(t, func() { newSkipListNode(skipListMaxLevel+1, 1, 1) })\n}\n\nfunc TestSkipList_Find(t *testing.T) {\n\tsl := newSkipListN(100)\n\tfor i := 0; i < 100; i++ {\n\t\tp := sl.Find(i)\n\t\texpectEq(t, *p, i)\n\t}\n\texpectEq(t, sl.Find(100), nil)\n}\n\nfunc TestSkipList_Has(t *testing.T) {\n\tsl := NewSkipList[int, int]()\n\texpectFalse(t, sl.Has(1))\n\tsl.Insert(1, 2)\n\texpectTrue(t, sl.Has(1))\n}\n\nfunc TestSkipList_ForEach(t *testing.T) {\n\tsl := newSkipListN(100)\n\ta := []int{}\n\tsl.ForEach(func(k int, v int) {\n\t\ta = append(a, k)\n\t})\n\texpectEq(t, len(a), 100)\n\texpectTrue(t, IsSorted(a))\n}\n\nfunc TestSkipList_ForEachIf(t *testing.T) {\n\tsl := newSkipListN(100)\n\ta := []int{}\n\tsl.ForEachIf(func(k int, v int) bool {\n\t\tif k < 50 {\n\t\t\ta = append(a, k)\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t})\n\texpectLt(t, MaxN(a...), 50)\n}\n\nfunc TestSkipList_ForEachMutable(t *testing.T) {\n\tsl := newSkipListN(100)\n\tsl.ForEachMutable(func(k int, v *int) {\n\t\t*v = -*v\n\t})\n\tfor i := 0; i < sl.Len(); i++ {\n\t\texpectEq(t, *sl.Find(i), -i)\n\t}\n}\n\nfunc TestSkipList_ForEachMutableIf(t *testing.T) {\n\tsl := newSkipListN(100)\n\tsl.ForEachMutableIf(func(k int, v *int) bool {\n\t\tif k > 50 {\n\t\t\t*v = 0\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\n\texpectEq(t, *sl.Find(51), 0)\n}\n"
  },
  {
    "path": "slist.go",
    "content": "package stl4go\n\n// SList is a singly linked list.\ntype SList[T any] struct {\n\thead   *sListNode[T]\n\ttail   *sListNode[T] // To support Back and PushBack\n\tlength int\n}\n\ntype sListNode[T any] struct {\n\tnext  *sListNode[T]\n\tvalue T\n}\n\n// SListOf return a SList that contains values.\nfunc SListOf[T any](values ...T) SList[T] {\n\tl := SList[T]{}\n\tfor i := range values {\n\t\tl.PushBack(values[i])\n\t}\n\treturn l\n}\n\n// IsEmpty checks if the container has no elements.\nfunc (l *SList[T]) IsEmpty() bool {\n\treturn l.length == 0\n}\n\n// Len returns the number of elements in the container.\nfunc (l *SList[T]) Len() int {\n\treturn l.length\n}\n\n// Clear erases all elements from the container. After this call, Len() returns zero.\nfunc (l *SList[T]) Clear() {\n\tl.head = nil\n\tl.tail = nil\n\tl.length = 0\n}\n\n// Front returns the first element in the list.\nfunc (l *SList[T]) Front() T {\n\tif l.IsEmpty() {\n\t\tpanic(\"!IsEmpty\")\n\t}\n\treturn l.head.value\n}\n\n// Back returns the last element in the list.\nfunc (l *SList[T]) Back() T {\n\tif l.IsEmpty() {\n\t\tpanic(\"!IsEmpty\")\n\t}\n\treturn l.tail.value\n}\n\n// PushFront pushed an element to the front of the list.\nfunc (l *SList[T]) PushFront(v T) {\n\tnode := sListNode[T]{l.head, v}\n\tl.head = &node\n\tif l.tail == nil {\n\t\tl.tail = &node\n\t}\n\tl.length++\n}\n\n// PushBack pushed an element to the tail of the list.\nfunc (l *SList[T]) PushBack(v T) {\n\tnode := sListNode[T]{nil, v}\n\tif l.tail != nil {\n\t\tl.tail.next = &node\n\t}\n\tl.tail = &node\n\tif l.head == nil {\n\t\tl.head = &node\n\t}\n\tl.length++\n}\n\n// PopFront popups an element from the front of the list.\n// The list must be non-empty!\nfunc (l *SList[T]) PopFront() T {\n\tif l.IsEmpty() {\n\t\tpanic(\"!IsEmpty\")\n\t}\n\n\tnode := l.head\n\tl.head = node.next\n\tif l.head == nil {\n\t\tl.tail = nil\n\t}\n\tl.length--\n\treturn node.value\n}\n\n// Reverse reverses the order of all elements in the container.\nfunc (l *SList[T]) Reverse() {\n\tvar head, tail *sListNode[T]\n\tfor node := l.head; node != nil; {\n\t\tnext := node.next\n\t\tnode.next = head\n\t\thead = node\n\t\tif tail == nil {\n\t\t\ttail = node\n\t\t}\n\t\tnode = next\n\t}\n\tl.head = head\n\tl.tail = tail\n}\n\n// Values copies all elements in the container to a slice and return it.\nfunc (l *SList[T]) Values() []T {\n\ts := make([]T, l.Len())\n\tfor node, i := l.head, 0; node != nil; node = node.next {\n\t\ts[i] = node.value\n\t\ti++\n\t}\n\treturn s\n}\n\n// InsertAfter inserts an element after the iterator into the list,\n// return an iterator to the inserted element.\n// func (l *SList[T]) InsertAfter(it Iterator[T], value T) MutableIterator[T] {\n// \t// cause internal compiler error: panic: runtime error: invalid memory address or nil pointer dereference\n// \titp := it.(*sListIterator[T])\n// \tnode := itp.node\n// \tnewNode := sListNode[T]{node.next, value}\n// \tnode.next = &newNode\n// \treturn &sListIterator[T]{&newNode}\n// }\n\n// ForEach iterate the list, apply each element to the cb callback function.\nfunc (l *SList[T]) ForEach(cb func(T)) {\n\tfor node := l.head; node != nil; node = node.next {\n\t\tcb(node.value)\n\t}\n}\n\n// ForEachIf iterate the container, apply each element to the cb callback function,\n// stop if cb returns false.\nfunc (l *SList[T]) ForEachIf(cb func(T) bool) {\n\tfor node := l.head; node != nil; node = node.next {\n\t\tif !cb(node.value) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// ForEachMutable iterate the container, apply pointer of each element to the cb callback function.\nfunc (l *SList[T]) ForEachMutable(cb func(*T)) {\n\tfor node := l.head; node != nil; node = node.next {\n\t\tcb(&node.value)\n\t}\n}\n\n// ForEachMutableIf iterate the container, apply pointer of each element to the cb callback function,\n// stop if cb returns false.\nfunc (l *SList[T]) ForEachMutableIf(cb func(*T) bool) {\n\tfor node := l.head; node != nil; node = node.next {\n\t\tif !cb(&node.value) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// Iterate returns an iterator to the whole container.\nfunc (l *SList[T]) Iterate() MutableIterator[T] {\n\tit := sListIterator[T]{l.head}\n\treturn &it\n}\n\ntype sListIterator[T any] struct {\n\tnode *sListNode[T]\n}\n\nfunc (it *sListIterator[T]) IsNotEnd() bool {\n\treturn it.node != nil\n}\n\nfunc (it *sListIterator[T]) MoveToNext() {\n\tit.node = it.node.next\n}\n\nfunc (it *sListIterator[T]) Value() T {\n\treturn it.node.value\n}\n\nfunc (it *sListIterator[T]) Pointer() *T {\n\treturn &it.node.value\n}\n\n// TODO: Sort\n"
  },
  {
    "path": "slist_test.go",
    "content": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_SList_Interface(t *testing.T) {\n\tsl := SList[int]{}\n\t_ = Container(&sl)\n}\n\nfunc Test_SList_Clean(t *testing.T) {\n\tsl := SList[int]{}\n\tsl.PushFront(1)\n\tsl.Clear()\n\texpectTrue(t, sl.IsEmpty())\n\texpectEq(t, sl.Len(), 0)\n}\n\nfunc Test_SList_Front(t *testing.T) {\n\tt.Run(\"empty\", func(t *testing.T) {\n\t\tsl := SList[int]{}\n\t\texpectPanic(t, func() { sl.Front() })\n\t})\n\n\tt.Run(\"normal\", func(t *testing.T) {\n\t\tsl := SList[int]{}\n\t\tsl.PushFront(1)\n\t\texpectEq(t, sl.Front(), 1)\n\n\t\tsl.PushBack(2)\n\t\texpectEq(t, sl.Front(), 1)\n\n\t\tsl.PushFront(3)\n\t\texpectEq(t, sl.Front(), 3)\n\t})\n}\n\nfunc Test_SList_Back(t *testing.T) {\n\tt.Run(\"empty\", func(t *testing.T) {\n\t\tsl := SList[int]{}\n\t\texpectPanic(t, func() { sl.Back() })\n\t})\n\n\tt.Run(\"normal\", func(t *testing.T) {\n\t\tsl := SList[int]{}\n\t\tsl.PushBack(1)\n\t\texpectEq(t, sl.Back(), 1)\n\n\t\tsl.PushFront(2)\n\t\texpectEq(t, sl.Back(), 1)\n\n\t\tsl.PushBack(3)\n\t\texpectEq(t, sl.Back(), 3)\n\t})\n}\n\nfunc Test_SList_PushFront(t *testing.T) {\n\tsl := SList[int]{}\n\tfor i := 1; i < 10; i++ {\n\t\tsl.PushFront(i)\n\t\texpectEq(t, sl.Front(), i)\n\t\texpectEq(t, sl.Len(), i)\n\t}\n}\n\nfunc Test_SList_PushBack(t *testing.T) {\n\tsl := SList[int]{}\n\tfor i := 1; i < 10; i++ {\n\t\tsl.PushBack(i)\n\t\texpectEq(t, sl.Back(), i)\n\t\texpectEq(t, sl.Len(), i)\n\t\texpectFalse(t, sl.IsEmpty())\n\t}\n}\n\nfunc Test_SList_PopFront(t *testing.T) {\n\tsl := SList[int]{}\n\texpectPanic(t, func() { sl.PopFront() })\n\n\tsl.PushFront(1)\n\tsl.PushFront(2)\n\texpectEq(t, sl.PopFront(), 2)\n\texpectEq(t, sl.PopFront(), 1)\n\texpectPanic(t, func() { sl.PopFront() })\n}\n\nfunc Test_SList_Reverse(t *testing.T) {\n\tsl := SListOf(1, 2, 3, 4)\n\tsl.Reverse()\n\texpectTrue(t, Equal(sl.Values(), []int{4, 3, 2, 1}))\n}\n\nfunc Test_SList_ForEach(t *testing.T) {\n\tsl := SListOf(1, 2, 3, 4)\n\ti := 0\n\tsl.ForEach(func(v int) {\n\t\ti++\n\t\texpectEq(t, v, i)\n\t})\n\texpectEq(t, i, sl.Len())\n}\n\nfunc Test_SList_ForEachIf(t *testing.T) {\n\tsl := SListOf(1, 2, 3, 4)\n\ti := 0\n\tsl.ForEachIf(func(v int) bool {\n\t\ti++\n\t\texpectEq(t, v, i)\n\t\treturn i < 3\n\t})\n\texpectEq(t, i, 3)\n}\n\nfunc Test_SList_ForEachMutable(t *testing.T) {\n\tsl := SListOf(1, 2, 3, 4)\n\ti := 0\n\tsl.ForEachMutable(func(v *int) {\n\t\ti++\n\t\texpectEq(t, *v, i)\n\t\t*v = -*v\n\t})\n\texpectEq(t, i, sl.Len())\n\tsl.ForEachMutable(func(v *int) {\n\t\texpectLt(t, *v, 0)\n\t})\n}\n\nfunc Test_SList_ForEachMutableIf(t *testing.T) {\n\tsl := SListOf(1, 2, 3, 4)\n\ti := 0\n\tsl.ForEachMutableIf(func(v *int) bool {\n\t\ti++\n\t\texpectEq(t, *v, i)\n\t\treturn i < 3\n\t})\n\texpectEq(t, i, 3)\n}\n\nfunc Test_SList_Iterate(t *testing.T) {\n\tsl := SList[int]{}\n\tsl.PushBack(1)\n\tsl.PushBack(2)\n\tsl.PushBack(3)\n\ti := 0\n\tfor it := sl.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n\t\ti++\n\t\texpectEq(t, it.Value(), i)\n\t\texpectEq(t, *it.Pointer(), i)\n\t}\n\texpectEq(t, i, 3)\n}\n"
  },
  {
    "path": "sort.go",
    "content": "package stl4go\n\nimport (\n\t\"sort\"\n)\n\n// IsSorted returns whether the slice a is sorted in ascending order.\n//\n// Complexity: O(len(a)).\nfunc IsSorted[T Ordered](a []T) bool {\n\tif len(a) == 0 {\n\t\treturn true\n\t}\n\tprev := a[0]\n\tfor _, v := range a[1:] {\n\t\tif v < prev {\n\t\t\treturn false\n\t\t}\n\t\tprev = v\n\t}\n\treturn true\n}\n\n// IsDescSorted returns whether the slice a is sorted in descending order.\n//\n// Complexity: O(len(a)).\nfunc IsDescSorted[T Ordered](a []T) bool {\n\tif len(a) == 0 {\n\t\treturn true\n\t}\n\tprev := a[0]\n\tfor _, v := range a[1:] {\n\t\tif v > prev {\n\t\t\treturn false\n\t\t}\n\t\tprev = v\n\t}\n\treturn true\n}\n\ntype ascSlice[T Ordered] []T\n\nfunc (x ascSlice[T]) Len() int           { return len(x) }\nfunc (x ascSlice[T]) Less(i, j int) bool { return x[i] < x[j] }\nfunc (x ascSlice[T]) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }\n\n// Sort sorts data in ascending order.\n// The order of equal elements is not guaranteed to be preserved.\n//\n// Complexity: O(N*log(N)), where N=len(a).\nfunc Sort[T Ordered](a []T) {\n\tsort.Sort(ascSlice[T](a))\n}\n\n// StableSort sorts data in ascending order stably.\n// The order of equivalent elements is guaranteed to be preserved.\n//\n// Complexity: O(N*log(N)^2), where N=len(a).\nfunc StableSort[T Ordered](a []T) {\n\tsort.Stable(ascSlice[T](a))\n}\n\ntype descSlice[T Ordered] []T\n\nfunc (x descSlice[T]) Len() int           { return len(x) }\nfunc (x descSlice[T]) Less(i, j int) bool { return x[i] > x[j] }\nfunc (x descSlice[T]) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }\n\n// DescSort sorts data in descending order.\n// The order of equal elements is not guaranteed to be preserved.\n//\n// Complexity: O(N*log(N)), N=len(a).\nfunc DescSort[T Ordered](a []T) {\n\tsort.Sort(descSlice[T](a))\n}\n\n// DescStableSort sorts data in descending order stably.\n// The order of equivalent elements is guaranteed to be preserved.\n//\n// Complexity: O(N*log(N)), N=len(a).\nfunc DescStableSort[T Ordered](a []T) {\n\tsort.Stable(descSlice[T](a))\n}\n\ntype funcSortable[T any] struct {\n\te    []T\n\tless LessFn[T]\n}\n\nfunc (x funcSortable[T]) Len() int           { return len(x.e) }\nfunc (x funcSortable[T]) Less(i, j int) bool { return x.less(x.e[i], x.e[j]) }\nfunc (x funcSortable[T]) Swap(i, j int)      { x.e[i], x.e[j] = x.e[j], x.e[i] }\n\n// SortFunc sorts data in ascending order with compare func less.\n// The order of equal elements is not guaranteed to be preserved.\n//\n// Complexity: O(N*log(N)), N=len(a).\nfunc SortFunc[T any](a []T, less func(x, y T) bool) {\n\tsort.Sort(funcSortable[T]{a, less})\n}\n\n// StableSortFunc sorts data in ascending order with compare func less stably.\n// The order of equivalent elements is guaranteed to be preserved.\n//\n// Complexity: O(N*log(N)), N=len(a).\nfunc StableSortFunc[T any](a []T, less func(x, y T) bool) {\n\tsort.Stable(funcSortable[T]{a, less})\n}\n"
  },
  {
    "path": "sort_test.go",
    "content": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_IsSorted(t *testing.T) {\n\texpectTrue(t, IsSorted([]int{}))\n\texpectTrue(t, IsSorted([]int{1, 2, 3, 4}))\n\texpectTrue(t, IsSorted([]int{1, 2, 2, 3, 4}))\n\texpectFalse(t, IsSorted([]int{1, 2, 2, 3, 2}))\n}\n\nfunc Test_IsDescSorted(t *testing.T) {\n\texpectTrue(t, IsDescSorted([]int{}))\n\texpectFalse(t, IsDescSorted([]int{1, 2, 3, 4}))\n\texpectFalse(t, IsDescSorted([]int{1, 2, 2, 3, 4}))\n\texpectTrue(t, IsDescSorted([]int{5, 4, 3, 3, 2}))\n}\n\nfunc Test_Sort(t *testing.T) {\n\ta := []int{5, 4, 3, 2, 1}\n\tSort(a)\n\texpectTrue(t, IsSorted(a))\n}\n\nfunc Test_DescSort(t *testing.T) {\n\ta := []int{1, 2, 3, 4}\n\tDescSort(a)\n\texpectTrue(t, IsDescSorted(a))\n}\n\nfunc Test_StableSort(t *testing.T) {\n\ta := []int{5, 4, 3, 2, 1}\n\tStableSort(a)\n\texpectTrue(t, IsSorted(a))\n}\n\nfunc Test_DescStableSort(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 5}\n\tDescStableSort(a)\n\texpectTrue(t, IsDescSorted(a))\n}\n\nfunc greater(x, y int) bool { return x > y }\n\nfunc Test_SortFunc(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 5}\n\tSortFunc(a, greater)\n\texpectTrue(t, IsDescSorted(a))\n}\n\nfunc Test_StableSortFunc(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 5}\n\tStableSortFunc(a, greater)\n\texpectTrue(t, IsDescSorted(a))\n}\n"
  },
  {
    "path": "stack.go",
    "content": "package stl4go\n\n// Stack s is a container adaptor that provides the functionality of a stack,\n// a LIFO (last-in, first-out) data structure.\ntype Stack[T any] struct {\n\telements []T\n}\n\n// NewStack creates a new Stack object.\nfunc NewStack[T any]() *Stack[T] {\n\treturn &Stack[T]{nil}\n}\n\n// NewStackCap creates a new Stack object with the specified capicity.\nfunc NewStackCap[T any](capicity int) *Stack[T] {\n\treturn &Stack[T]{make([]T, 0, capicity)}\n}\n\n// IsEmpty implements the Container interface.\nfunc (s Stack[T]) IsEmpty() bool {\n\treturn len(s.elements) == 0\n}\n\n// Len implements the Container interface.\nfunc (s Stack[T]) Len() int {\n\treturn len(s.elements)\n}\n\n// Cap returns the capacity of the stack.\nfunc (s Stack[T]) Cap() int {\n\treturn cap(s.elements)\n}\n\n// Clear implements the Container interface.\nfunc (s *Stack[T]) Clear() {\n\ts.elements = s.elements[0:0]\n}\n\n// Push pushes the element to the top of the stack.\nfunc (s *Stack[T]) Push(t T) {\n\ts.elements = append(s.elements, t)\n}\n\n// TryPop tries to popup an element from the top of the stack.\nfunc (s *Stack[T]) TryPop() (val T, ok bool) {\n\tvar t T\n\tif len(s.elements) == 0 {\n\t\treturn t, false\n\t}\n\tt = s.elements[len(s.elements)-1]\n\ts.elements = s.elements[:len(s.elements)-1]\n\treturn t, true\n}\n\n// Pop popups an element from the top of the stack.\n// It must be called when IsEmpty() returned false,\n// otherwise it will panic.\nfunc (s *Stack[T]) Pop() T {\n\tt := s.elements[len(s.elements)-1]\n\ts.elements = s.elements[:len(s.elements)-1]\n\treturn t\n}\n\n// Top returns the top element in the stack.\n// It must be called when s.IsEmpty() returned false,\n// otherwise it will panic.\nfunc (s Stack[T]) Top() T {\n\treturn s.elements[len(s.elements)-1]\n}\n"
  },
  {
    "path": "stack_test.go",
    "content": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_Stack_Interface(t *testing.T) {\n\t_ = Container(NewStack[int]())\n}\nfunc Test_NewStack(t *testing.T) {\n\tsi := NewStack[int]()\n\tss := NewStack[string]()\n\texpectEq(t, si.Len(), 0)\n\texpectEq(t, ss.Len(), 0)\n}\n\nfunc Test_NewStackCap(t *testing.T) {\n\ts := NewStackCap[int](10)\n\texpectEq(t, s.Len(), 0)\n\texpectEq(t, s.Cap(), 10)\n}\n\nfunc Test_StackCap(t *testing.T) {\n\ts := NewStackCap[int](10)\n\ts.Push(1)\n\texpectEq(t, s.Len(), 1)\n\texpectEq(t, s.Cap(), 10)\n}\n\nfunc Test_Stack_Clear(t *testing.T) {\n\ts := NewStack[int]()\n\ts.Push(1)\n\ts.Push(2)\n\ts.Clear()\n\texpectEq(t, s.Len(), 0)\n\texpectTrue(t, s.IsEmpty())\n}\n\nfunc Test_Stack_Push(t *testing.T) {\n\ts := NewStack[int]()\n\ts.Push(1)\n\texpectEq(t, s.Len(), 1)\n\ts.Push(2)\n\texpectEq(t, s.Len(), 2)\n}\n\nfunc Test_Stack_TryPop(t *testing.T) {\n\ts := NewStack[int]()\n\t_, ok := s.TryPop()\n\texpectFalse(t, ok)\n\ts.Push(1)\n\tv, ok := s.TryPop()\n\texpectTrue(t, ok)\n\texpectEq(t, v, 1)\n}\n\nfunc Test_Stack_Pop(t *testing.T) {\n\ts := NewStack[int]()\n\ts.Push(1)\n\tv := s.Pop()\n\texpectEq(t, v, 1)\n\texpectPanic(t, func() { s.Pop() })\n}\n\nfunc Test_Stack_Top(t *testing.T) {\n\ts := NewStack[int]()\n\ts.Push(1)\n\tv := s.Top()\n\texpectEq(t, v, 1)\n\ts.Pop()\n\texpectPanic(t, func() { s.Top() })\n}\n"
  },
  {
    "path": "test_helper.go",
    "content": "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\", msg)\n}\n\nfunc reportMismatch[T comparable](t *testing.T, a T, op string, b T) {\n\tt.Helper()\n\treport(t, fmt.Sprintf(\"%v %v %v\", a, op, b))\n}\n\nfunc expectEq[T comparable](t *testing.T, a, b T) {\n\tt.Helper()\n\tif a != b {\n\t\treportMismatch(t, a, \"==\", b)\n\t}\n}\n\nfunc expectNe[T comparable](t *testing.T, a, b T) {\n\tt.Helper()\n\tif !(a != b) {\n\t\treportMismatch(t, a, \"!=\", b)\n\t}\n}\n\nfunc expectLt[T Ordered](t *testing.T, a, b T) {\n\tt.Helper()\n\tif !(a < b) {\n\t\treportMismatch(t, a, \"<\", b)\n\t}\n}\n\nfunc expectGt[T Ordered](t *testing.T, a, b T) {\n\tt.Helper()\n\tif !(a > b) {\n\t\treportMismatch(t, a, \">\", b)\n\t}\n}\n\nfunc expectLe[T Ordered](t *testing.T, a, b T) {\n\tt.Helper()\n\tif !(a <= b) {\n\t\treportMismatch(t, a, \"<=\", b)\n\t}\n}\n\nfunc expectGe[T Ordered](t *testing.T, a, b T) {\n\tt.Helper()\n\tif !(a >= b) {\n\t\treportMismatch(t, a, \">=\", b)\n\t}\n}\n\nfunc expectTrue(t *testing.T, actual bool) {\n\tt.Helper()\n\tif !actual {\n\t\treportMismatch(t, actual, \"==\", true)\n\t}\n}\n\nfunc expectFalse(t *testing.T, actual bool) {\n\tt.Helper()\n\tif actual {\n\t\treportMismatch(t, actual, \"==\", false)\n\t}\n}\n\nfunc expectPanic(t *testing.T, f func()) {\n\tt.Helper()\n\tdefer func() {\n\t\tt.Helper()\n\t\tif r := recover(); r == nil {\n\t\t\treport(t, \"din't panic\")\n\t\t}\n\t}()\n\n\tf()\n}\n"
  },
  {
    "path": "transform.go",
    "content": "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) []T {\n\treturn append([]T{}, a...)\n}\n\n// CopyTo copies all elements in slice a to slice to, return the copied slice.\n// if slice to is large enough, no memory allocation occurs.\n//\n// Complexity: O(len(a)).\nfunc CopyTo[T any](a []T, to []T) []T {\n\tb := append(to[0:0], a...)\n\treturn b\n}\n\n// Fill fills each element in slice a with new value v.\n//\n// Complexity: O(len(a)).\nfunc Fill[T any](a []T, v T) {\n\tif len(a) == 0 {\n\t\treturn\n\t}\n\t// Preload the first value into the array/slice.\n\ta[0] = v\n\n\t// Incrementally duplicate the value into the rest of the container.\n\t// About 2~3 times faster than naive fill.\n\t// https://gist.github.com/taylorza/df2f89d5f9ab3ffd06865062a4cf015d\n\tfor j := 1; j < len(a); j *= 2 {\n\t\tcopy(a[j:], a[:j])\n\t}\n}\n\n// FillPattern fills elements in slice a with specified pattern.\n//\n// Complexity: O(len(a)).\nfunc FillPattern[T any](a []T, pattern []T) {\n\tif len(pattern) == 0 {\n\t\tpanic(\"pattern can't be empty\")\n\t}\n\t// Copy the pattern into the start of the container\n\tcopy(a, pattern)\n\n\t// Incrementally duplicate the pattern throughout the container\n\tfor j := len(pattern); j < len(a); j *= 2 {\n\t\tcopy(a[j:], a[:j])\n\t}\n}\n\n// TransformTo applies the function op to each element in slice a and fill it to slice b,\n// return the transformed slice.\n// If cap(b) >= len(a), no memory allocation.\n//\n// Complexity: O(len(a)).\nfunc TransformTo[R any, T any](a []T, op func(T) R, b []R) []R {\n\tb = b[0:0]\n\tfor i := range a {\n\t\tb = append(b, op(a[i]))\n\t}\n\treturn b\n}\n\n// Transform applies the function op to each element in slice a and set it back to the same place in a.\n//\n// Complexity: O(len(a)).\nfunc Transform[T any](a []T, op func(T) T) {\n\tfor i, v := range a {\n\t\ta[i] = op(v)\n\t}\n}\n\n// TransformCopy applies the function op to each element in slice a and return all the result as a slice.\n//\n// Complexity: O(len(a)).\nfunc TransformCopy[R any, T any](a []T, op func(T) R) []R {\n\tr := make([]R, len(a))\n\tfor i, v := range a {\n\t\tr[i] = op(v)\n\t}\n\treturn r\n}\n\n// Replace replaces every element that equals to old with new.\n//\n// Complexity: O(len(a)).\nfunc Replace[T comparable](a []T, old, new T) {\n\tfor i := range a {\n\t\tif a[i] == old {\n\t\t\ta[i] = new\n\t\t}\n\t}\n}\n\n// ReplaceIf replaces every element that make preq returns true with new.\n//\n// Complexity: O(len(a)).\nfunc ReplaceIf[T any](a []T, pred func(v T) bool, new T) {\n\tfor i := range a {\n\t\tif pred(a[i]) {\n\t\t\ta[i] = new\n\t\t}\n\t}\n}\n\n// Unique remove adjacent repeated elements from the input slice.\n// return the processed slice with new length.\n//\n// Complexity: O(len(a)).\nfunc Unique[T comparable](a []T) []T {\n\tif len(a) == 0 {\n\t\treturn a\n\t}\n\ti := 1\n\tprev := a[0]\n\tfor _, v := range a[1:] {\n\t\tif v != prev {\n\t\t\ta[i] = v\n\t\t\ti++\n\t\t\tprev = v\n\t\t}\n\t}\n\treturn a[:i]\n}\n\n// UniqueCopy remove adjacent repeated elements from the input slice.\n// return the result slice, and the input slice is kept unchanged.\n//\n// Complexity: O(len(a)).\nfunc UniqueCopy[T comparable](a []T) []T {\n\tvar r []T\n\tif len(a) == 0 {\n\t\treturn r\n\t}\n\n\tfor _, v := range a {\n\t\tif len(r) > 0 && r[len(r)-1] == v {\n\t\t\tcontinue\n\t\t}\n\t\tr = append(r, v)\n\t}\n\n\treturn r\n}\n\n// Remove remove the elements which equals to x from the input slice.\n// return the processed slice with new length.\n//\n// Complexity: O(len(a)).\nfunc Remove[T comparable](a []T, x T) []T {\n\tj := 0\n\tfor _, v := range a {\n\t\tif v != x {\n\t\t\ta[j] = v\n\t\t\tj++\n\t\t}\n\t}\n\treturn a[:j]\n}\n\n// RemoveCopy remove all elements which equals to x from the input slice.\n// return a new slice with processed results. The input slice is kept unchanged.\n//\n// Complexity: O(len(a)).\nfunc RemoveCopy[T comparable](a []T, x T) []T {\n\tr := make([]T, 0, len(a))\n\tfor _, v := range a {\n\t\tif v != x {\n\t\t\tr = append(r, v)\n\t\t}\n\t}\n\treturn r\n}\n\n// RemoveIf remove each element which make cond(x) returns true from the input slice,\n// copy other elements to a new slice and return it.\n//\n// Complexity: O(len(a)).\nfunc RemoveIf[T any](a []T, cond func(T) bool) []T {\n\tj := 0\n\tfor _, v := range a {\n\t\tif !cond(v) {\n\t\t\ta[j] = v\n\t\t\tj++\n\t\t}\n\t}\n\treturn a[:j]\n}\n\n// RemoveIfCopy drops each element which make cond(x) returns true from the input slice,\n// copy other elements to a new slice and return it. The input slice is kept unchanged.\n//\n// Complexity: O(len(a)).\nfunc RemoveIfCopy[T any](a []T, cond func(T) bool) []T {\n\tr := make([]T, 0, len(a))\n\tfor _, v := range a {\n\t\tif !cond(v) {\n\t\t\tr = append(r, v)\n\t\t}\n\t}\n\treturn r\n}\n\n// Shuffle pseudo-randomizes the order of elements.\n//\n// Complexity: O(len(a)).\nfunc Shuffle[T any](a []T) {\n\trand.Shuffle(len(a), func(i, j int) {\n\t\ta[i], a[j] = a[j], a[i]\n\t})\n}\n\n// Reverse reverses the order of the elements in the slice a.\n//\n// Complexity: O(len(a)).\nfunc Reverse[T any](a []T) {\n\tfor i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {\n\t\ta[i], a[j] = a[j], a[i]\n\t}\n}\n\n// ReverseCopy returns a reversed copy of slice a.\n//\n// Complexity: O(len(a)).\nfunc ReverseCopy[T any](a []T) []T {\n\tb := make([]T, 0, len(a))\n\tfor i := len(a) - 1; i >= 0; i-- {\n\t\tb = append(b, a[i])\n\t}\n\treturn b\n}\n"
  },
  {
    "path": "transform_fillzero_clear.go",
    "content": "//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// Complexity: O(len(a)).\nfunc FillZero[T any](a []T) {\n\tclear(a)\n}\n"
  },
  {
    "path": "transform_fillzero_old.go",
    "content": "//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// Complexity: O(len(a)).\nfunc FillZero[T any](a []T) {\n\tvar zero T\n\tFill(a, zero)\n}\n"
  },
  {
    "path": "transform_test.go",
    "content": "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 := []int{1, 2, 3, 4}\n\tb := Copy(a)\n\texpectTrue(t, Equal(a, b))\n}\n\nfunc Test_CopyTo(t *testing.T) {\n\ta := []int{1, 2, 3, 4}\n\ttos := [][]int{nil, make([]int, 0), make([]int, 10)}\n\tfor _, to := range tos {\n\t\tb := CopyTo(a, to)\n\t\texpectTrue(t, Equal(a, b))\n\t}\n}\n\nfunc Test_Fill(t *testing.T) {\n\ta := []int{1, 2, 3, 4}\n\tFill(a, 1)\n\texpectTrue(t, Equal(a, []int{1, 1, 1, 1}))\n\tb := a[:0]\n\tFill(b, 2)\n\texpectTrue(t, Equal(a, []int{1, 1, 1, 1}))\n}\n\nfunc Test_FillZero(t *testing.T) {\n\ta := []int{1, 2, 3, 4}\n\tFillZero(a)\n\texpectTrue(t, Equal(a, []int{0, 0, 0, 0}))\n}\n\nfunc naiveFill[T any](a []T, v T) {\n\tfor i := range a {\n\t\ta[i] = v\n\t}\n}\n\nfunc BenchmarkFill(b *testing.B) {\n\ta := make([]int, 10000)\n\tb.Run(\"Fill\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tFill(a, 1)\n\t\t}\n\t})\n\tb.Run(\"naiveFill\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tnaiveFill(a, 1)\n\t\t}\n\t})\n}\n\nfunc Test_FillPattern(t *testing.T) {\n\ta := make([]int, 10)\n\tp := []int{1, 2, 3}\n\tFillPattern(a, p)\n\texpectTrue(t, Equal(a, []int{1, 2, 3, 1, 2, 3, 1, 2, 3, 1}))\n\texpectPanic(t, func() { FillPattern(a, []int{}) })\n}\n\nfunc Test_Transform(t *testing.T) {\n\ta := Range(0, 100)\n\tTransform(a, func(v int) int { return v * v })\n\tfor i, v := range a {\n\t\texpectEq(t, v, i*i)\n\t}\n}\n\nfunc Test_TransformTo(t *testing.T) {\n\ta := Range(0, 100)\n\tb := make([]string, len(a))\n\tr1 := TransformTo(a, func(v int) string { return strconv.Itoa(v) }, b)\n\tfor i, v := range a {\n\t\texpectEq(t, b[i], strconv.Itoa(v))\n\t}\n\texpectEq(t, &r1[0], &b[0])\n\tc := make([]string, len(a)-1)\n\tr2 := TransformTo(a, func(v int) string { return strconv.Itoa(v) }, c)\n\texpectEq(t, len(a), len(r2))\n\texpectNe(t, &r2[0], &c[0])\n}\n\nfunc Test_TransformCopy(t *testing.T) {\n\ta := Range(0, 100)\n\tb := TransformCopy(a, func(v int) string { return strconv.Itoa(v) })\n\tfor i, v := range b {\n\t\texpectEq(t, v, strconv.Itoa(i))\n\t}\n}\n\nfunc Test_Replace(t *testing.T) {\n\ta := []int{1, 2, 2, 4}\n\tReplace(a, 2, 3)\n\texpectTrue(t, Equal(a, []int{1, 3, 3, 4}))\n}\n\nfunc Test_ReplaceIf(t *testing.T) {\n\ta := []int{1, 2, 2, 4}\n\tReplaceIf(a, func(n int) bool { return n == 2 }, 3)\n\texpectTrue(t, Equal(a, []int{1, 3, 3, 4}))\n}\n\nfunc Test_Unique(t *testing.T) {\n\texpectTrue(t, Equal(Unique(emptyInts), emptyInts))\n\ta := []int{1, 2, 2, 3, 2, 4}\n\tb := []int{1, 2, 3, 2, 4}\n\texpectTrue(t, Equal(Unique(a), b))\n\texpectTrue(t, Equal(Unique(a[:len(b)]), b))\n}\n\nfunc Test_UniqueCopy(t *testing.T) {\n\texpectTrue(t, Equal(UniqueCopy(emptyInts), emptyInts))\n\ta := []int{1, 2, 2, 3, 2, 4}\n\ta1 := append([]int{}, a...)\n\tb := []int{1, 2, 3, 2, 4}\n\texpectTrue(t, Equal(UniqueCopy(a), b))\n\texpectTrue(t, Equal(a, a1))\n}\n\nfunc Test_Remove(t *testing.T) {\n\ta := []int{1, 2, 2, 3, 2, 4}\n\tb := Remove(a, 2)\n\texpectTrue(t, Equal([]int{1, 3, 4}, b))\n\texpectTrue(t, Equal([]int{1, 3, 4}, a[:len(b)]))\n}\n\nfunc Test_RemoveCopy(t *testing.T) {\n\ta := []int{1, 2, 2, 3, 2, 4}\n\ta1 := []int{1, 2, 2, 3, 2, 4}\n\tb := RemoveCopy(a, 2)\n\texpectTrue(t, Equal([]int{1, 3, 4}, b))\n\texpectTrue(t, Equal(a1, a))\n}\n\nfunc Test_RemoveIf(t *testing.T) {\n\ta := []int{1, 2, 2, 3, 2, 4}\n\tb := RemoveIf(a, func(v int) bool { return v == 2 })\n\texpectTrue(t, Equal([]int{1, 3, 4}, b))\n\texpectTrue(t, Equal([]int{1, 3, 4}, a[:len(b)]))\n}\n\nfunc Test_RemoveIfCopy(t *testing.T) {\n\ta := []int{1, 2, 2, 3, 2, 4}\n\ta1 := []int{1, 2, 2, 3, 2, 4}\n\tb := RemoveIfCopy(a, func(v int) bool { return v == 2 })\n\texpectTrue(t, Equal([]int{1, 3, 4}, b))\n\texpectTrue(t, Equal(a1, a))\n}\n\nfunc Test_Shuffle(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 5, 6}\n\tShuffle(a)\n}\n\nfunc Test_Reverse(t *testing.T) {\n\ta := []int{1, 2, 3, 4}\n\tReverse(a)\n\texpectTrue(t, Equal(a, []int{4, 3, 2, 1}))\n}\n\nfunc Test_Reverse_Odd(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 5}\n\tReverse(a)\n\texpectTrue(t, Equal(a, []int{5, 4, 3, 2, 1}))\n}\n\nfunc Test_ReverseCopy(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 5}\n\tb := ReverseCopy(a)\n\texpectTrue(t, Equal(b, []int{5, 4, 3, 2, 1}))\n}\n"
  },
  {
    "path": "types.go",
    "content": "package stl4go\n\n// Signed is a constraint that permits any signed integer type.\n// If future releases of Go add new predeclared signed integer types,\n// this constraint will be modified to include them.\ntype Signed interface {\n\t~int | ~int8 | ~int16 | ~int32 | ~int64\n}\n\n// Unsigned is a constraint that permits any unsigned integer type.\n// If future releases of Go add new predeclared unsigned integer types,\n// this constraint will be modified to include them.\ntype Unsigned interface {\n\t~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr\n}\n\n// Integer is a constraint that permits any integer type.\n// If future releases of Go add new predeclared integer types,\n// this constraint will be modified to include them.\ntype Integer interface {\n\tSigned | Unsigned\n}\n\n// Float is a constraint that permits any floating-point type.\n// If future releases of Go add new predeclared floating-point types,\n// this constraint will be modified to include them.\ntype Float interface {\n\t~float32 | ~float64\n}\n\n// Ordered is a constraint that permits any ordered type: any type\n// that supports the operators < <= >= >.\n// If future releases of Go add new ordered types,\n// this constraint will be modified to include them.\ntype Ordered interface {\n\tInteger | Float | ~string\n}\n\n// Numeric is a constraint that permits any numeric type.\ntype Numeric interface {\n\tInteger | Float\n}\n\n// LessFn is a function that returns whether 'a' is less than 'b'.\ntype LessFn[T any] func(a, b T) bool\n\n// CompareFn is a 3 way compare function that\n// returns 1  if a >  b,\n// returns 0  if a == b,\n// returns -1 if a < b.\ntype CompareFn[T any] func(a, b T) int\n\n// HashFn is a function that returns the hash of 't'.\ntype HashFn[T any] func(t T) uint64\n"
  },
  {
    "path": "updatedoc.bat",
    "content": "@echo off\n\ngomarkdoc -o generated_doc.md -e .\n"
  },
  {
    "path": "updatedoc.sh",
    "content": "#!/bin/bash\n\ngomarkdoc -o generated_doc.md -e .\n"
  },
  {
    "path": "vector.go",
    "content": "package stl4go\n\n// Many tricks are from:\n// https://github.com/golang/go/wiki/SliceTricks#in-place-deduplicate-comparable\n\n// Vector is a sequence container representing array that can change in size.\ntype Vector[T any] []T\n\n// MakeVector creates an empty Vector object.\nfunc MakeVector[T any]() Vector[T] {\n\treturn (Vector[T])([]T{})\n}\n\n// MakeVectorCap creates an empty Vector object with specified capacity.\nfunc MakeVectorCap[T any](c int) Vector[T] {\n\tv := make([]T, 0, c)\n\treturn (Vector[T])(v)\n}\n\n// VectorOf creates a Vector object with initial values.\nfunc VectorOf[T any](v ...T) Vector[T] {\n\treturn (Vector[T])(v)\n}\n\n// AsVector casts a slice as a Vector object.\nfunc AsVector[T any](s []T) Vector[T] {\n\treturn (Vector[T])(s)\n}\n\n// IsEmpty implements the Container interface.\nfunc (v *Vector[T]) IsEmpty() bool {\n\treturn len(*v) == 0\n}\n\n// Len implements the Container interface.\nfunc (v *Vector[T]) Len() int {\n\treturn len(*v)\n}\n\n// Cap returns the capacity of the vector.\nfunc (v *Vector[T]) Cap() int {\n\treturn cap(*v)\n}\n\n// Clear erases all elements from the vector. After this call, Len() returns zero.\n// Leaves the Cap() of the vector unchanged.\nfunc (v *Vector[T]) Clear() {\n\tFillZero(*v)\n\t*v = (*v)[0:0]\n}\n\n// Reserve increases the capacity of the vector (the total number of elements\n// that the vector can hold without requiring reallocation)to a value that's\n// greater or equal to l. If l is greater than the current Cap(), new storage\n// is allocated, otherwise the function does nothing.\n//\n// Reserve() does not change the size of the vector.\nfunc (v *Vector[T]) Reserve(l int) {\n\tif cap(*v) < l {\n\t\tt := make([]T, len(*v), l)\n\t\tcopy(t, *v)\n\t\t*v = t\n\t}\n}\n\n// Shrink removes unused capacity from the vector.\nfunc (v *Vector[T]) Shrink() {\n\tif cap(*v) > len(*v) {\n\t\t*v = append([]T{}, *v...)\n\t}\n}\n\n// At returns the element value at the index i.\n// You can also use the [] operator, and it's better.\nfunc (v *Vector[T]) At(i int) T {\n\treturn (*v)[i]\n}\n\n// Set sets the value of the element at the index i.\n// You can also use the [] operator, and it's better.\nfunc (v *Vector[T]) Set(i int, x T) {\n\t(*v)[i] = x\n}\n\n// PushBack pushs an element to the end of the vector.\n//\n// Complexity: O(1) if v.Len() < v.Cap(), therwise O(len(v)).\nfunc (v *Vector[T]) PushBack(x T) {\n\t*v = append(*v, x)\n}\n\n// PopBack popups an element from the end of the vector.\n// It must be called when IsEmpty() returned false,\n// otherwise it will panic.\nfunc (v *Vector[T]) PopBack() T {\n\tvar zero T\n\te := (*v)[v.Len()-1]\n\t(*v)[len(*v)-1] = zero\n\t*v = (*v)[0 : v.Len()-1]\n\treturn e\n}\n\n// TryPopBack popups an element from the end of the vector.\nfunc (v *Vector[T]) TryPopBack() (T, bool) {\n\tif v.IsEmpty() {\n\t\tvar zero T\n\t\treturn zero, false\n\t}\n\treturn v.PopBack(), true\n}\n\n// Back returns the element at the end of the vector.\n// It must be called when IsEmpty() returned false,\n// otherwise it will panic.\nfunc (v Vector[T]) Back() T {\n\treturn v[len(v)-1]\n}\n\n// Append appends the values x... to the tail of the vector.\nfunc (v *Vector[T]) Append(x ...T) {\n\t*v = append(*v, x...)\n}\n\n// Insert inserts the values x... into the vector at index i.\n// After the insertion, (*v)[i] == x[0].\n// Insert panics if i is out of range.\n//\n// Complexity: O(len(s) + len(v)).\nfunc (v *Vector[T]) Insert(i int, x ...T) {\n\ts := *v\n\ttotal := len(s) + len(x)\n\tif total <= cap(s) {\n\t\ts2 := s[:total]\n\t\tcopy(s2[i+len(x):], s[i:])\n\t\tcopy(s2[i:], x)\n\t\t*v = s2\n\t\treturn\n\t}\n\ts2 := make([]T, total)\n\tcopy(s2, s[:i])\n\tcopy(s2[i:], x)\n\tcopy(s2[i+len(x):], s[i:])\n\t*v = s2\n}\n\n// Remove removes 1 element in the vector.\n//\n// Complexity: O(len(s) - i).\nfunc (v *Vector[T]) Remove(i int) {\n\tv.RemoveRange(i, i+1)\n}\n\n// RemoveRange removes the elements in the range[i, j) from the vector.\nfunc (v *Vector[T]) RemoveRange(i, j int) {\n\toldV := *v\n\t*v = append((*v)[:i], (*v)[j:]...)\n\tFillZero(oldV[v.Len():])\n}\n\n// RemoveLength removes the elements in the range[i, i+len) from the vector.\nfunc (v *Vector[T]) RemoveLength(i int, len int) {\n\tv.RemoveRange(i, i+len)\n}\n\n// RemoveIf removes the elements which make cond(x) returns true from the vector.\nfunc (v *Vector[T]) RemoveIf(cond func(T) bool) {\n\toldV := *v\n\t*v = RemoveIf(*v, cond)\n\tFillZero(oldV[v.Len():])\n}\n\n// ForEach iterate the container, apply each element to the cb callback function.\nfunc (v Vector[T]) ForEach(cb func(val T)) {\n\tfor _, e := range v {\n\t\tcb(e)\n\t}\n}\n\n// ForEachIf iterate the container, apply each element to the cb callback function,\n// stop if cb returns false.\nfunc (v Vector[T]) ForEachIf(cb func(val T) bool) {\n\tfor _, e := range v {\n\t\tif !cb(e) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// ForEachMutable iterate the container, apply pointer of each element to the cb callback function.\nfunc (v Vector[T]) ForEachMutable(cb func(val *T)) {\n\tfor i := range v {\n\t\tcb(&v[i])\n\t}\n}\n\n// ForEachMutableIf iterate the container, apply pointer of each element to the cb callback function,\n// stop if cb returns false.\nfunc (v Vector[T]) ForEachMutableIf(cb func(val *T) bool) {\n\tfor i := range v {\n\t\tif !cb(&v[i]) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// Iterate returns an iterator to the whole container.\nfunc (v Vector[T]) Iterate() MutableIterator[T] {\n\treturn &vectorIterator[T]{v, 0}\n}\n\n// IterateRange returns an iterator to the range [i, j) of the container.\nfunc (v Vector[T]) IterateRange(i, j int) MutableIterator[T] {\n\treturn &vectorIterator[T]{v[i:j], 0}\n}\n\ntype vectorIterator[T any] struct {\n\tv Vector[T]\n\ti int\n}\n\nfunc (it vectorIterator[T]) Value() T {\n\treturn it.v[it.i]\n}\n\nfunc (it vectorIterator[T]) Pointer() *T {\n\treturn &it.v[it.i]\n}\n\nfunc (it vectorIterator[T]) IsNotEnd() bool {\n\treturn it.i < len(it.v)\n}\n\nfunc (it *vectorIterator[T]) MoveToNext() {\n\tit.i++\n}\n"
  },
  {
    "path": "vector_test.go",
    "content": "package stl4go\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_Vector_Interface(t *testing.T) {\n\tv := MakeVector[int]()\n\t_ = Container(&v)\n}\n\nfunc Test_MakeVector(t *testing.T) {\n\tMakeVector[int]()\n\t_ = make(Vector[int], 1)\n\t_ = make(Vector[int], 1, 2)\n\tvar v Vector[int]\n\t_ = v\n\tv = Vector[int]{1, 2, 3}\n}\n\nfunc Test_MakeVectorCap(t *testing.T) {\n\tv := MakeVectorCap[int](10)\n\texpectEq(t, v.Len(), 0)\n\texpectEq(t, v.Cap(), 10)\n}\n\nfunc Test_VectorOf(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\texpectEq(t, v.Len(), 3)\n\texpectEq(t, v.Cap(), 3)\n\texpectEq(t, v[0], 1)\n\texpectEq(t, v[1], 2)\n\texpectEq(t, v[2], 3)\n}\n\nfunc Test_AsVector(t *testing.T) {\n\ts := []int{1, 2, 3}\n\tv := AsVector(s)\n\texpectTrue(t, Equal(s, v))\n\texpectEq(t, &s[0], &v[0])\n}\n\nfunc Test_VectorCap(t *testing.T) {\n\tv := MakeVectorCap[int](10)\n\tv.PushBack(1)\n\texpectEq(t, v.Len(), 1)\n\texpectFalse(t, v.IsEmpty())\n\texpectEq(t, v.Cap(), 10)\n}\n\nfunc Test_Vector_Clear(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tv.Clear()\n\texpectEq(t, v.Len(), 0)\n\texpectTrue(t, v.IsEmpty())\n\texpectGt(t, v.Cap(), 0)\n}\n\nfunc Test_Vector_Reserve(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tv.Reserve(1)\n\texpectEq(t, v.Cap(), 3)\n\tv.Reserve(5)\n\texpectEq(t, v.Cap(), 5)\n\texpectEq(t, v.Len(), 3)\n}\n\nfunc Test_Vector_Shrink(t *testing.T) {\n\tv := MakeVectorCap[int](10)\n\tv.Append(1, 2, 3)\n\texpectEq(t, v.Cap(), 10)\n\tv.Shrink()\n\texpectEq(t, v.Len(), v.Cap())\n}\n\nfunc Test_Vector_At_Set(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\texpectEq(t, v.At(0), 1)\n\texpectEq(t, v[0], 1)\n\tv[0] = 2\n\texpectEq(t, v[0], 2)\n\texpectPanic(t, func() { v.Set(3, 2) })\n}\n\nfunc Test_Vector_PushBack(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tv.PushBack(4)\n\texpectTrue(t, Equal(v, []int{1, 2, 3, 4}))\n}\n\nfunc Test_Vector_PopBack(t *testing.T) {\n\tv := VectorOf(1, 2)\n\texpectEq(t, v.PopBack(), 2)\n\tn, ok := v.TryPopBack()\n\texpectEq(t, n, 1)\n\texpectTrue(t, ok)\n\tn, ok = v.TryPopBack()\n\texpectEq(t, n, 0)\n\texpectFalse(t, ok)\n\texpectPanic(t, func() { v.PopBack() })\n}\n\nfunc Test_Vector_PopBack_Clear(t *testing.T) {\n\tv := VectorOf(1, 2)\n\toldV := v\n\tv.PopBack()\n\texpectEq(t, oldV[1], 0)\n}\n\nfunc Test_Vector_Back(t *testing.T) {\n\tv := VectorOf(1)\n\texpectEq(t, v.Back(), 1)\n\tv.PopBack()\n\texpectPanic(t, func() { v.Back() })\n}\n\nfunc Test_Vector_Insert(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tv.Insert(0, 1, 2, 3)\n\texpectTrue(t, Equal(v, []int{1, 2, 3, 1, 2, 3}))\n}\n\nfunc Test_Vector_Insert_Tail(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tv.Insert(3, 1, 2, 3)\n\texpectTrue(t, Equal(v, []int{1, 2, 3, 1, 2, 3}))\n}\n\nfunc Test_Vector_Insert_Mid(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tv.Insert(2, 1, 2)\n\texpectTrue(t, Equal(v, []int{1, 2, 1, 2, 3}))\n}\n\nfunc Test_Vector_Insert_Cap(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tv.Reserve(8)\n\tv.Insert(2, 1, 2)\n\texpectTrue(t, Equal(v, []int{1, 2, 1, 2, 3}))\n}\n\nfunc Test_Vector_Remove(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\toldV := v\n\tv.Remove(1)\n\texpectEq(t, v.Len(), 2)\n\texpectEq(t, v.Cap(), 3)\n\texpectEq(t, v[0], 1)\n\texpectEq(t, v[1], 3)\n\texpectEq(t, oldV[2], 0)\n}\n\nfunc Test_Vector_RemoveRange(t *testing.T) {\n\tv := VectorOf(1, 2, 3, 4)\n\toldV := v\n\tv.RemoveRange(1, 3)\n\texpectEq(t, v.Len(), 2)\n\texpectEq(t, v.Cap(), 4)\n\texpectEq(t, v[0], 1)\n\texpectEq(t, v[1], 4)\n\texpectEq(t, oldV[2], 0)\n\texpectEq(t, oldV[3], 0)\n}\n\nfunc Test_Vector_RemoveLength(t *testing.T) {\n\tv := VectorOf(1, 2, 3, 4)\n\toldV := v\n\tv.RemoveLength(1, 2)\n\texpectEq(t, v.Len(), 2)\n\texpectEq(t, v.Cap(), 4)\n\texpectEq(t, v[0], 1)\n\texpectEq(t, v[1], 4)\n\texpectEq(t, oldV[2], 0)\n\texpectEq(t, oldV[3], 0)\n}\n\nfunc Test_Vector_RemoveIf(t *testing.T) {\n\tv := VectorOf(1, 2, 3, 4)\n\toldV := v\n\tv.RemoveIf(func(i int) bool { return i%2 == 0 })\n\texpectEq(t, v.Len(), 2)\n\texpectEq(t, v.Cap(), 4)\n\texpectEq(t, v[0], 1)\n\texpectEq(t, v[1], 3)\n\texpectEq(t, oldV[2], 0)\n\texpectEq(t, oldV[3], 0)\n}\n\nfunc Test_Vector_ForEach(t *testing.T) {\n\ta := []int{1, 2, 3}\n\tv := VectorOf(a...)\n\tvar b []int\n\tv.ForEach(func(n int) {\n\t\tb = append(b, n)\n\t})\n\texpectEq(t, len(b), 3)\n\texpectTrue(t, Equal(a, b))\n}\n\nfunc Test_Vector_ForEachIf(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tc := 0\n\tv.ForEachIf(func(n int) bool {\n\t\tc = n\n\t\treturn n != 2\n\t})\n\texpectEq(t, c, 2)\n}\n\nfunc Test_Vector_ForEachMutable(t *testing.T) {\n\ta := []int{1, 2, 3}\n\tv := VectorOf(1, 2, 3)\n\tv.ForEachMutable(func(n *int) {\n\t\t*n = -*n\n\t})\n\texpectEq(t, v.Len(), 3)\n\tfor i := range v {\n\t\texpectEq(t, a[i], -v[i])\n\t}\n}\n\nfunc Test_Vector_ForEachMutableIf(t *testing.T) {\n\tv := VectorOf(1, 2, 3)\n\tc := 0\n\tv.ForEachMutableIf(func(n *int) bool {\n\t\tc = *n\n\t\treturn *n != 2\n\t})\n\texpectEq(t, c, 2)\n}\n\nfunc Test_Vector_Iterate(t *testing.T) {\n\tv := VectorOf(1, 2, 3, 4)\n\ti := 1\n\tfor it := v.Iterate(); it.IsNotEnd(); it.MoveToNext() {\n\t\texpectEq(t, it.Value(), i)\n\t\texpectEq(t, *it.Pointer(), it.Value())\n\t\ti++\n\t}\n\texpectEq(t, i, 5)\n}\n\nfunc Test_Vector_IterateRange(t *testing.T) {\n\tv := VectorOf(1, 2, 3, 4)\n\ti := 2\n\tfor it := v.IterateRange(1, 3); it.IsNotEnd(); it.MoveToNext() {\n\t\texpectEq(t, it.Value(), i)\n\t\texpectEq(t, *it.Pointer(), it.Value())\n\t\ti++\n\t}\n\texpectEq(t, i, 4)\n}\n"
  }
]