mirror of
https://github.com/Luzifer/ansible-role-version.git
synced 2024-12-23 02:51:20 +00:00
Update dependencies
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
fe680c31db
commit
209b813c5b
2298 changed files with 1037783 additions and 285 deletions
179
Gopkg.lock
generated
179
Gopkg.lock
generated
|
@ -1,12 +1,55 @@
|
||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/emirpasic/gods"
|
||||||
|
packages = [
|
||||||
|
"containers",
|
||||||
|
"lists",
|
||||||
|
"lists/arraylist",
|
||||||
|
"trees",
|
||||||
|
"trees/binaryheap",
|
||||||
|
"utils"
|
||||||
|
]
|
||||||
|
revision = "f6c17b524822278a87e3b3bd809fec33b51f5b46"
|
||||||
|
version = "v1.9.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/inconshreveable/mousetrap"
|
name = "github.com/inconshreveable/mousetrap"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||||
version = "v1.0"
|
version = "v1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/jbenet/go-context"
|
||||||
|
packages = ["io"]
|
||||||
|
revision = "d14ea06fba99483203c19d92cfcd13ebe73135f4"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/kevinburke/ssh_config"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "9fc7bb800b555d63157c65a904c86a2cc7b4e795"
|
||||||
|
version = "0.4"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/mitchellh/go-homedir"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "b8bc1bf767474819792c23f32d8286a45736f1c6"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/pelletier/go-buffruneio"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "c37440a7cf42ac63b919c752ca73a85067e05992"
|
||||||
|
version = "v0.2.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/sergi/go-diff"
|
||||||
|
packages = ["diffmatchpatch"]
|
||||||
|
revision = "1744e2970ca51c86172c8190fadad617561ed6e7"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/spf13/cobra"
|
name = "github.com/spf13/cobra"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
@ -20,14 +63,144 @@
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "v2"
|
name = "github.com/src-d/gcfg"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"scanner",
|
||||||
|
"token",
|
||||||
|
"types"
|
||||||
|
]
|
||||||
|
revision = "f187355171c936ac84a82793659ebb4936bc1c23"
|
||||||
|
version = "v1.3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/xanzy/ssh-agent"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "ba9c9e33906f58169366275e3450db66139a31a9"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/crypto"
|
||||||
|
packages = [
|
||||||
|
"cast5",
|
||||||
|
"curve25519",
|
||||||
|
"ed25519",
|
||||||
|
"ed25519/internal/edwards25519",
|
||||||
|
"internal/chacha20",
|
||||||
|
"openpgp",
|
||||||
|
"openpgp/armor",
|
||||||
|
"openpgp/elgamal",
|
||||||
|
"openpgp/errors",
|
||||||
|
"openpgp/packet",
|
||||||
|
"openpgp/s2k",
|
||||||
|
"poly1305",
|
||||||
|
"ssh",
|
||||||
|
"ssh/agent",
|
||||||
|
"ssh/knownhosts"
|
||||||
|
]
|
||||||
|
revision = "c3a3ad6d03f7a915c0f7e194b7152974bb73d287"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/net"
|
||||||
|
packages = ["context"]
|
||||||
|
revision = "92b859f39abd2d91a854c9f9c4621b2f5054a92d"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/sys"
|
||||||
|
packages = ["windows"]
|
||||||
|
revision = "d8e400bc7db4870d786864138af681469693d18c"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "golang.org/x/text"
|
||||||
|
packages = [
|
||||||
|
"internal/gen",
|
||||||
|
"internal/triegen",
|
||||||
|
"internal/ucd",
|
||||||
|
"transform",
|
||||||
|
"unicode/cldr",
|
||||||
|
"unicode/norm"
|
||||||
|
]
|
||||||
|
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||||
|
version = "v0.3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "gopkg.in/src-d/go-billy.v4"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"helper/chroot",
|
||||||
|
"helper/polyfill",
|
||||||
|
"memfs",
|
||||||
|
"osfs",
|
||||||
|
"util"
|
||||||
|
]
|
||||||
|
revision = "027dceab1aa836eb310d92c2eb2266e4dc9f4b81"
|
||||||
|
version = "v4.1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "gopkg.in/src-d/go-git.v4"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"config",
|
||||||
|
"internal/revision",
|
||||||
|
"plumbing",
|
||||||
|
"plumbing/cache",
|
||||||
|
"plumbing/filemode",
|
||||||
|
"plumbing/format/config",
|
||||||
|
"plumbing/format/diff",
|
||||||
|
"plumbing/format/gitignore",
|
||||||
|
"plumbing/format/idxfile",
|
||||||
|
"plumbing/format/index",
|
||||||
|
"plumbing/format/objfile",
|
||||||
|
"plumbing/format/packfile",
|
||||||
|
"plumbing/format/pktline",
|
||||||
|
"plumbing/object",
|
||||||
|
"plumbing/protocol/packp",
|
||||||
|
"plumbing/protocol/packp/capability",
|
||||||
|
"plumbing/protocol/packp/sideband",
|
||||||
|
"plumbing/revlist",
|
||||||
|
"plumbing/storer",
|
||||||
|
"plumbing/transport",
|
||||||
|
"plumbing/transport/client",
|
||||||
|
"plumbing/transport/file",
|
||||||
|
"plumbing/transport/git",
|
||||||
|
"plumbing/transport/http",
|
||||||
|
"plumbing/transport/internal/common",
|
||||||
|
"plumbing/transport/server",
|
||||||
|
"plumbing/transport/ssh",
|
||||||
|
"storage",
|
||||||
|
"storage/filesystem",
|
||||||
|
"storage/filesystem/internal/dotgit",
|
||||||
|
"storage/memory",
|
||||||
|
"utils/binary",
|
||||||
|
"utils/diff",
|
||||||
|
"utils/ioutil",
|
||||||
|
"utils/merkletrie",
|
||||||
|
"utils/merkletrie/filesystem",
|
||||||
|
"utils/merkletrie/index",
|
||||||
|
"utils/merkletrie/internal/frame",
|
||||||
|
"utils/merkletrie/noder"
|
||||||
|
]
|
||||||
|
revision = "1d28459504251497e0ce6132a0fadd5eb44ffd22"
|
||||||
|
version = "v4.2.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "gopkg.in/warnings.v0"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "ec4a0fea49c7b46c2aeb0b51aac55779c607e52b"
|
||||||
|
version = "v0.1.2"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
name = "gopkg.in/yaml.v2"
|
name = "gopkg.in/yaml.v2"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
|
revision = "7f97868eec74b32b0982dd158a51a446d1da7eb5"
|
||||||
|
version = "v2.1.1"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "7ff1f45772d06d809a7ce689131011edc8fbd443f3b3d5b819110f42ad9d5283"
|
inputs-digest = "232dd462ee87625b6d06a386c00dff327b7e8f1033800dd1383ea2d9e2c94dd4"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
26
vendor/github.com/emirpasic/gods/.gitignore
generated
vendored
Normal file
26
vendor/github.com/emirpasic/gods/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
||||||
|
.idea
|
10
vendor/github.com/emirpasic/gods/.travis.yml
generated
vendored
Normal file
10
vendor/github.com/emirpasic/gods/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.1
|
||||||
|
- 1.2
|
||||||
|
- 1.3
|
||||||
|
- 1.4
|
||||||
|
- 1.5
|
||||||
|
- 1.6
|
||||||
|
- 1.7
|
||||||
|
- tip
|
41
vendor/github.com/emirpasic/gods/LICENSE
generated
vendored
Normal file
41
vendor/github.com/emirpasic/gods/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
Copyright (c) 2015, Emir Pasic
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
AVL Tree:
|
||||||
|
|
||||||
|
Copyright (c) 2017 Benjamin Scher Purcell <benjapurcell@gmail.com>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
1436
vendor/github.com/emirpasic/gods/README.md
generated
vendored
Normal file
1436
vendor/github.com/emirpasic/gods/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
35
vendor/github.com/emirpasic/gods/containers/containers.go
generated
vendored
Normal file
35
vendor/github.com/emirpasic/gods/containers/containers.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package containers provides core interfaces and functions for data structures.
|
||||||
|
//
|
||||||
|
// Container is the base interface for all data structures to implement.
|
||||||
|
//
|
||||||
|
// Iterators provide stateful iterators.
|
||||||
|
//
|
||||||
|
// Enumerable provides Ruby inspired (each, select, map, find, any?, etc.) container functions.
|
||||||
|
//
|
||||||
|
// Serialization provides serializers (marshalers) and deserializers (unmarshalers).
|
||||||
|
package containers
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/utils"
|
||||||
|
|
||||||
|
// Container is base interface that all data structures implement.
|
||||||
|
type Container interface {
|
||||||
|
Empty() bool
|
||||||
|
Size() int
|
||||||
|
Clear()
|
||||||
|
Values() []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSortedValues returns sorted container's elements with respect to the passed comparator.
|
||||||
|
// Does not effect the ordering of elements within the container.
|
||||||
|
func GetSortedValues(container Container, comparator utils.Comparator) []interface{} {
|
||||||
|
values := container.Values()
|
||||||
|
if len(values) < 2 {
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
utils.Sort(values, comparator)
|
||||||
|
return values
|
||||||
|
}
|
55
vendor/github.com/emirpasic/gods/containers/containers_test.go
generated
vendored
Normal file
55
vendor/github.com/emirpasic/gods/containers/containers_test.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// All data structures must implement the container structure
|
||||||
|
|
||||||
|
package containers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// For testing purposes
|
||||||
|
type ContainerTest struct {
|
||||||
|
values []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (container ContainerTest) Empty() bool {
|
||||||
|
return len(container.values) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (container ContainerTest) Size() int {
|
||||||
|
return len(container.values)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (container ContainerTest) Clear() {
|
||||||
|
container.values = []interface{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (container ContainerTest) Values() []interface{} {
|
||||||
|
return container.values
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetSortedValuesInts(t *testing.T) {
|
||||||
|
container := ContainerTest{}
|
||||||
|
container.values = []interface{}{5, 1, 3, 2, 4}
|
||||||
|
values := GetSortedValues(container, utils.IntComparator)
|
||||||
|
for i := 1; i < container.Size(); i++ {
|
||||||
|
if values[i-1].(int) > values[i].(int) {
|
||||||
|
t.Errorf("Not sorted!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetSortedValuesStrings(t *testing.T) {
|
||||||
|
container := ContainerTest{}
|
||||||
|
container.values = []interface{}{"g", "a", "d", "e", "f", "c", "b"}
|
||||||
|
values := GetSortedValues(container, utils.StringComparator)
|
||||||
|
for i := 1; i < container.Size(); i++ {
|
||||||
|
if values[i-1].(string) > values[i].(string) {
|
||||||
|
t.Errorf("Not sorted!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
vendor/github.com/emirpasic/gods/containers/enumerable.go
generated
vendored
Normal file
61
vendor/github.com/emirpasic/gods/containers/enumerable.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package containers
|
||||||
|
|
||||||
|
// EnumerableWithIndex provides functions for ordered containers whose values can be fetched by an index.
|
||||||
|
type EnumerableWithIndex interface {
|
||||||
|
// Each calls the given function once for each element, passing that element's index and value.
|
||||||
|
Each(func(index int, value interface{}))
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a
|
||||||
|
// container containing the values returned by the given function.
|
||||||
|
// TODO need help on how to enforce this in containers (don't want to type assert when chaining)
|
||||||
|
// Map(func(index int, value interface{}) interface{}) Container
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
// TODO need help on how to enforce this in containers (don't want to type assert when chaining)
|
||||||
|
// Select(func(index int, value interface{}) bool) Container
|
||||||
|
|
||||||
|
// Any passes each element of the container to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
Any(func(index int, value interface{}) bool) bool
|
||||||
|
|
||||||
|
// All passes each element of the container to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
All(func(index int, value interface{}) bool) bool
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (index,value) for which the function is true or -1,nil otherwise
|
||||||
|
// if no element matches the criteria.
|
||||||
|
Find(func(index int, value interface{}) bool) (int, interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnumerableWithKey provides functions for ordered containers whose values whose elements are key/value pairs.
|
||||||
|
type EnumerableWithKey interface {
|
||||||
|
// Each calls the given function once for each element, passing that element's key and value.
|
||||||
|
Each(func(key interface{}, value interface{}))
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a container
|
||||||
|
// containing the values returned by the given function as key/value pairs.
|
||||||
|
// TODO need help on how to enforce this in containers (don't want to type assert when chaining)
|
||||||
|
// Map(func(key interface{}, value interface{}) (interface{}, interface{})) Container
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
// TODO need help on how to enforce this in containers (don't want to type assert when chaining)
|
||||||
|
// Select(func(key interface{}, value interface{}) bool) Container
|
||||||
|
|
||||||
|
// Any passes each element of the container to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
Any(func(key interface{}, value interface{}) bool) bool
|
||||||
|
|
||||||
|
// All passes each element of the container to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
All(func(key interface{}, value interface{}) bool) bool
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (key,value) for which the function is true or nil,nil otherwise if no element
|
||||||
|
// matches the criteria.
|
||||||
|
Find(func(key interface{}, value interface{}) bool) (interface{}, interface{})
|
||||||
|
}
|
109
vendor/github.com/emirpasic/gods/containers/iterator.go
generated
vendored
Normal file
109
vendor/github.com/emirpasic/gods/containers/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package containers
|
||||||
|
|
||||||
|
// IteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index.
|
||||||
|
type IteratorWithIndex interface {
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
Next() bool
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
Value() interface{}
|
||||||
|
|
||||||
|
// Index returns the current element's index.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
Index() int
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
Begin()
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
First() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs.
|
||||||
|
type IteratorWithKey interface {
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
Next() bool
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
Value() interface{}
|
||||||
|
|
||||||
|
// Key returns the current element's key.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
Key() interface{}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
Begin()
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
First() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index.
|
||||||
|
//
|
||||||
|
// Essentially it is the same as IteratorWithIndex, but provides additional:
|
||||||
|
//
|
||||||
|
// Prev() function to enable traversal in reverse
|
||||||
|
//
|
||||||
|
// Last() function to move the iterator to the last element.
|
||||||
|
//
|
||||||
|
// End() function to move the iterator past the last element (one-past-the-end).
|
||||||
|
type ReverseIteratorWithIndex interface {
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
Prev() bool
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
End()
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
Last() bool
|
||||||
|
|
||||||
|
IteratorWithIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReverseIteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs.
|
||||||
|
//
|
||||||
|
// Essentially it is the same as IteratorWithKey, but provides additional:
|
||||||
|
//
|
||||||
|
// Prev() function to enable traversal in reverse
|
||||||
|
//
|
||||||
|
// Last() function to move the iterator to the last element.
|
||||||
|
type ReverseIteratorWithKey interface {
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
Prev() bool
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
End()
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
Last() bool
|
||||||
|
|
||||||
|
IteratorWithKey
|
||||||
|
}
|
17
vendor/github.com/emirpasic/gods/containers/serialization.go
generated
vendored
Normal file
17
vendor/github.com/emirpasic/gods/containers/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package containers
|
||||||
|
|
||||||
|
// JSONSerializer provides JSON serialization
|
||||||
|
type JSONSerializer interface {
|
||||||
|
// ToJSON outputs the JSON representation of containers's elements.
|
||||||
|
ToJSON() ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONDeserializer provides JSON deserialization
|
||||||
|
type JSONDeserializer interface {
|
||||||
|
// FromJSON populates containers's elements from the input JSON representation.
|
||||||
|
FromJSON([]byte) error
|
||||||
|
}
|
31
vendor/github.com/emirpasic/gods/examples/arraylist.go
generated
vendored
Normal file
31
vendor/github.com/emirpasic/gods/examples/arraylist.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/lists/arraylist"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ArrayListExample to demonstrate basic usage of ArrayList
|
||||||
|
func ArrayListExample() {
|
||||||
|
list := arraylist.New()
|
||||||
|
list.Add("a") // ["a"]
|
||||||
|
list.Add("c", "b") // ["a","c","b"]
|
||||||
|
list.Sort(utils.StringComparator) // ["a","b","c"]
|
||||||
|
_, _ = list.Get(0) // "a",true
|
||||||
|
_, _ = list.Get(100) // nil,false
|
||||||
|
_ = list.Contains("a", "b", "c") // true
|
||||||
|
_ = list.Contains("a", "b", "c", "d") // false
|
||||||
|
list.Swap(0, 1) // ["b","a",c"]
|
||||||
|
list.Remove(2) // ["b","a"]
|
||||||
|
list.Remove(1) // ["b"]
|
||||||
|
list.Remove(0) // []
|
||||||
|
list.Remove(0) // [] (ignored)
|
||||||
|
_ = list.Empty() // true
|
||||||
|
_ = list.Size() // 0
|
||||||
|
list.Add("a") // ["a"]
|
||||||
|
list.Clear() // []
|
||||||
|
}
|
23
vendor/github.com/emirpasic/gods/examples/arraystack.go
generated
vendored
Normal file
23
vendor/github.com/emirpasic/gods/examples/arraystack.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/stacks/arraystack"
|
||||||
|
|
||||||
|
// ArrayStackExample to demonstrate basic usage of ArrayStack
|
||||||
|
func ArrayStackExample() {
|
||||||
|
stack := arraystack.New() // empty
|
||||||
|
stack.Push(1) // 1
|
||||||
|
stack.Push(2) // 1, 2
|
||||||
|
stack.Values() // 2, 1 (LIFO order)
|
||||||
|
_, _ = stack.Peek() // 2,true
|
||||||
|
_, _ = stack.Pop() // 2, true
|
||||||
|
_, _ = stack.Pop() // 1, true
|
||||||
|
_, _ = stack.Pop() // nil, false (nothing to pop)
|
||||||
|
stack.Push(1) // 1
|
||||||
|
stack.Clear() // empty
|
||||||
|
stack.Empty() // true
|
||||||
|
stack.Size() // 0
|
||||||
|
}
|
50
vendor/github.com/emirpasic/gods/examples/avltree.go
generated
vendored
Normal file
50
vendor/github.com/emirpasic/gods/examples/avltree.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
avl "github.com/emirpasic/gods/trees/avltree"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AVLTreeExample to demonstrate basic usage of AVLTree
|
||||||
|
func AVLTreeExample() {
|
||||||
|
tree := avl.NewWithIntComparator() // empty(keys are of type int)
|
||||||
|
|
||||||
|
tree.Put(1, "x") // 1->x
|
||||||
|
tree.Put(2, "b") // 1->x, 2->b (in order)
|
||||||
|
tree.Put(1, "a") // 1->a, 2->b (in order, replacement)
|
||||||
|
tree.Put(3, "c") // 1->a, 2->b, 3->c (in order)
|
||||||
|
tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order)
|
||||||
|
tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order)
|
||||||
|
tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order)
|
||||||
|
|
||||||
|
fmt.Println(tree)
|
||||||
|
//
|
||||||
|
// AVLTree
|
||||||
|
// │ ┌── 6
|
||||||
|
// │ ┌── 5
|
||||||
|
// └── 4
|
||||||
|
// │ ┌── 3
|
||||||
|
// └── 2
|
||||||
|
// └── 1
|
||||||
|
|
||||||
|
_ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f"} (in order)
|
||||||
|
_ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6} (in order)
|
||||||
|
|
||||||
|
tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order)
|
||||||
|
fmt.Println(tree)
|
||||||
|
//
|
||||||
|
// AVLTree
|
||||||
|
// │ ┌── 6
|
||||||
|
// │ ┌── 5
|
||||||
|
// └── 4
|
||||||
|
// └── 3
|
||||||
|
// └── 1
|
||||||
|
|
||||||
|
tree.Clear() // empty
|
||||||
|
tree.Empty() // true
|
||||||
|
tree.Size() // 0
|
||||||
|
}
|
40
vendor/github.com/emirpasic/gods/examples/binaryheap.go
generated
vendored
Normal file
40
vendor/github.com/emirpasic/gods/examples/binaryheap.go
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/trees/binaryheap"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BinaryHeapExample to demonstrate basic usage of BinaryHeap
|
||||||
|
func BinaryHeapExample() {
|
||||||
|
|
||||||
|
// Min-heap
|
||||||
|
heap := binaryheap.NewWithIntComparator() // empty (min-heap)
|
||||||
|
heap.Push(2) // 2
|
||||||
|
heap.Push(3) // 2, 3
|
||||||
|
heap.Push(1) // 1, 3, 2
|
||||||
|
heap.Values() // 1, 3, 2
|
||||||
|
_, _ = heap.Peek() // 1,true
|
||||||
|
_, _ = heap.Pop() // 1, true
|
||||||
|
_, _ = heap.Pop() // 2, true
|
||||||
|
_, _ = heap.Pop() // 3, true
|
||||||
|
_, _ = heap.Pop() // nil, false (nothing to pop)
|
||||||
|
heap.Push(1) // 1
|
||||||
|
heap.Clear() // empty
|
||||||
|
heap.Empty() // true
|
||||||
|
heap.Size() // 0
|
||||||
|
|
||||||
|
// Max-heap
|
||||||
|
inverseIntComparator := func(a, b interface{}) int {
|
||||||
|
return -utils.IntComparator(a, b)
|
||||||
|
}
|
||||||
|
heap = binaryheap.NewWith(inverseIntComparator) // empty (min-heap)
|
||||||
|
heap.Push(2) // 2
|
||||||
|
heap.Push(3) // 3, 2
|
||||||
|
heap.Push(1) // 3, 2, 1
|
||||||
|
heap.Values() // 3, 2, 1
|
||||||
|
}
|
59
vendor/github.com/emirpasic/gods/examples/btree.go
generated
vendored
Normal file
59
vendor/github.com/emirpasic/gods/examples/btree.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/trees/btree"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BTreeExample to demonstrate basic usage of BTree
|
||||||
|
func BTreeExample() {
|
||||||
|
tree := btree.NewWithIntComparator(3) // empty (keys are of type int)
|
||||||
|
|
||||||
|
tree.Put(1, "x") // 1->x
|
||||||
|
tree.Put(2, "b") // 1->x, 2->b (in order)
|
||||||
|
tree.Put(1, "a") // 1->a, 2->b (in order, replacement)
|
||||||
|
tree.Put(3, "c") // 1->a, 2->b, 3->c (in order)
|
||||||
|
tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order)
|
||||||
|
tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order)
|
||||||
|
tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order)
|
||||||
|
tree.Put(7, "g") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f, 7->g (in order)
|
||||||
|
|
||||||
|
fmt.Println(tree)
|
||||||
|
// BTree
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
// 4
|
||||||
|
// 5
|
||||||
|
// 6
|
||||||
|
// 7
|
||||||
|
|
||||||
|
_ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f", "g"} (in order)
|
||||||
|
_ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6, 7} (in order)
|
||||||
|
|
||||||
|
tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order)
|
||||||
|
fmt.Println(tree)
|
||||||
|
// BTree
|
||||||
|
// 1
|
||||||
|
// 3
|
||||||
|
// 4
|
||||||
|
// 5
|
||||||
|
// 6
|
||||||
|
|
||||||
|
tree.Clear() // empty
|
||||||
|
tree.Empty() // true
|
||||||
|
tree.Size() // 0
|
||||||
|
|
||||||
|
// Other:
|
||||||
|
tree.Height() // gets the height of the tree
|
||||||
|
tree.Left() // gets the left-most (min) node
|
||||||
|
tree.LeftKey() // get the left-most (min) node's key
|
||||||
|
tree.LeftValue() // get the left-most (min) node's value
|
||||||
|
tree.Right() // get the right-most (max) node
|
||||||
|
tree.RightKey() // get the right-most (max) node's key
|
||||||
|
tree.RightValue() // get the right-most (max) node's value
|
||||||
|
}
|
45
vendor/github.com/emirpasic/gods/examples/customcomparator.go
generated
vendored
Normal file
45
vendor/github.com/emirpasic/gods/examples/customcomparator.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/sets/treeset"
|
||||||
|
)
|
||||||
|
|
||||||
|
// User model (id and name)
|
||||||
|
type User struct {
|
||||||
|
id int
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comparator function (sort by IDs)
|
||||||
|
func byID(a, b interface{}) int {
|
||||||
|
|
||||||
|
// Type assertion, program will panic if this is not respected
|
||||||
|
c1 := a.(User)
|
||||||
|
c2 := b.(User)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case c1.id > c2.id:
|
||||||
|
return 1
|
||||||
|
case c1.id < c2.id:
|
||||||
|
return -1
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomComparatorExample to demonstrate basic usage of CustomComparator
|
||||||
|
func CustomComparatorExample() {
|
||||||
|
set := treeset.NewWith(byID)
|
||||||
|
|
||||||
|
set.Add(User{2, "Second"})
|
||||||
|
set.Add(User{3, "Third"})
|
||||||
|
set.Add(User{1, "First"})
|
||||||
|
set.Add(User{4, "Fourth"})
|
||||||
|
|
||||||
|
fmt.Println(set) // {1 First}, {2 Second}, {3 Third}, {4 Fourth}
|
||||||
|
}
|
31
vendor/github.com/emirpasic/gods/examples/doublylinkedlist.go
generated
vendored
Normal file
31
vendor/github.com/emirpasic/gods/examples/doublylinkedlist.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
dll "github.com/emirpasic/gods/lists/doublylinkedlist"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DoublyLinkedListExample to demonstrate basic usage of DoublyLinkedList
|
||||||
|
func DoublyLinkedListExample() {
|
||||||
|
list := dll.New()
|
||||||
|
list.Add("a") // ["a"]
|
||||||
|
list.Append("b") // ["a","b"] (same as Add())
|
||||||
|
list.Prepend("c") // ["c","a","b"]
|
||||||
|
list.Sort(utils.StringComparator) // ["a","b","c"]
|
||||||
|
_, _ = list.Get(0) // "a",true
|
||||||
|
_, _ = list.Get(100) // nil,false
|
||||||
|
_ = list.Contains("a", "b", "c") // true
|
||||||
|
_ = list.Contains("a", "b", "c", "d") // false
|
||||||
|
list.Remove(2) // ["a","b"]
|
||||||
|
list.Remove(1) // ["a"]
|
||||||
|
list.Remove(0) // []
|
||||||
|
list.Remove(0) // [] (ignored)
|
||||||
|
_ = list.Empty() // true
|
||||||
|
_ = list.Size() // 0
|
||||||
|
list.Add("a") // ["a"]
|
||||||
|
list.Clear() // []
|
||||||
|
}
|
59
vendor/github.com/emirpasic/gods/examples/enumerablewithindex.go
generated
vendored
Normal file
59
vendor/github.com/emirpasic/gods/examples/enumerablewithindex.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/sets/treeset"
|
||||||
|
)
|
||||||
|
|
||||||
|
func printSet(txt string, set *treeset.Set) {
|
||||||
|
fmt.Print(txt, "[ ")
|
||||||
|
set.Each(func(index int, value interface{}) {
|
||||||
|
fmt.Print(value, " ")
|
||||||
|
})
|
||||||
|
fmt.Println("]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnumerableWithIndexExample to demonstrate basic usage of EnumerableWithIndex
|
||||||
|
func EnumerableWithIndexExample() {
|
||||||
|
set := treeset.NewWithIntComparator()
|
||||||
|
set.Add(2, 3, 4, 2, 5, 6, 7, 8)
|
||||||
|
printSet("Initial", set) // [ 2 3 4 5 6 7 8 ]
|
||||||
|
|
||||||
|
even := set.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(int)%2 == 0
|
||||||
|
})
|
||||||
|
printSet("Even numbers", even) // [ 2 4 6 8 ]
|
||||||
|
|
||||||
|
foundIndex, foundValue := set.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(int)%2 == 0 && value.(int)%3 == 0
|
||||||
|
})
|
||||||
|
if foundIndex != -1 {
|
||||||
|
fmt.Println("Number divisible by 2 and 3 found is", foundValue, "at index", foundIndex) // value: 6, index: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
square := set.Map(func(index int, value interface{}) interface{} {
|
||||||
|
return value.(int) * value.(int)
|
||||||
|
})
|
||||||
|
printSet("Numbers squared", square) // [ 4 9 16 25 36 49 64 ]
|
||||||
|
|
||||||
|
bigger := set.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(int) > 5
|
||||||
|
})
|
||||||
|
fmt.Println("Set contains a number bigger than 5 is ", bigger) // true
|
||||||
|
|
||||||
|
positive := set.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(int) > 0
|
||||||
|
})
|
||||||
|
fmt.Println("All numbers are positive is", positive) // true
|
||||||
|
|
||||||
|
evenNumbersSquared := set.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(int)%2 == 0
|
||||||
|
}).Map(func(index int, value interface{}) interface{} {
|
||||||
|
return value.(int) * value.(int)
|
||||||
|
})
|
||||||
|
printSet("Chaining", evenNumbersSquared) // [ 4 16 36 64 ]
|
||||||
|
}
|
65
vendor/github.com/emirpasic/gods/examples/enumerablewithkey.go
generated
vendored
Normal file
65
vendor/github.com/emirpasic/gods/examples/enumerablewithkey.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/maps/treemap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func printMap(txt string, m *treemap.Map) {
|
||||||
|
fmt.Print(txt, " { ")
|
||||||
|
m.Each(func(key interface{}, value interface{}) {
|
||||||
|
fmt.Print(key, ":", value, " ")
|
||||||
|
})
|
||||||
|
fmt.Println("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// EunumerableWithKeyExample to demonstrate basic usage of EunumerableWithKey
|
||||||
|
func EunumerableWithKeyExample() {
|
||||||
|
m := treemap.NewWithStringComparator()
|
||||||
|
m.Put("g", 7)
|
||||||
|
m.Put("f", 6)
|
||||||
|
m.Put("e", 5)
|
||||||
|
m.Put("d", 4)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("b", 2)
|
||||||
|
m.Put("a", 1)
|
||||||
|
printMap("Initial", m) // { a:1 b:2 c:3 d:4 e:5 f:6 g:7 }
|
||||||
|
|
||||||
|
even := m.Select(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int)%2 == 0
|
||||||
|
})
|
||||||
|
printMap("Elements with even values", even) // { b:2 d:4 f:6 }
|
||||||
|
|
||||||
|
foundKey, foundValue := m.Find(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int)%2 == 0 && value.(int)%3 == 0
|
||||||
|
})
|
||||||
|
if foundKey != nil {
|
||||||
|
fmt.Println("Element with value divisible by 2 and 3 found is", foundValue, "with key", foundKey) // value: 6, index: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
square := m.Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
|
||||||
|
return key.(string) + key.(string), value.(int) * value.(int)
|
||||||
|
})
|
||||||
|
printMap("Elements' values squared and letters duplicated", square) // { aa:1 bb:4 cc:9 dd:16 ee:25 ff:36 gg:49 }
|
||||||
|
|
||||||
|
bigger := m.Any(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) > 5
|
||||||
|
})
|
||||||
|
fmt.Println("Map contains element whose value is bigger than 5 is", bigger) // true
|
||||||
|
|
||||||
|
positive := m.All(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) > 0
|
||||||
|
})
|
||||||
|
fmt.Println("All map's elements have positive values is", positive) // true
|
||||||
|
|
||||||
|
evenNumbersSquared := m.Select(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int)%2 == 0
|
||||||
|
}).Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
|
||||||
|
return key, value.(int) * value.(int)
|
||||||
|
})
|
||||||
|
printMap("Chaining", evenNumbersSquared) // { b:4 d:16 f:36 }
|
||||||
|
}
|
25
vendor/github.com/emirpasic/gods/examples/hashbidimap.go
generated
vendored
Normal file
25
vendor/github.com/emirpasic/gods/examples/hashbidimap.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/maps/hashbidimap"
|
||||||
|
|
||||||
|
// HashBidiMapExample to demonstrate basic usage of HashMap
|
||||||
|
func HashBidiMapExample() {
|
||||||
|
m := hashbidimap.New() // empty
|
||||||
|
m.Put(1, "x") // 1->x
|
||||||
|
m.Put(3, "b") // 1->x, 3->b (random order)
|
||||||
|
m.Put(1, "a") // 1->a, 3->b (random order)
|
||||||
|
m.Put(2, "b") // 1->a, 2->b (random order)
|
||||||
|
_, _ = m.GetKey("a") // 1, true
|
||||||
|
_, _ = m.Get(2) // b, true
|
||||||
|
_, _ = m.Get(3) // nil, false
|
||||||
|
_ = m.Values() // []interface {}{"a", "b"} (random order)
|
||||||
|
_ = m.Keys() // []interface {}{1, 2} (random order)
|
||||||
|
m.Remove(1) // 2->b
|
||||||
|
m.Clear() // empty
|
||||||
|
m.Empty() // true
|
||||||
|
m.Size() // 0
|
||||||
|
}
|
23
vendor/github.com/emirpasic/gods/examples/hashmap.go
generated
vendored
Normal file
23
vendor/github.com/emirpasic/gods/examples/hashmap.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/maps/hashmap"
|
||||||
|
|
||||||
|
// HashMapExample to demonstrate basic usage of HashMap
|
||||||
|
func HashMapExample() {
|
||||||
|
m := hashmap.New() // empty
|
||||||
|
m.Put(1, "x") // 1->x
|
||||||
|
m.Put(2, "b") // 2->b, 1->x (random order)
|
||||||
|
m.Put(1, "a") // 2->b, 1->a (random order)
|
||||||
|
_, _ = m.Get(2) // b, true
|
||||||
|
_, _ = m.Get(3) // nil, false
|
||||||
|
_ = m.Values() // []interface {}{"b", "a"} (random order)
|
||||||
|
_ = m.Keys() // []interface {}{1, 2} (random order)
|
||||||
|
m.Remove(1) // 2->b
|
||||||
|
m.Clear() // empty
|
||||||
|
m.Empty() // true
|
||||||
|
m.Size() // 0
|
||||||
|
}
|
23
vendor/github.com/emirpasic/gods/examples/hashset.go
generated
vendored
Normal file
23
vendor/github.com/emirpasic/gods/examples/hashset.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/sets/hashset"
|
||||||
|
|
||||||
|
// HashSetExample to demonstrate basic usage of HashSet
|
||||||
|
func HashSetExample() {
|
||||||
|
set := hashset.New() // empty (keys are of type int)
|
||||||
|
set.Add(1) // 1
|
||||||
|
set.Add(2, 2, 3, 4, 5) // 3, 1, 2, 4, 5 (random order, duplicates ignored)
|
||||||
|
set.Remove(4) // 5, 3, 2, 1 (random order)
|
||||||
|
set.Remove(2, 3) // 1, 5 (random order)
|
||||||
|
set.Contains(1) // true
|
||||||
|
set.Contains(1, 5) // true
|
||||||
|
set.Contains(1, 6) // false
|
||||||
|
_ = set.Values() // []int{5,1} (random order)
|
||||||
|
set.Clear() // empty
|
||||||
|
set.Empty() // true
|
||||||
|
set.Size() // 0
|
||||||
|
}
|
51
vendor/github.com/emirpasic/gods/examples/iteratorwithindex.go
generated
vendored
Normal file
51
vendor/github.com/emirpasic/gods/examples/iteratorwithindex.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/sets/treeset"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IteratorWithIndexExample to demonstrate basic usage of IteratorWithIndex
|
||||||
|
func IteratorWithIndexExample() {
|
||||||
|
set := treeset.NewWithStringComparator()
|
||||||
|
set.Add("a", "b", "c")
|
||||||
|
it := set.Iterator()
|
||||||
|
|
||||||
|
fmt.Print("\nForward iteration\n")
|
||||||
|
for it.Next() {
|
||||||
|
index, value := it.Index(), it.Value()
|
||||||
|
fmt.Print("[", index, ":", value, "]") // [0:a][1:b][2:c]
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("\nForward iteration (again)\n")
|
||||||
|
for it.Begin(); it.Next(); {
|
||||||
|
index, value := it.Index(), it.Value()
|
||||||
|
fmt.Print("[", index, ":", value, "]") // [0:a][1:b][2:c]
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("\nBackward iteration\n")
|
||||||
|
for it.Prev() {
|
||||||
|
index, value := it.Index(), it.Value()
|
||||||
|
fmt.Print("[", index, ":", value, "]") // [2:c][1:b][0:a]
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("\nBackward iteration (again)\n")
|
||||||
|
for it.End(); it.Prev(); {
|
||||||
|
index, value := it.Index(), it.Value()
|
||||||
|
fmt.Print("[", index, ":", value, "]") // [2:c][1:b][0:a]
|
||||||
|
}
|
||||||
|
|
||||||
|
if it.First() {
|
||||||
|
fmt.Print("\nFirst index: ", it.Index()) // First index: 0
|
||||||
|
fmt.Print("\nFirst value: ", it.Value()) // First value: a
|
||||||
|
}
|
||||||
|
|
||||||
|
if it.Last() {
|
||||||
|
fmt.Print("\nLast index: ", it.Index()) // Last index: 3
|
||||||
|
fmt.Print("\nLast value: ", it.Value()) // Last value: c
|
||||||
|
}
|
||||||
|
}
|
53
vendor/github.com/emirpasic/gods/examples/iteratorwithkey.go
generated
vendored
Normal file
53
vendor/github.com/emirpasic/gods/examples/iteratorwithkey.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/maps/treemap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IteratorWithKeyExample to demonstrate basic usage of IteratorWithKey
|
||||||
|
func IteratorWithKeyExample() {
|
||||||
|
m := treemap.NewWithIntComparator()
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(3, "a")
|
||||||
|
it := m.Iterator()
|
||||||
|
|
||||||
|
fmt.Print("\nForward iteration\n")
|
||||||
|
for it.Next() {
|
||||||
|
key, value := it.Key(), it.Value()
|
||||||
|
fmt.Print("[", key, ":", value, "]") // [0:a][1:b][2:c]
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("\nForward iteration (again)\n")
|
||||||
|
for it.Begin(); it.Next(); {
|
||||||
|
key, value := it.Key(), it.Value()
|
||||||
|
fmt.Print("[", key, ":", value, "]") // [0:a][1:b][2:c]
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("\nBackward iteration\n")
|
||||||
|
for it.Prev() {
|
||||||
|
key, value := it.Key(), it.Value()
|
||||||
|
fmt.Print("[", key, ":", value, "]") // [2:c][1:b][0:a]
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("\nBackward iteration (again)\n")
|
||||||
|
for it.End(); it.Prev(); {
|
||||||
|
key, value := it.Key(), it.Value()
|
||||||
|
fmt.Print("[", key, ":", value, "]") // [2:c][1:b][0:a]
|
||||||
|
}
|
||||||
|
|
||||||
|
if it.First() {
|
||||||
|
fmt.Print("\nFirst key: ", it.Key()) // First key: 0
|
||||||
|
fmt.Print("\nFirst value: ", it.Value()) // First value: a
|
||||||
|
}
|
||||||
|
|
||||||
|
if it.Last() {
|
||||||
|
fmt.Print("\nLast key: ", it.Key()) // Last key: 3
|
||||||
|
fmt.Print("\nLast value: ", it.Value()) // Last value: c
|
||||||
|
}
|
||||||
|
}
|
23
vendor/github.com/emirpasic/gods/examples/linkedliststack.go
generated
vendored
Normal file
23
vendor/github.com/emirpasic/gods/examples/linkedliststack.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import lls "github.com/emirpasic/gods/stacks/linkedliststack"
|
||||||
|
|
||||||
|
// LinkedListStackExample to demonstrate basic usage of LinkedListStack
|
||||||
|
func LinkedListStackExample() {
|
||||||
|
stack := lls.New() // empty
|
||||||
|
stack.Push(1) // 1
|
||||||
|
stack.Push(2) // 1, 2
|
||||||
|
stack.Values() // 2, 1 (LIFO order)
|
||||||
|
_, _ = stack.Peek() // 2,true
|
||||||
|
_, _ = stack.Pop() // 2, true
|
||||||
|
_, _ = stack.Pop() // 1, true
|
||||||
|
_, _ = stack.Pop() // nil, false (nothing to pop)
|
||||||
|
stack.Push(1) // 1
|
||||||
|
stack.Clear() // empty
|
||||||
|
stack.Empty() // true
|
||||||
|
stack.Size() // 0
|
||||||
|
}
|
50
vendor/github.com/emirpasic/gods/examples/redblacktree.go
generated
vendored
Normal file
50
vendor/github.com/emirpasic/gods/examples/redblacktree.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RedBlackTreeExample to demonstrate basic usage of RedBlackTree
|
||||||
|
func RedBlackTreeExample() {
|
||||||
|
tree := rbt.NewWithIntComparator() // empty(keys are of type int)
|
||||||
|
|
||||||
|
tree.Put(1, "x") // 1->x
|
||||||
|
tree.Put(2, "b") // 1->x, 2->b (in order)
|
||||||
|
tree.Put(1, "a") // 1->a, 2->b (in order, replacement)
|
||||||
|
tree.Put(3, "c") // 1->a, 2->b, 3->c (in order)
|
||||||
|
tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order)
|
||||||
|
tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order)
|
||||||
|
tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order)
|
||||||
|
|
||||||
|
fmt.Println(tree)
|
||||||
|
//
|
||||||
|
// RedBlackTree
|
||||||
|
// │ ┌── 6
|
||||||
|
// │ ┌── 5
|
||||||
|
// │ ┌── 4
|
||||||
|
// │ │ └── 3
|
||||||
|
// └── 2
|
||||||
|
// └── 1
|
||||||
|
|
||||||
|
_ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f"} (in order)
|
||||||
|
_ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6} (in order)
|
||||||
|
|
||||||
|
tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order)
|
||||||
|
fmt.Println(tree)
|
||||||
|
//
|
||||||
|
// RedBlackTree
|
||||||
|
// │ ┌── 6
|
||||||
|
// │ ┌── 5
|
||||||
|
// └── 4
|
||||||
|
// │ ┌── 3
|
||||||
|
// └── 1
|
||||||
|
|
||||||
|
tree.Clear() // empty
|
||||||
|
tree.Empty() // true
|
||||||
|
tree.Size() // 0
|
||||||
|
}
|
113
vendor/github.com/emirpasic/gods/examples/redblacktreeextended.go
generated
vendored
Normal file
113
vendor/github.com/emirpasic/gods/examples/redblacktreeextended.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RedBlackTreeExtended to demonstrate how to extend a RedBlackTree to include new functions
|
||||||
|
type RedBlackTreeExtended struct {
|
||||||
|
*rbt.Tree
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMin gets the min value and flag if found
|
||||||
|
func (tree *RedBlackTreeExtended) GetMin() (value interface{}, found bool) {
|
||||||
|
node, found := tree.getMinFromNode(tree.Root)
|
||||||
|
if node != nil {
|
||||||
|
return node.Value, found
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMax gets the max value and flag if found
|
||||||
|
func (tree *RedBlackTreeExtended) GetMax() (value interface{}, found bool) {
|
||||||
|
node, found := tree.getMaxFromNode(tree.Root)
|
||||||
|
if node != nil {
|
||||||
|
return node.Value, found
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveMin removes the min value and flag if found
|
||||||
|
func (tree *RedBlackTreeExtended) RemoveMin() (value interface{}, deleted bool) {
|
||||||
|
node, found := tree.getMinFromNode(tree.Root)
|
||||||
|
if found {
|
||||||
|
tree.Remove(node.Key)
|
||||||
|
return node.Value, found
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveMax removes the max value and flag if found
|
||||||
|
func (tree *RedBlackTreeExtended) RemoveMax() (value interface{}, deleted bool) {
|
||||||
|
node, found := tree.getMaxFromNode(tree.Root)
|
||||||
|
if found {
|
||||||
|
tree.Remove(node.Key)
|
||||||
|
return node.Value, found
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *RedBlackTreeExtended) getMinFromNode(node *rbt.Node) (foundNode *rbt.Node, found bool) {
|
||||||
|
if node == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if node.Left == nil {
|
||||||
|
return node, true
|
||||||
|
}
|
||||||
|
return tree.getMinFromNode(node.Left)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *RedBlackTreeExtended) getMaxFromNode(node *rbt.Node) (foundNode *rbt.Node, found bool) {
|
||||||
|
if node == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if node.Right == nil {
|
||||||
|
return node, true
|
||||||
|
}
|
||||||
|
return tree.getMaxFromNode(node.Right)
|
||||||
|
}
|
||||||
|
|
||||||
|
func print(tree *RedBlackTreeExtended) {
|
||||||
|
max, _ := tree.GetMax()
|
||||||
|
min, _ := tree.GetMin()
|
||||||
|
fmt.Printf("Value for max key: %v \n", max)
|
||||||
|
fmt.Printf("Value for min key: %v \n", min)
|
||||||
|
fmt.Println(tree)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RedBlackTreeExtendedExample main method on how to use the custom red-black tree above
|
||||||
|
func RedBlackTreeExtendedExample() {
|
||||||
|
tree := RedBlackTreeExtended{rbt.NewWithIntComparator()}
|
||||||
|
|
||||||
|
tree.Put(1, "a") // 1->x (in order)
|
||||||
|
tree.Put(2, "b") // 1->x, 2->b (in order)
|
||||||
|
tree.Put(3, "c") // 1->x, 2->b, 3->c (in order)
|
||||||
|
tree.Put(4, "d") // 1->x, 2->b, 3->c, 4->d (in order)
|
||||||
|
tree.Put(5, "e") // 1->x, 2->b, 3->c, 4->d, 5->e (in order)
|
||||||
|
|
||||||
|
print(&tree)
|
||||||
|
// Value for max key: e
|
||||||
|
// Value for min key: a
|
||||||
|
// RedBlackTree
|
||||||
|
// │ ┌── 5
|
||||||
|
// │ ┌── 4
|
||||||
|
// │ │ └── 3
|
||||||
|
// └── 2
|
||||||
|
// └── 1
|
||||||
|
|
||||||
|
tree.RemoveMin() // 2->b, 3->c, 4->d, 5->e (in order)
|
||||||
|
tree.RemoveMax() // 2->b, 3->c, 4->d (in order)
|
||||||
|
tree.RemoveMin() // 3->c, 4->d (in order)
|
||||||
|
tree.RemoveMax() // 3->c (in order)
|
||||||
|
|
||||||
|
print(&tree)
|
||||||
|
// Value for max key: c
|
||||||
|
// Value for min key: c
|
||||||
|
// RedBlackTree
|
||||||
|
// └── 3
|
||||||
|
}
|
51
vendor/github.com/emirpasic/gods/examples/serialization.go
generated
vendored
Normal file
51
vendor/github.com/emirpasic/gods/examples/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/lists/arraylist"
|
||||||
|
"github.com/emirpasic/gods/maps/hashmap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListSerializationExample demonstrates how to serialize and deserialize lists to and from JSON
|
||||||
|
func ListSerializationExample() {
|
||||||
|
list := arraylist.New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
|
||||||
|
// Serialization (marshalling)
|
||||||
|
json, err := list.ToJSON()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println(string(json)) // ["a","b","c"]
|
||||||
|
|
||||||
|
// Deserialization (unmarshalling)
|
||||||
|
json = []byte(`["a","b"]`)
|
||||||
|
err = list.FromJSON(json)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println(list) // ArrayList ["a","b"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapSerializationExample demonstrates how to serialize and deserialize maps to and from JSON
|
||||||
|
func MapSerializationExample() {
|
||||||
|
m := hashmap.New()
|
||||||
|
m.Put("a", "1")
|
||||||
|
m.Put("b", "2")
|
||||||
|
m.Put("c", "3")
|
||||||
|
|
||||||
|
// Serialization (marshalling)
|
||||||
|
json, err := m.ToJSON()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println(string(json)) // {"a":"1","b":"2","c":"3"}
|
||||||
|
|
||||||
|
// Deserialization (unmarshalling)
|
||||||
|
json = []byte(`{"a":"1","b":"2"}`)
|
||||||
|
err = m.FromJSON(json)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println(m) // HashMap {"a":"1","b":"2"}
|
||||||
|
}
|
31
vendor/github.com/emirpasic/gods/examples/singlylinkedlist.go
generated
vendored
Normal file
31
vendor/github.com/emirpasic/gods/examples/singlylinkedlist.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
sll "github.com/emirpasic/gods/lists/singlylinkedlist"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SinglyLinkedListExample to demonstrate basic usage of SinglyLinkedList
|
||||||
|
func SinglyLinkedListExample() {
|
||||||
|
list := sll.New()
|
||||||
|
list.Add("a") // ["a"]
|
||||||
|
list.Append("b") // ["a","b"] (same as Add())
|
||||||
|
list.Prepend("c") // ["c","a","b"]
|
||||||
|
list.Sort(utils.StringComparator) // ["a","b","c"]
|
||||||
|
_, _ = list.Get(0) // "a",true
|
||||||
|
_, _ = list.Get(100) // nil,false
|
||||||
|
_ = list.Contains("a", "b", "c") // true
|
||||||
|
_ = list.Contains("a", "b", "c", "d") // false
|
||||||
|
list.Remove(2) // ["a","b"]
|
||||||
|
list.Remove(1) // ["a"]
|
||||||
|
list.Remove(0) // []
|
||||||
|
list.Remove(0) // [] (ignored)
|
||||||
|
_ = list.Empty() // true
|
||||||
|
_ = list.Size() // 0
|
||||||
|
list.Add("a") // ["a"]
|
||||||
|
list.Clear() // []
|
||||||
|
}
|
17
vendor/github.com/emirpasic/gods/examples/sort.go
generated
vendored
Normal file
17
vendor/github.com/emirpasic/gods/examples/sort.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/utils"
|
||||||
|
|
||||||
|
// SortExample to demonstrate basic usage of basic sort
|
||||||
|
func SortExample() {
|
||||||
|
strings := []interface{}{} // []
|
||||||
|
strings = append(strings, "d") // ["d"]
|
||||||
|
strings = append(strings, "a") // ["d","a"]
|
||||||
|
strings = append(strings, "b") // ["d","a",b"
|
||||||
|
strings = append(strings, "c") // ["d","a",b","c"]
|
||||||
|
utils.Sort(strings, utils.StringComparator) // ["a","b","c","d"]
|
||||||
|
}
|
28
vendor/github.com/emirpasic/gods/examples/treebidimap.go
generated
vendored
Normal file
28
vendor/github.com/emirpasic/gods/examples/treebidimap.go
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/maps/treebidimap"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TreeBidiMapExample to demonstrate basic usage of TreeBidiMap
|
||||||
|
func TreeBidiMapExample() {
|
||||||
|
m := treebidimap.NewWith(utils.IntComparator, utils.StringComparator)
|
||||||
|
m.Put(1, "x") // 1->x
|
||||||
|
m.Put(3, "b") // 1->x, 3->b (ordered)
|
||||||
|
m.Put(1, "a") // 1->a, 3->b (ordered)
|
||||||
|
m.Put(2, "b") // 1->a, 2->b (ordered)
|
||||||
|
_, _ = m.GetKey("a") // 1, true
|
||||||
|
_, _ = m.Get(2) // b, true
|
||||||
|
_, _ = m.Get(3) // nil, false
|
||||||
|
_ = m.Values() // []interface {}{"a", "b"} (ordered)
|
||||||
|
_ = m.Keys() // []interface {}{1, 2} (ordered)
|
||||||
|
m.Remove(1) // 2->b
|
||||||
|
m.Clear() // empty
|
||||||
|
m.Empty() // true
|
||||||
|
m.Size() // 0
|
||||||
|
}
|
23
vendor/github.com/emirpasic/gods/examples/treemap.go
generated
vendored
Normal file
23
vendor/github.com/emirpasic/gods/examples/treemap.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/maps/treemap"
|
||||||
|
|
||||||
|
// TreeMapExample to demonstrate basic usage of TreeMap
|
||||||
|
func TreeMapExample() {
|
||||||
|
m := treemap.NewWithIntComparator() // empty (keys are of type int)
|
||||||
|
m.Put(1, "x") // 1->x
|
||||||
|
m.Put(2, "b") // 1->x, 2->b (in order)
|
||||||
|
m.Put(1, "a") // 1->a, 2->b (in order)
|
||||||
|
_, _ = m.Get(2) // b, true
|
||||||
|
_, _ = m.Get(3) // nil, false
|
||||||
|
_ = m.Values() // []interface {}{"a", "b"} (in order)
|
||||||
|
_ = m.Keys() // []interface {}{1, 2} (in order)
|
||||||
|
m.Remove(1) // 2->b
|
||||||
|
m.Clear() // empty
|
||||||
|
m.Empty() // true
|
||||||
|
m.Size() // 0
|
||||||
|
}
|
23
vendor/github.com/emirpasic/gods/examples/treeset.go
generated
vendored
Normal file
23
vendor/github.com/emirpasic/gods/examples/treeset.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/sets/treeset"
|
||||||
|
|
||||||
|
// TreeSetExample to demonstrate basic usage of TreeSet
|
||||||
|
func TreeSetExample() {
|
||||||
|
set := treeset.NewWithIntComparator() // empty
|
||||||
|
set.Add(1) // 1
|
||||||
|
set.Add(2, 2, 3, 4, 5) // 1, 2, 3, 4, 5 (in order, duplicates ignored)
|
||||||
|
set.Remove(4) // 1, 2, 3, 5 (in order)
|
||||||
|
set.Remove(2, 3) // 1, 5 (in order)
|
||||||
|
set.Contains(1) // true
|
||||||
|
set.Contains(1, 5) // true
|
||||||
|
set.Contains(1, 6) // false
|
||||||
|
_ = set.Values() // []int{1,5} (in order)
|
||||||
|
set.Clear() // empty
|
||||||
|
set.Empty() // true
|
||||||
|
set.Size() // 0
|
||||||
|
}
|
200
vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go
generated
vendored
Normal file
200
vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go
generated
vendored
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package arraylist implements the array list.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29
|
||||||
|
package arraylist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/lists"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertListImplementation() {
|
||||||
|
var _ lists.List = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// List holds the elements in a slice
|
||||||
|
type List struct {
|
||||||
|
elements []interface{}
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
growthFactor = float32(2.0) // growth by 100%
|
||||||
|
shrinkFactor = float32(0.25) // shrink when size is 25% of capacity (0 means never shrink)
|
||||||
|
)
|
||||||
|
|
||||||
|
// New instantiates a new empty list
|
||||||
|
func New() *List {
|
||||||
|
return &List{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add appends a value at the end of the list
|
||||||
|
func (list *List) Add(values ...interface{}) {
|
||||||
|
list.growBy(len(values))
|
||||||
|
for _, value := range values {
|
||||||
|
list.elements[list.size] = value
|
||||||
|
list.size++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the element at index.
|
||||||
|
// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false.
|
||||||
|
func (list *List) Get(index int) (interface{}, bool) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.elements[index], true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes one or more elements from the list with the supplied indices.
|
||||||
|
func (list *List) Remove(index int) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list.elements[index] = nil // cleanup reference
|
||||||
|
copy(list.elements[index:], list.elements[index+1:list.size]) // shift to the left by one (slow operation, need ways to optimize this)
|
||||||
|
list.size--
|
||||||
|
|
||||||
|
list.shrink()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains checks if elements (one or more) are present in the set.
|
||||||
|
// All elements have to be present in the set for the method to return true.
|
||||||
|
// Performance time complexity of n^2.
|
||||||
|
// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set.
|
||||||
|
func (list *List) Contains(values ...interface{}) bool {
|
||||||
|
|
||||||
|
for _, searchValue := range values {
|
||||||
|
found := false
|
||||||
|
for _, element := range list.elements {
|
||||||
|
if element == searchValue {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all elements in the list.
|
||||||
|
func (list *List) Values() []interface{} {
|
||||||
|
newElements := make([]interface{}, list.size, list.size)
|
||||||
|
copy(newElements, list.elements[:list.size])
|
||||||
|
return newElements
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if list does not contain any elements.
|
||||||
|
func (list *List) Empty() bool {
|
||||||
|
return list.size == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements within the list.
|
||||||
|
func (list *List) Size() int {
|
||||||
|
return list.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the list.
|
||||||
|
func (list *List) Clear() {
|
||||||
|
list.size = 0
|
||||||
|
list.elements = []interface{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort sorts values (in-place) using.
|
||||||
|
func (list *List) Sort(comparator utils.Comparator) {
|
||||||
|
if len(list.elements) < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
utils.Sort(list.elements[:list.size], comparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap swaps the two values at the specified positions.
|
||||||
|
func (list *List) Swap(i, j int) {
|
||||||
|
if list.withinRange(i) && list.withinRange(j) {
|
||||||
|
list.elements[i], list.elements[j] = list.elements[j], list.elements[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right.
|
||||||
|
// Does not do anything if position is negative or bigger than list's size
|
||||||
|
// Note: position equal to list's size is valid, i.e. append.
|
||||||
|
func (list *List) Insert(index int, values ...interface{}) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
// Append
|
||||||
|
if index == list.size {
|
||||||
|
list.Add(values...)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := len(values)
|
||||||
|
list.growBy(l)
|
||||||
|
list.size += l
|
||||||
|
// Shift old to right
|
||||||
|
for i := list.size - 1; i >= index+l; i-- {
|
||||||
|
list.elements[i] = list.elements[i-l]
|
||||||
|
}
|
||||||
|
// Insert new
|
||||||
|
for i, value := range values {
|
||||||
|
list.elements[index+i] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (list *List) String() string {
|
||||||
|
str := "ArrayList\n"
|
||||||
|
values := []string{}
|
||||||
|
for _, value := range list.elements[:list.size] {
|
||||||
|
values = append(values, fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
|
str += strings.Join(values, ", ")
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the index is within bounds of the list
|
||||||
|
func (list *List) withinRange(index int) bool {
|
||||||
|
return index >= 0 && index < list.size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *List) resize(cap int) {
|
||||||
|
newElements := make([]interface{}, cap, cap)
|
||||||
|
copy(newElements, list.elements)
|
||||||
|
list.elements = newElements
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand the array if necessary, i.e. capacity will be reached if we add n elements
|
||||||
|
func (list *List) growBy(n int) {
|
||||||
|
// When capacity is reached, grow by a factor of growthFactor and add number of elements
|
||||||
|
currentCapacity := cap(list.elements)
|
||||||
|
if list.size+n >= currentCapacity {
|
||||||
|
newCapacity := int(growthFactor * float32(currentCapacity+n))
|
||||||
|
list.resize(newCapacity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shrink the array if necessary, i.e. when size is shrinkFactor percent of current capacity
|
||||||
|
func (list *List) shrink() {
|
||||||
|
if shrinkFactor == 0.0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Shrink when size is at shrinkFactor * capacity
|
||||||
|
currentCapacity := cap(list.elements)
|
||||||
|
if list.size <= int(float32(currentCapacity)*shrinkFactor) {
|
||||||
|
list.resize(list.size)
|
||||||
|
}
|
||||||
|
}
|
606
vendor/github.com/emirpasic/gods/lists/arraylist/arraylist_test.go
generated
vendored
Normal file
606
vendor/github.com/emirpasic/gods/lists/arraylist/arraylist_test.go
generated
vendored
Normal file
|
@ -0,0 +1,606 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package arraylist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestListAdd(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue := list.Empty(); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListRemove(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
list.Remove(2)
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
list.Remove(1)
|
||||||
|
list.Remove(0)
|
||||||
|
list.Remove(0) // no effect
|
||||||
|
if actualValue := list.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListGet(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "a" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "a")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(1); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(3); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
list.Remove(0)
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSwap(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
list.Swap(0, 1)
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSort(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Sort(utils.StringComparator)
|
||||||
|
list.Add("e", "f", "g", "a", "b", "c", "d")
|
||||||
|
list.Sort(utils.StringComparator)
|
||||||
|
for i := 1; i < list.Size(); i++ {
|
||||||
|
a, _ := list.Get(i - 1)
|
||||||
|
b, _ := list.Get(i)
|
||||||
|
if a.(string) > b.(string) {
|
||||||
|
t.Errorf("Not sorted! %s > %s", a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListClear(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("e", "f", "g", "a", "b", "c", "d")
|
||||||
|
list.Clear()
|
||||||
|
if actualValue := list.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListContains(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue := list.Contains("a"); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c"); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c", "d"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
list.Clear()
|
||||||
|
if actualValue := list.Contains("a"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListValues(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListInsert(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Insert(0, "b", "c")
|
||||||
|
list.Insert(0, "a")
|
||||||
|
list.Insert(10, "x") // ignore
|
||||||
|
if actualValue := list.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
list.Insert(3, "d") // append
|
||||||
|
if actualValue := list.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", list.Values()...), "abcd"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListEach(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
list.Each(func(index int, value interface{}) {
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListMap(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
mappedList := list.Map(func(index int, value interface{}) interface{} {
|
||||||
|
return "mapped: " + value.(string)
|
||||||
|
})
|
||||||
|
if actualValue, _ := mappedList.Get(0); actualValue != "mapped: a" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedList.Get(1); actualValue != "mapped: b" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: b")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedList.Get(2); actualValue != "mapped: c" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: c")
|
||||||
|
}
|
||||||
|
if mappedList.Size() != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", mappedList.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSelect(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
selectedList := list.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "b"
|
||||||
|
})
|
||||||
|
if actualValue, _ := selectedList.Get(0); actualValue != "a" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := selectedList.Get(1); actualValue != "b" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: b")
|
||||||
|
}
|
||||||
|
if selectedList.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", selectedList.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListAny(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
any := list.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "c"
|
||||||
|
})
|
||||||
|
if any != true {
|
||||||
|
t.Errorf("Got %v expected %v", any, true)
|
||||||
|
}
|
||||||
|
any = list.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "x"
|
||||||
|
})
|
||||||
|
if any != false {
|
||||||
|
t.Errorf("Got %v expected %v", any, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListAll(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
all := list.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "c"
|
||||||
|
})
|
||||||
|
if all != true {
|
||||||
|
t.Errorf("Got %v expected %v", all, true)
|
||||||
|
}
|
||||||
|
all = list.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "b"
|
||||||
|
})
|
||||||
|
if all != false {
|
||||||
|
t.Errorf("Got %v expected %v", all, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListFind(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
foundIndex, foundValue := list.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "c"
|
||||||
|
})
|
||||||
|
if foundValue != "c" || foundIndex != 2 {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 2)
|
||||||
|
}
|
||||||
|
foundIndex, foundValue = list.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "x"
|
||||||
|
})
|
||||||
|
if foundValue != nil || foundIndex != -1 {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListChaining(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
chainedList := list.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) > "a"
|
||||||
|
}).Map(func(index int, value interface{}) interface{} {
|
||||||
|
return value.(string) + value.(string)
|
||||||
|
})
|
||||||
|
if chainedList.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", chainedList.Size(), 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := chainedList.Get(0); actualValue != "bb" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
if actualValue, ok := chainedList.Get(1); actualValue != "cc" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorNext(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
it := list.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorPrevOnEmpty(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorPrev(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
it := list.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
for it.Prev() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorBegin(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorEnd(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
|
||||||
|
if index := it.Index(); index != -1 {
|
||||||
|
t.Errorf("Got %v expected %v", index, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", index, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != list.Size() {
|
||||||
|
t.Errorf("Got %v expected %v", index, list.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Prev()
|
||||||
|
if index, value := it.Index(), it.Value(); index != list.Size()-1 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, list.Size()-1, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorFirst(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorLast(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 2 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSerialization(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := list.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = list.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkAdd(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListAdd100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListAdd1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListAdd10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListAdd100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayListRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
79
vendor/github.com/emirpasic/gods/lists/arraylist/enumerable.go
generated
vendored
Normal file
79
vendor/github.com/emirpasic/gods/lists/arraylist/enumerable.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package arraylist
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertEnumerableImplementation() {
|
||||||
|
var _ containers.EnumerableWithIndex = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each calls the given function once for each element, passing that element's index and value.
|
||||||
|
func (list *List) Each(f func(index int, value interface{})) {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
f(iterator.Index(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a
|
||||||
|
// container containing the values returned by the given function.
|
||||||
|
func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
|
||||||
|
newList := &List{}
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
newList.Add(f(iterator.Index(), iterator.Value()))
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
func (list *List) Select(f func(index int, value interface{}) bool) *List {
|
||||||
|
newList := &List{}
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
newList.Add(iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any passes each element of the collection to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
func (list *List) Any(f func(index int, value interface{}) bool) bool {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// All passes each element of the collection to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
func (list *List) All(f func(index int, value interface{}) bool) bool {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if !f(iterator.Index(), iterator.Value()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (index,value) for which the function is true or -1,nil otherwise
|
||||||
|
// if no element matches the criteria.
|
||||||
|
func (list *List) Find(f func(index int, value interface{}) bool) (int, interface{}) {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
return iterator.Index(), iterator.Value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1, nil
|
||||||
|
}
|
83
vendor/github.com/emirpasic/gods/lists/arraylist/iterator.go
generated
vendored
Normal file
83
vendor/github.com/emirpasic/gods/lists/arraylist/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package arraylist
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
list *List
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
func (list *List) Iterator() Iterator {
|
||||||
|
return Iterator{list: list, index: -1}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
if iterator.index < iterator.list.size {
|
||||||
|
iterator.index++
|
||||||
|
}
|
||||||
|
return iterator.list.withinRange(iterator.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
if iterator.index >= 0 {
|
||||||
|
iterator.index--
|
||||||
|
}
|
||||||
|
return iterator.list.withinRange(iterator.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
return iterator.list.elements[iterator.index]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index returns the current element's index.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Index() int {
|
||||||
|
return iterator.index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.index = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.index = iterator.list.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
iterator.End()
|
||||||
|
return iterator.Prev()
|
||||||
|
}
|
29
vendor/github.com/emirpasic/gods/lists/arraylist/serialization.go
generated
vendored
Normal file
29
vendor/github.com/emirpasic/gods/lists/arraylist/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package arraylist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*List)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (list *List) ToJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(list.elements[:list.size])
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (list *List) FromJSON(data []byte) error {
|
||||||
|
err := json.Unmarshal(data, &list.elements)
|
||||||
|
if err == nil {
|
||||||
|
list.size = len(list.elements)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
296
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/doublylinkedlist.go
generated
vendored
Normal file
296
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/doublylinkedlist.go
generated
vendored
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package doublylinkedlist implements the doubly-linked list.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29
|
||||||
|
package doublylinkedlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/lists"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertListImplementation() {
|
||||||
|
var _ lists.List = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// List holds the elements, where each element points to the next and previous element
|
||||||
|
type List struct {
|
||||||
|
first *element
|
||||||
|
last *element
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
type element struct {
|
||||||
|
value interface{}
|
||||||
|
prev *element
|
||||||
|
next *element
|
||||||
|
}
|
||||||
|
|
||||||
|
// New instantiates a new empty list
|
||||||
|
func New() *List {
|
||||||
|
return &List{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add appends a value (one or more) at the end of the list (same as Append())
|
||||||
|
func (list *List) Add(values ...interface{}) {
|
||||||
|
for _, value := range values {
|
||||||
|
newElement := &element{value: value, prev: list.last}
|
||||||
|
if list.size == 0 {
|
||||||
|
list.first = newElement
|
||||||
|
list.last = newElement
|
||||||
|
} else {
|
||||||
|
list.last.next = newElement
|
||||||
|
list.last = newElement
|
||||||
|
}
|
||||||
|
list.size++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append appends a value (one or more) at the end of the list (same as Add())
|
||||||
|
func (list *List) Append(values ...interface{}) {
|
||||||
|
list.Add(values...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend prepends a values (or more)
|
||||||
|
func (list *List) Prepend(values ...interface{}) {
|
||||||
|
// in reverse to keep passed order i.e. ["c","d"] -> Prepend(["a","b"]) -> ["a","b","c",d"]
|
||||||
|
for v := len(values) - 1; v >= 0; v-- {
|
||||||
|
newElement := &element{value: values[v], next: list.first}
|
||||||
|
if list.size == 0 {
|
||||||
|
list.first = newElement
|
||||||
|
list.last = newElement
|
||||||
|
} else {
|
||||||
|
list.first.prev = newElement
|
||||||
|
list.first = newElement
|
||||||
|
}
|
||||||
|
list.size++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the element at index.
|
||||||
|
// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false.
|
||||||
|
func (list *List) Get(index int) (interface{}, bool) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine traveral direction, last to first or first to last
|
||||||
|
if list.size-index < index {
|
||||||
|
element := list.last
|
||||||
|
for e := list.size - 1; e != index; e, element = e-1, element.prev {
|
||||||
|
}
|
||||||
|
return element.value, true
|
||||||
|
}
|
||||||
|
element := list.first
|
||||||
|
for e := 0; e != index; e, element = e+1, element.next {
|
||||||
|
}
|
||||||
|
return element.value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes one or more elements from the list with the supplied indices.
|
||||||
|
func (list *List) Remove(index int) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if list.size == 1 {
|
||||||
|
list.Clear()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var element *element
|
||||||
|
// determine traversal direction, last to first or first to last
|
||||||
|
if list.size-index < index {
|
||||||
|
element = list.last
|
||||||
|
for e := list.size - 1; e != index; e, element = e-1, element.prev {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
element = list.first
|
||||||
|
for e := 0; e != index; e, element = e+1, element.next {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if element == list.first {
|
||||||
|
list.first = element.next
|
||||||
|
}
|
||||||
|
if element == list.last {
|
||||||
|
list.last = element.prev
|
||||||
|
}
|
||||||
|
if element.prev != nil {
|
||||||
|
element.prev.next = element.next
|
||||||
|
}
|
||||||
|
if element.next != nil {
|
||||||
|
element.next.prev = element.prev
|
||||||
|
}
|
||||||
|
|
||||||
|
element = nil
|
||||||
|
|
||||||
|
list.size--
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains check if values (one or more) are present in the set.
|
||||||
|
// All values have to be present in the set for the method to return true.
|
||||||
|
// Performance time complexity of n^2.
|
||||||
|
// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set.
|
||||||
|
func (list *List) Contains(values ...interface{}) bool {
|
||||||
|
|
||||||
|
if len(values) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if list.size == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range values {
|
||||||
|
found := false
|
||||||
|
for element := list.first; element != nil; element = element.next {
|
||||||
|
if element.value == value {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all elements in the list.
|
||||||
|
func (list *List) Values() []interface{} {
|
||||||
|
values := make([]interface{}, list.size, list.size)
|
||||||
|
for e, element := 0, list.first; element != nil; e, element = e+1, element.next {
|
||||||
|
values[e] = element.value
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if list does not contain any elements.
|
||||||
|
func (list *List) Empty() bool {
|
||||||
|
return list.size == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements within the list.
|
||||||
|
func (list *List) Size() int {
|
||||||
|
return list.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the list.
|
||||||
|
func (list *List) Clear() {
|
||||||
|
list.size = 0
|
||||||
|
list.first = nil
|
||||||
|
list.last = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort sorts values (in-place) using.
|
||||||
|
func (list *List) Sort(comparator utils.Comparator) {
|
||||||
|
|
||||||
|
if list.size < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
values := list.Values()
|
||||||
|
utils.Sort(values, comparator)
|
||||||
|
|
||||||
|
list.Clear()
|
||||||
|
|
||||||
|
list.Add(values...)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap swaps values of two elements at the given indices.
|
||||||
|
func (list *List) Swap(i, j int) {
|
||||||
|
if list.withinRange(i) && list.withinRange(j) && i != j {
|
||||||
|
var element1, element2 *element
|
||||||
|
for e, currentElement := 0, list.first; element1 == nil || element2 == nil; e, currentElement = e+1, currentElement.next {
|
||||||
|
switch e {
|
||||||
|
case i:
|
||||||
|
element1 = currentElement
|
||||||
|
case j:
|
||||||
|
element2 = currentElement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
element1.value, element2.value = element2.value, element1.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right.
|
||||||
|
// Does not do anything if position is negative or bigger than list's size
|
||||||
|
// Note: position equal to list's size is valid, i.e. append.
|
||||||
|
func (list *List) Insert(index int, values ...interface{}) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
// Append
|
||||||
|
if index == list.size {
|
||||||
|
list.Add(values...)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list.size += len(values)
|
||||||
|
|
||||||
|
var beforeElement *element
|
||||||
|
var foundElement *element
|
||||||
|
// determine traversal direction, last to first or first to last
|
||||||
|
if list.size-index < index {
|
||||||
|
foundElement = list.last
|
||||||
|
for e := list.size - 1; e != index; e, foundElement = e-1, foundElement.prev {
|
||||||
|
beforeElement = foundElement.prev
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foundElement = list.first
|
||||||
|
for e := 0; e != index; e, foundElement = e+1, foundElement.next {
|
||||||
|
beforeElement = foundElement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundElement == list.first {
|
||||||
|
oldNextElement := list.first
|
||||||
|
for i, value := range values {
|
||||||
|
newElement := &element{value: value}
|
||||||
|
if i == 0 {
|
||||||
|
list.first = newElement
|
||||||
|
} else {
|
||||||
|
newElement.prev = beforeElement
|
||||||
|
beforeElement.next = newElement
|
||||||
|
}
|
||||||
|
beforeElement = newElement
|
||||||
|
}
|
||||||
|
oldNextElement.prev = beforeElement
|
||||||
|
beforeElement.next = oldNextElement
|
||||||
|
} else {
|
||||||
|
oldNextElement := beforeElement.next
|
||||||
|
for _, value := range values {
|
||||||
|
newElement := &element{value: value}
|
||||||
|
newElement.prev = beforeElement
|
||||||
|
beforeElement.next = newElement
|
||||||
|
beforeElement = newElement
|
||||||
|
}
|
||||||
|
oldNextElement.prev = beforeElement
|
||||||
|
beforeElement.next = oldNextElement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (list *List) String() string {
|
||||||
|
str := "DoublyLinkedList\n"
|
||||||
|
values := []string{}
|
||||||
|
for element := list.first; element != nil; element = element.next {
|
||||||
|
values = append(values, fmt.Sprintf("%v", element.value))
|
||||||
|
}
|
||||||
|
str += strings.Join(values, ", ")
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the index is within bounds of the list
|
||||||
|
func (list *List) withinRange(index int) bool {
|
||||||
|
return index >= 0 && index < list.size
|
||||||
|
}
|
606
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/doublylinkedlist_test.go
generated
vendored
Normal file
606
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/doublylinkedlist_test.go
generated
vendored
Normal file
|
@ -0,0 +1,606 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package doublylinkedlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestListAdd(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue := list.Empty(); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListRemove(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
list.Remove(2)
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
list.Remove(1)
|
||||||
|
list.Remove(0)
|
||||||
|
list.Remove(0) // no effect
|
||||||
|
if actualValue := list.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListGet(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "a" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "a")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(1); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(3); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
list.Remove(0)
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSwap(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
list.Swap(0, 1)
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSort(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Sort(utils.StringComparator)
|
||||||
|
list.Add("e", "f", "g", "a", "b", "c", "d")
|
||||||
|
list.Sort(utils.StringComparator)
|
||||||
|
for i := 1; i < list.Size(); i++ {
|
||||||
|
a, _ := list.Get(i - 1)
|
||||||
|
b, _ := list.Get(i)
|
||||||
|
if a.(string) > b.(string) {
|
||||||
|
t.Errorf("Not sorted! %s > %s", a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListClear(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("e", "f", "g", "a", "b", "c", "d")
|
||||||
|
list.Clear()
|
||||||
|
if actualValue := list.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListContains(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue := list.Contains("a"); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c"); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c", "d"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
list.Clear()
|
||||||
|
if actualValue := list.Contains("a"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListValues(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListInsert(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Insert(0, "b", "c")
|
||||||
|
list.Insert(0, "a")
|
||||||
|
list.Insert(10, "x") // ignore
|
||||||
|
if actualValue := list.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
list.Insert(3, "d") // append
|
||||||
|
if actualValue := list.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", list.Values()...), "abcd"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListEach(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
list.Each(func(index int, value interface{}) {
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListMap(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
mappedList := list.Map(func(index int, value interface{}) interface{} {
|
||||||
|
return "mapped: " + value.(string)
|
||||||
|
})
|
||||||
|
if actualValue, _ := mappedList.Get(0); actualValue != "mapped: a" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedList.Get(1); actualValue != "mapped: b" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: b")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedList.Get(2); actualValue != "mapped: c" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: c")
|
||||||
|
}
|
||||||
|
if mappedList.Size() != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", mappedList.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSelect(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
selectedList := list.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "b"
|
||||||
|
})
|
||||||
|
if actualValue, _ := selectedList.Get(0); actualValue != "a" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := selectedList.Get(1); actualValue != "b" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: b")
|
||||||
|
}
|
||||||
|
if selectedList.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", selectedList.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListAny(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
any := list.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "c"
|
||||||
|
})
|
||||||
|
if any != true {
|
||||||
|
t.Errorf("Got %v expected %v", any, true)
|
||||||
|
}
|
||||||
|
any = list.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "x"
|
||||||
|
})
|
||||||
|
if any != false {
|
||||||
|
t.Errorf("Got %v expected %v", any, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListAll(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
all := list.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "c"
|
||||||
|
})
|
||||||
|
if all != true {
|
||||||
|
t.Errorf("Got %v expected %v", all, true)
|
||||||
|
}
|
||||||
|
all = list.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "b"
|
||||||
|
})
|
||||||
|
if all != false {
|
||||||
|
t.Errorf("Got %v expected %v", all, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListFind(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
foundIndex, foundValue := list.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "c"
|
||||||
|
})
|
||||||
|
if foundValue != "c" || foundIndex != 2 {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 2)
|
||||||
|
}
|
||||||
|
foundIndex, foundValue = list.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "x"
|
||||||
|
})
|
||||||
|
if foundValue != nil || foundIndex != -1 {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListChaining(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
chainedList := list.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) > "a"
|
||||||
|
}).Map(func(index int, value interface{}) interface{} {
|
||||||
|
return value.(string) + value.(string)
|
||||||
|
})
|
||||||
|
if chainedList.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", chainedList.Size(), 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := chainedList.Get(0); actualValue != "bb" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
if actualValue, ok := chainedList.Get(1); actualValue != "cc" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorNext(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
it := list.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorPrevOnEmpty(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorPrev(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
it := list.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
for it.Prev() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorBegin(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorEnd(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
|
||||||
|
if index := it.Index(); index != -1 {
|
||||||
|
t.Errorf("Got %v expected %v", index, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", index, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != list.Size() {
|
||||||
|
t.Errorf("Got %v expected %v", index, list.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Prev()
|
||||||
|
if index, value := it.Index(), it.Value(); index != list.Size()-1 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, list.Size()-1, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorFirst(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorLast(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 2 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSerialization(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := list.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = list.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkAdd(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListAdd100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListAdd1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListAdd10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListAdd100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDoublyLinkedListRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
79
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/enumerable.go
generated
vendored
Normal file
79
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/enumerable.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package doublylinkedlist
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertEnumerableImplementation() {
|
||||||
|
var _ containers.EnumerableWithIndex = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each calls the given function once for each element, passing that element's index and value.
|
||||||
|
func (list *List) Each(f func(index int, value interface{})) {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
f(iterator.Index(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a
|
||||||
|
// container containing the values returned by the given function.
|
||||||
|
func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
|
||||||
|
newList := &List{}
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
newList.Add(f(iterator.Index(), iterator.Value()))
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
func (list *List) Select(f func(index int, value interface{}) bool) *List {
|
||||||
|
newList := &List{}
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
newList.Add(iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any passes each element of the container to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
func (list *List) Any(f func(index int, value interface{}) bool) bool {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// All passes each element of the container to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
func (list *List) All(f func(index int, value interface{}) bool) bool {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if !f(iterator.Index(), iterator.Value()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (index,value) for which the function is true or -1,nil otherwise
|
||||||
|
// if no element matches the criteria.
|
||||||
|
func (list *List) Find(f func(index int, value interface{}) bool) (index int, value interface{}) {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
return iterator.Index(), iterator.Value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1, nil
|
||||||
|
}
|
104
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/iterator.go
generated
vendored
Normal file
104
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package doublylinkedlist
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
list *List
|
||||||
|
index int
|
||||||
|
element *element
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
func (list *List) Iterator() Iterator {
|
||||||
|
return Iterator{list: list, index: -1, element: nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
if iterator.index < iterator.list.size {
|
||||||
|
iterator.index++
|
||||||
|
}
|
||||||
|
if !iterator.list.withinRange(iterator.index) {
|
||||||
|
iterator.element = nil
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if iterator.index != 0 {
|
||||||
|
iterator.element = iterator.element.next
|
||||||
|
} else {
|
||||||
|
iterator.element = iterator.list.first
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
if iterator.index >= 0 {
|
||||||
|
iterator.index--
|
||||||
|
}
|
||||||
|
if !iterator.list.withinRange(iterator.index) {
|
||||||
|
iterator.element = nil
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if iterator.index == iterator.list.size-1 {
|
||||||
|
iterator.element = iterator.list.last
|
||||||
|
} else {
|
||||||
|
iterator.element = iterator.element.prev
|
||||||
|
}
|
||||||
|
return iterator.list.withinRange(iterator.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
return iterator.element.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index returns the current element's index.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Index() int {
|
||||||
|
return iterator.index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.index = -1
|
||||||
|
iterator.element = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.index = iterator.list.size
|
||||||
|
iterator.element = iterator.list.last
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
iterator.End()
|
||||||
|
return iterator.Prev()
|
||||||
|
}
|
31
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/serialization.go
generated
vendored
Normal file
31
vendor/github.com/emirpasic/gods/lists/doublylinkedlist/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package doublylinkedlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*List)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (list *List) ToJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(list.Values())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (list *List) FromJSON(data []byte) error {
|
||||||
|
elements := []interface{}{}
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
list.Clear()
|
||||||
|
list.Add(elements...)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
32
vendor/github.com/emirpasic/gods/lists/lists.go
generated
vendored
Normal file
32
vendor/github.com/emirpasic/gods/lists/lists.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package lists provides an abstract List interface.
|
||||||
|
//
|
||||||
|
// In computer science, a list or sequence is an abstract data type that represents an ordered sequence of values, where the same value may occur more than once. An instance of a list is a computer representation of the mathematical concept of a finite sequence; the (potentially) infinite analog of a list is a stream. Lists are a basic example of containers, as they contain other values. If the same value occurs multiple times, each occurrence is considered a distinct item.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29
|
||||||
|
package lists
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// List interface that all lists implement
|
||||||
|
type List interface {
|
||||||
|
Get(index int) (interface{}, bool)
|
||||||
|
Remove(index int)
|
||||||
|
Add(values ...interface{})
|
||||||
|
Contains(values ...interface{}) bool
|
||||||
|
Sort(comparator utils.Comparator)
|
||||||
|
Swap(index1, index2 int)
|
||||||
|
Insert(index int, values ...interface{})
|
||||||
|
|
||||||
|
containers.Container
|
||||||
|
// Empty() bool
|
||||||
|
// Size() int
|
||||||
|
// Clear()
|
||||||
|
// Values() []interface{}
|
||||||
|
}
|
79
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/enumerable.go
generated
vendored
Normal file
79
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/enumerable.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package singlylinkedlist
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertEnumerableImplementation() {
|
||||||
|
var _ containers.EnumerableWithIndex = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each calls the given function once for each element, passing that element's index and value.
|
||||||
|
func (list *List) Each(f func(index int, value interface{})) {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
f(iterator.Index(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a
|
||||||
|
// container containing the values returned by the given function.
|
||||||
|
func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
|
||||||
|
newList := &List{}
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
newList.Add(f(iterator.Index(), iterator.Value()))
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
func (list *List) Select(f func(index int, value interface{}) bool) *List {
|
||||||
|
newList := &List{}
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
newList.Add(iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any passes each element of the container to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
func (list *List) Any(f func(index int, value interface{}) bool) bool {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// All passes each element of the container to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
func (list *List) All(f func(index int, value interface{}) bool) bool {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if !f(iterator.Index(), iterator.Value()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (index,value) for which the function is true or -1,nil otherwise
|
||||||
|
// if no element matches the criteria.
|
||||||
|
func (list *List) Find(f func(index int, value interface{}) bool) (index int, value interface{}) {
|
||||||
|
iterator := list.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
return iterator.Index(), iterator.Value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1, nil
|
||||||
|
}
|
70
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/iterator.go
generated
vendored
Normal file
70
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package singlylinkedlist
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.IteratorWithIndex = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
list *List
|
||||||
|
index int
|
||||||
|
element *element
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
func (list *List) Iterator() Iterator {
|
||||||
|
return Iterator{list: list, index: -1, element: nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
if iterator.index < iterator.list.size {
|
||||||
|
iterator.index++
|
||||||
|
}
|
||||||
|
if !iterator.list.withinRange(iterator.index) {
|
||||||
|
iterator.element = nil
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if iterator.index == 0 {
|
||||||
|
iterator.element = iterator.list.first
|
||||||
|
} else {
|
||||||
|
iterator.element = iterator.element.next
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
return iterator.element.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index returns the current element's index.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Index() int {
|
||||||
|
return iterator.index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.index = -1
|
||||||
|
iterator.element = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
31
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/serialization.go
generated
vendored
Normal file
31
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package singlylinkedlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*List)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (list *List) ToJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(list.Values())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (list *List) FromJSON(data []byte) error {
|
||||||
|
elements := []interface{}{}
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
list.Clear()
|
||||||
|
list.Add(elements...)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
264
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/singlylinkedlist.go
generated
vendored
Normal file
264
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/singlylinkedlist.go
generated
vendored
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package singlylinkedlist implements the singly-linked list.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29
|
||||||
|
package singlylinkedlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/lists"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertListImplementation() {
|
||||||
|
var _ lists.List = (*List)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// List holds the elements, where each element points to the next element
|
||||||
|
type List struct {
|
||||||
|
first *element
|
||||||
|
last *element
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
type element struct {
|
||||||
|
value interface{}
|
||||||
|
next *element
|
||||||
|
}
|
||||||
|
|
||||||
|
// New instantiates a new empty list
|
||||||
|
func New() *List {
|
||||||
|
return &List{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add appends a value (one or more) at the end of the list (same as Append())
|
||||||
|
func (list *List) Add(values ...interface{}) {
|
||||||
|
for _, value := range values {
|
||||||
|
newElement := &element{value: value}
|
||||||
|
if list.size == 0 {
|
||||||
|
list.first = newElement
|
||||||
|
list.last = newElement
|
||||||
|
} else {
|
||||||
|
list.last.next = newElement
|
||||||
|
list.last = newElement
|
||||||
|
}
|
||||||
|
list.size++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append appends a value (one or more) at the end of the list (same as Add())
|
||||||
|
func (list *List) Append(values ...interface{}) {
|
||||||
|
list.Add(values...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend prepends a values (or more)
|
||||||
|
func (list *List) Prepend(values ...interface{}) {
|
||||||
|
// in reverse to keep passed order i.e. ["c","d"] -> Prepend(["a","b"]) -> ["a","b","c",d"]
|
||||||
|
for v := len(values) - 1; v >= 0; v-- {
|
||||||
|
newElement := &element{value: values[v], next: list.first}
|
||||||
|
list.first = newElement
|
||||||
|
if list.size == 0 {
|
||||||
|
list.last = newElement
|
||||||
|
}
|
||||||
|
list.size++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the element at index.
|
||||||
|
// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false.
|
||||||
|
func (list *List) Get(index int) (interface{}, bool) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
element := list.first
|
||||||
|
for e := 0; e != index; e, element = e+1, element.next {
|
||||||
|
}
|
||||||
|
|
||||||
|
return element.value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes one or more elements from the list with the supplied indices.
|
||||||
|
func (list *List) Remove(index int) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if list.size == 1 {
|
||||||
|
list.Clear()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var beforeElement *element
|
||||||
|
element := list.first
|
||||||
|
for e := 0; e != index; e, element = e+1, element.next {
|
||||||
|
beforeElement = element
|
||||||
|
}
|
||||||
|
|
||||||
|
if element == list.first {
|
||||||
|
list.first = element.next
|
||||||
|
}
|
||||||
|
if element == list.last {
|
||||||
|
list.last = beforeElement
|
||||||
|
}
|
||||||
|
if beforeElement != nil {
|
||||||
|
beforeElement.next = element.next
|
||||||
|
}
|
||||||
|
|
||||||
|
element = nil
|
||||||
|
|
||||||
|
list.size--
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains checks if values (one or more) are present in the set.
|
||||||
|
// All values have to be present in the set for the method to return true.
|
||||||
|
// Performance time complexity of n^2.
|
||||||
|
// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set.
|
||||||
|
func (list *List) Contains(values ...interface{}) bool {
|
||||||
|
|
||||||
|
if len(values) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if list.size == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range values {
|
||||||
|
found := false
|
||||||
|
for element := list.first; element != nil; element = element.next {
|
||||||
|
if element.value == value {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all elements in the list.
|
||||||
|
func (list *List) Values() []interface{} {
|
||||||
|
values := make([]interface{}, list.size, list.size)
|
||||||
|
for e, element := 0, list.first; element != nil; e, element = e+1, element.next {
|
||||||
|
values[e] = element.value
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if list does not contain any elements.
|
||||||
|
func (list *List) Empty() bool {
|
||||||
|
return list.size == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements within the list.
|
||||||
|
func (list *List) Size() int {
|
||||||
|
return list.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the list.
|
||||||
|
func (list *List) Clear() {
|
||||||
|
list.size = 0
|
||||||
|
list.first = nil
|
||||||
|
list.last = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort sort values (in-place) using.
|
||||||
|
func (list *List) Sort(comparator utils.Comparator) {
|
||||||
|
|
||||||
|
if list.size < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
values := list.Values()
|
||||||
|
utils.Sort(values, comparator)
|
||||||
|
|
||||||
|
list.Clear()
|
||||||
|
|
||||||
|
list.Add(values...)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap swaps values of two elements at the given indices.
|
||||||
|
func (list *List) Swap(i, j int) {
|
||||||
|
if list.withinRange(i) && list.withinRange(j) && i != j {
|
||||||
|
var element1, element2 *element
|
||||||
|
for e, currentElement := 0, list.first; element1 == nil || element2 == nil; e, currentElement = e+1, currentElement.next {
|
||||||
|
switch e {
|
||||||
|
case i:
|
||||||
|
element1 = currentElement
|
||||||
|
case j:
|
||||||
|
element2 = currentElement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
element1.value, element2.value = element2.value, element1.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right.
|
||||||
|
// Does not do anything if position is negative or bigger than list's size
|
||||||
|
// Note: position equal to list's size is valid, i.e. append.
|
||||||
|
func (list *List) Insert(index int, values ...interface{}) {
|
||||||
|
|
||||||
|
if !list.withinRange(index) {
|
||||||
|
// Append
|
||||||
|
if index == list.size {
|
||||||
|
list.Add(values...)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list.size += len(values)
|
||||||
|
|
||||||
|
var beforeElement *element
|
||||||
|
foundElement := list.first
|
||||||
|
for e := 0; e != index; e, foundElement = e+1, foundElement.next {
|
||||||
|
beforeElement = foundElement
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundElement == list.first {
|
||||||
|
oldNextElement := list.first
|
||||||
|
for i, value := range values {
|
||||||
|
newElement := &element{value: value}
|
||||||
|
if i == 0 {
|
||||||
|
list.first = newElement
|
||||||
|
} else {
|
||||||
|
beforeElement.next = newElement
|
||||||
|
}
|
||||||
|
beforeElement = newElement
|
||||||
|
}
|
||||||
|
beforeElement.next = oldNextElement
|
||||||
|
} else {
|
||||||
|
oldNextElement := beforeElement.next
|
||||||
|
for _, value := range values {
|
||||||
|
newElement := &element{value: value}
|
||||||
|
beforeElement.next = newElement
|
||||||
|
beforeElement = newElement
|
||||||
|
}
|
||||||
|
beforeElement.next = oldNextElement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (list *List) String() string {
|
||||||
|
str := "SinglyLinkedList\n"
|
||||||
|
values := []string{}
|
||||||
|
for element := list.first; element != nil; element = element.next {
|
||||||
|
values = append(values, fmt.Sprintf("%v", element.value))
|
||||||
|
}
|
||||||
|
str += strings.Join(values, ", ")
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the index is within bounds of the list
|
||||||
|
func (list *List) withinRange(index int) bool {
|
||||||
|
return index >= 0 && index < list.size
|
||||||
|
}
|
525
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/singlylinkedlist_test.go
generated
vendored
Normal file
525
vendor/github.com/emirpasic/gods/lists/singlylinkedlist/singlylinkedlist_test.go
generated
vendored
Normal file
|
@ -0,0 +1,525 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package singlylinkedlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestListAdd(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue := list.Empty(); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListRemove(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
list.Remove(2)
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
list.Remove(1)
|
||||||
|
list.Remove(0)
|
||||||
|
list.Remove(0) // no effect
|
||||||
|
if actualValue := list.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListGet(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "a" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "a")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(1); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
if actualValue, ok := list.Get(3); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
list.Remove(0)
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSwap(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
list.Swap(0, 1)
|
||||||
|
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSort(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Sort(utils.StringComparator)
|
||||||
|
list.Add("e", "f", "g", "a", "b", "c", "d")
|
||||||
|
list.Sort(utils.StringComparator)
|
||||||
|
for i := 1; i < list.Size(); i++ {
|
||||||
|
a, _ := list.Get(i - 1)
|
||||||
|
b, _ := list.Get(i)
|
||||||
|
if a.(string) > b.(string) {
|
||||||
|
t.Errorf("Not sorted! %s > %s", a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListClear(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("e", "f", "g", "a", "b", "c", "d")
|
||||||
|
list.Clear()
|
||||||
|
if actualValue := list.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListContains(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue := list.Contains("a"); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c"); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c", "d"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
list.Clear()
|
||||||
|
if actualValue := list.Contains("a"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := list.Contains("a", "b", "c"); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListValues(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a")
|
||||||
|
list.Add("b", "c")
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListInsert(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Insert(0, "b", "c")
|
||||||
|
list.Insert(0, "a")
|
||||||
|
list.Insert(10, "x") // ignore
|
||||||
|
if actualValue := list.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
list.Insert(3, "d") // append
|
||||||
|
if actualValue := list.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", list.Values()...), "abcd"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListEach(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
list.Each(func(index int, value interface{}) {
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListMap(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
mappedList := list.Map(func(index int, value interface{}) interface{} {
|
||||||
|
return "mapped: " + value.(string)
|
||||||
|
})
|
||||||
|
if actualValue, _ := mappedList.Get(0); actualValue != "mapped: a" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedList.Get(1); actualValue != "mapped: b" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: b")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedList.Get(2); actualValue != "mapped: c" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: c")
|
||||||
|
}
|
||||||
|
if mappedList.Size() != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", mappedList.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSelect(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
selectedList := list.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "b"
|
||||||
|
})
|
||||||
|
if actualValue, _ := selectedList.Get(0); actualValue != "a" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := selectedList.Get(1); actualValue != "b" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: b")
|
||||||
|
}
|
||||||
|
if selectedList.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", selectedList.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListAny(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
any := list.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "c"
|
||||||
|
})
|
||||||
|
if any != true {
|
||||||
|
t.Errorf("Got %v expected %v", any, true)
|
||||||
|
}
|
||||||
|
any = list.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "x"
|
||||||
|
})
|
||||||
|
if any != false {
|
||||||
|
t.Errorf("Got %v expected %v", any, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListAll(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
all := list.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "c"
|
||||||
|
})
|
||||||
|
if all != true {
|
||||||
|
t.Errorf("Got %v expected %v", all, true)
|
||||||
|
}
|
||||||
|
all = list.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "b"
|
||||||
|
})
|
||||||
|
if all != false {
|
||||||
|
t.Errorf("Got %v expected %v", all, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListFind(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
foundIndex, foundValue := list.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "c"
|
||||||
|
})
|
||||||
|
if foundValue != "c" || foundIndex != 2 {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 2)
|
||||||
|
}
|
||||||
|
foundIndex, foundValue = list.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "x"
|
||||||
|
})
|
||||||
|
if foundValue != nil || foundIndex != -1 {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestListChaining(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
chainedList := list.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) > "a"
|
||||||
|
}).Map(func(index int, value interface{}) interface{} {
|
||||||
|
return value.(string) + value.(string)
|
||||||
|
})
|
||||||
|
if chainedList.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", chainedList.Size(), 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := chainedList.Get(0); actualValue != "bb" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "b")
|
||||||
|
}
|
||||||
|
if actualValue, ok := chainedList.Get(1); actualValue != "cc" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorNext(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
it := list.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorBegin(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorFirst(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
it := list.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListSerialization(t *testing.T) {
|
||||||
|
list := New()
|
||||||
|
list.Add("a", "b", "c")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := list.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = list.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkAdd(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, list *List, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListAdd100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListAdd1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListAdd10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListAdd100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSinglyLinkedListRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
list := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
list.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, list, size)
|
||||||
|
}
|
102
vendor/github.com/emirpasic/gods/maps/hashbidimap/hashbidimap.go
generated
vendored
Normal file
102
vendor/github.com/emirpasic/gods/maps/hashbidimap/hashbidimap.go
generated
vendored
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package hashbidimap implements a bidirectional map backed by two hashmaps.
|
||||||
|
//
|
||||||
|
// A bidirectional map, or hash bag, is an associative data structure in which the (key,value) pairs form a one-to-one correspondence.
|
||||||
|
// Thus the binary relation is functional in each direction: value can also act as a key to key.
|
||||||
|
// A pair (a,b) thus provides a unique coupling between 'a' and 'b' so that 'b' can be found when 'a' is used as a key and 'a' can be found when 'b' is used as a key.
|
||||||
|
//
|
||||||
|
// Elements are unordered in the map.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/Bidirectional_map
|
||||||
|
package hashbidimap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/maps"
|
||||||
|
"github.com/emirpasic/gods/maps/hashmap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertMapImplementation() {
|
||||||
|
var _ maps.BidiMap = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map holds the elements in two hashmaps.
|
||||||
|
type Map struct {
|
||||||
|
forwardMap hashmap.Map
|
||||||
|
inverseMap hashmap.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
// New instantiates a bidirectional map.
|
||||||
|
func New() *Map {
|
||||||
|
return &Map{*hashmap.New(), *hashmap.New()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put inserts element into the map.
|
||||||
|
func (m *Map) Put(key interface{}, value interface{}) {
|
||||||
|
if valueByKey, ok := m.forwardMap.Get(key); ok {
|
||||||
|
m.inverseMap.Remove(valueByKey)
|
||||||
|
}
|
||||||
|
if keyByValue, ok := m.inverseMap.Get(value); ok {
|
||||||
|
m.forwardMap.Remove(keyByValue)
|
||||||
|
}
|
||||||
|
m.forwardMap.Put(key, value)
|
||||||
|
m.inverseMap.Put(value, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get searches the element in the map by key and returns its value or nil if key is not found in map.
|
||||||
|
// Second return parameter is true if key was found, otherwise false.
|
||||||
|
func (m *Map) Get(key interface{}) (value interface{}, found bool) {
|
||||||
|
return m.forwardMap.Get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetKey searches the element in the map by value and returns its key or nil if value is not found in map.
|
||||||
|
// Second return parameter is true if value was found, otherwise false.
|
||||||
|
func (m *Map) GetKey(value interface{}) (key interface{}, found bool) {
|
||||||
|
return m.inverseMap.Get(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the element from the map by key.
|
||||||
|
func (m *Map) Remove(key interface{}) {
|
||||||
|
if value, found := m.forwardMap.Get(key); found {
|
||||||
|
m.forwardMap.Remove(key)
|
||||||
|
m.inverseMap.Remove(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if map does not contain any elements
|
||||||
|
func (m *Map) Empty() bool {
|
||||||
|
return m.Size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements in the map.
|
||||||
|
func (m *Map) Size() int {
|
||||||
|
return m.forwardMap.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys (random order).
|
||||||
|
func (m *Map) Keys() []interface{} {
|
||||||
|
return m.forwardMap.Keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all values (random order).
|
||||||
|
func (m *Map) Values() []interface{} {
|
||||||
|
return m.inverseMap.Keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the map.
|
||||||
|
func (m *Map) Clear() {
|
||||||
|
m.forwardMap.Clear()
|
||||||
|
m.inverseMap.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (m *Map) String() string {
|
||||||
|
str := "HashBidiMap\n"
|
||||||
|
str += fmt.Sprintf("%v", m.forwardMap)
|
||||||
|
return str
|
||||||
|
}
|
354
vendor/github.com/emirpasic/gods/maps/hashbidimap/hashbidimap_test.go
generated
vendored
Normal file
354
vendor/github.com/emirpasic/gods/maps/hashbidimap/hashbidimap_test.go
generated
vendored
Normal file
|
@ -0,0 +1,354 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hashbidimap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapPut(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
if actualValue := m.Size(); actualValue != 7 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// key,expectedValue,expectedFound
|
||||||
|
tests1 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, "e", true},
|
||||||
|
{6, "f", true},
|
||||||
|
{7, "g", true},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests1 {
|
||||||
|
// retrievals
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapRemove(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
m.Remove(5)
|
||||||
|
m.Remove(6)
|
||||||
|
m.Remove(7)
|
||||||
|
m.Remove(8)
|
||||||
|
m.Remove(5)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests2 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, nil, false},
|
||||||
|
{6, nil, false},
|
||||||
|
{7, nil, false},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests2 {
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Remove(1)
|
||||||
|
m.Remove(4)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(3)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(2)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
if actualValue := m.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapGetKey(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
// key,expectedValue,expectedFound
|
||||||
|
tests1 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, "e", true},
|
||||||
|
{6, "f", true},
|
||||||
|
{7, "g", true},
|
||||||
|
{nil, "x", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests1 {
|
||||||
|
// retrievals
|
||||||
|
actualValue, actualFound := m.GetKey(test[1])
|
||||||
|
if actualValue != test[0] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapSerialization(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("a", 1.0)
|
||||||
|
m.Put("b", 2.0)
|
||||||
|
m.Put("c", 3.0)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{"a", "b", "c"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{1.0, 2.0, 3.0}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := m.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = m.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sameElements(a []interface{}, b []interface{}) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, av := range a {
|
||||||
|
found := false
|
||||||
|
for _, bv := range b {
|
||||||
|
if av == bv {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPut(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapPut100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapPut1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapPut10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapPut100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashBidiMapRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
33
vendor/github.com/emirpasic/gods/maps/hashbidimap/serialization.go
generated
vendored
Normal file
33
vendor/github.com/emirpasic/gods/maps/hashbidimap/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hashbidimap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Map)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
|
return m.forwardMap.ToJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
m.Clear()
|
||||||
|
for key, value := range elements {
|
||||||
|
m.Put(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
92
vendor/github.com/emirpasic/gods/maps/hashmap/hashmap.go
generated
vendored
Normal file
92
vendor/github.com/emirpasic/gods/maps/hashmap/hashmap.go
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package hashmap implements a map backed by a hash table.
|
||||||
|
//
|
||||||
|
// Elements are unordered in the map.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: http://en.wikipedia.org/wiki/Associative_array
|
||||||
|
package hashmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertMapImplementation() {
|
||||||
|
var _ maps.Map = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map holds the elements in go's native map
|
||||||
|
type Map struct {
|
||||||
|
m map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New instantiates a hash map.
|
||||||
|
func New() *Map {
|
||||||
|
return &Map{m: make(map[interface{}]interface{})}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put inserts element into the map.
|
||||||
|
func (m *Map) Put(key interface{}, value interface{}) {
|
||||||
|
m.m[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get searches the element in the map by key and returns its value or nil if key is not found in map.
|
||||||
|
// Second return parameter is true if key was found, otherwise false.
|
||||||
|
func (m *Map) Get(key interface{}) (value interface{}, found bool) {
|
||||||
|
value, found = m.m[key]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the element from the map by key.
|
||||||
|
func (m *Map) Remove(key interface{}) {
|
||||||
|
delete(m.m, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if map does not contain any elements
|
||||||
|
func (m *Map) Empty() bool {
|
||||||
|
return m.Size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements in the map.
|
||||||
|
func (m *Map) Size() int {
|
||||||
|
return len(m.m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys (random order).
|
||||||
|
func (m *Map) Keys() []interface{} {
|
||||||
|
keys := make([]interface{}, m.Size())
|
||||||
|
count := 0
|
||||||
|
for key := range m.m {
|
||||||
|
keys[count] = key
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all values (random order).
|
||||||
|
func (m *Map) Values() []interface{} {
|
||||||
|
values := make([]interface{}, m.Size())
|
||||||
|
count := 0
|
||||||
|
for _, value := range m.m {
|
||||||
|
values[count] = value
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the map.
|
||||||
|
func (m *Map) Clear() {
|
||||||
|
m.m = make(map[interface{}]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (m *Map) String() string {
|
||||||
|
str := "HashMap\n"
|
||||||
|
str += fmt.Sprintf("%v", m.m)
|
||||||
|
return str
|
||||||
|
}
|
322
vendor/github.com/emirpasic/gods/maps/hashmap/hashmap_test.go
generated
vendored
Normal file
322
vendor/github.com/emirpasic/gods/maps/hashmap/hashmap_test.go
generated
vendored
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hashmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapPut(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
if actualValue := m.Size(); actualValue != 7 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// key,expectedValue,expectedFound
|
||||||
|
tests1 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, "e", true},
|
||||||
|
{6, "f", true},
|
||||||
|
{7, "g", true},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests1 {
|
||||||
|
// retrievals
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapRemove(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
m.Remove(5)
|
||||||
|
m.Remove(6)
|
||||||
|
m.Remove(7)
|
||||||
|
m.Remove(8)
|
||||||
|
m.Remove(5)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests2 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, nil, false},
|
||||||
|
{6, nil, false},
|
||||||
|
{7, nil, false},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests2 {
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Remove(1)
|
||||||
|
m.Remove(4)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(3)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(2)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
if actualValue := m.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapSerialization(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("a", 1.0)
|
||||||
|
m.Put("b", 2.0)
|
||||||
|
m.Put("c", 3.0)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{"a", "b", "c"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{1.0, 2.0, 3.0}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := m.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = m.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sameElements(a []interface{}, b []interface{}) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, av := range a {
|
||||||
|
found := false
|
||||||
|
for _, bv := range b {
|
||||||
|
if av == bv {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPut(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapPut100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapPut1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapPut10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapPut100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashMapRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
38
vendor/github.com/emirpasic/gods/maps/hashmap/serialization.go
generated
vendored
Normal file
38
vendor/github.com/emirpasic/gods/maps/hashmap/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hashmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Map)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
for key, value := range m.m {
|
||||||
|
elements[utils.ToString(key)] = value
|
||||||
|
}
|
||||||
|
return json.Marshal(&elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
m.Clear()
|
||||||
|
for key, value := range elements {
|
||||||
|
m.m[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
39
vendor/github.com/emirpasic/gods/maps/maps.go
generated
vendored
Normal file
39
vendor/github.com/emirpasic/gods/maps/maps.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package maps provides an abstract Map interface.
|
||||||
|
//
|
||||||
|
// In computer science, an associative array, map, symbol table, or dictionary is an abstract data type composed of a collection of (key, value) pairs, such that each possible key appears just once in the collection.
|
||||||
|
//
|
||||||
|
// Operations associated with this data type allow:
|
||||||
|
// - the addition of a pair to the collection
|
||||||
|
// - the removal of a pair from the collection
|
||||||
|
// - the modification of an existing pair
|
||||||
|
// - the lookup of a value associated with a particular key
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/Associative_array
|
||||||
|
package maps
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
// Map interface that all maps implement
|
||||||
|
type Map interface {
|
||||||
|
Put(key interface{}, value interface{})
|
||||||
|
Get(key interface{}) (value interface{}, found bool)
|
||||||
|
Remove(key interface{})
|
||||||
|
Keys() []interface{}
|
||||||
|
|
||||||
|
containers.Container
|
||||||
|
// Empty() bool
|
||||||
|
// Size() int
|
||||||
|
// Clear()
|
||||||
|
// Values() []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BidiMap interface that all bidirectional maps implement (extends the Map interface)
|
||||||
|
type BidiMap interface {
|
||||||
|
GetKey(value interface{}) (key interface{}, found bool)
|
||||||
|
|
||||||
|
Map
|
||||||
|
}
|
80
vendor/github.com/emirpasic/gods/maps/treebidimap/enumerable.go
generated
vendored
Normal file
80
vendor/github.com/emirpasic/gods/maps/treebidimap/enumerable.go
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treebidimap
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertEnumerableImplementation() {
|
||||||
|
var _ containers.EnumerableWithKey = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each calls the given function once for each element, passing that element's key and value.
|
||||||
|
func (m *Map) Each(f func(key interface{}, value interface{})) {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
f(iterator.Key(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a container
|
||||||
|
// containing the values returned by the given function as key/value pairs.
|
||||||
|
func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, interface{})) *Map {
|
||||||
|
newMap := NewWith(m.keyComparator, m.valueComparator)
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
key2, value2 := f(iterator.Key(), iterator.Value())
|
||||||
|
newMap.Put(key2, value2)
|
||||||
|
}
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map {
|
||||||
|
newMap := NewWith(m.keyComparator, m.valueComparator)
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
newMap.Put(iterator.Key(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any passes each element of the container to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
func (m *Map) Any(f func(key interface{}, value interface{}) bool) bool {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// All passes each element of the container to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
func (m *Map) All(f func(key interface{}, value interface{}) bool) bool {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if !f(iterator.Key(), iterator.Value()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (key,value) for which the function is true or nil,nil otherwise if no element
|
||||||
|
// matches the criteria.
|
||||||
|
func (m *Map) Find(f func(key interface{}, value interface{}) bool) (interface{}, interface{}) {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
return iterator.Key(), iterator.Value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
77
vendor/github.com/emirpasic/gods/maps/treebidimap/iterator.go
generated
vendored
Normal file
77
vendor/github.com/emirpasic/gods/maps/treebidimap/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treebidimap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
iterator rbt.Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose elements are key/value pairs.
|
||||||
|
func (m *Map) Iterator() Iterator {
|
||||||
|
return Iterator{iterator: m.forwardMap.Iterator()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
return iterator.iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
return iterator.iterator.Prev()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
return iterator.iterator.Value().(*data).value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the current element's key.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Key() interface{} {
|
||||||
|
return iterator.iterator.Key()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.iterator.Begin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.iterator.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
return iterator.iterator.First()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
return iterator.iterator.Last()
|
||||||
|
}
|
39
vendor/github.com/emirpasic/gods/maps/treebidimap/serialization.go
generated
vendored
Normal file
39
vendor/github.com/emirpasic/gods/maps/treebidimap/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treebidimap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Map)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
it := m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
elements[utils.ToString(it.Key())] = it.Value()
|
||||||
|
}
|
||||||
|
return json.Marshal(&elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
m.Clear()
|
||||||
|
for key, value := range elements {
|
||||||
|
m.Put(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
138
vendor/github.com/emirpasic/gods/maps/treebidimap/treebidimap.go
generated
vendored
Normal file
138
vendor/github.com/emirpasic/gods/maps/treebidimap/treebidimap.go
generated
vendored
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package treebidimap implements a bidirectional map backed by two red-black tree.
|
||||||
|
//
|
||||||
|
// This structure guarantees that the map will be in both ascending key and value order.
|
||||||
|
//
|
||||||
|
// Other than key and value ordering, the goal with this structure is to avoid duplication of elements, which can be significant if contained elements are large.
|
||||||
|
//
|
||||||
|
// A bidirectional map, or hash bag, is an associative data structure in which the (key,value) pairs form a one-to-one correspondence.
|
||||||
|
// Thus the binary relation is functional in each direction: value can also act as a key to key.
|
||||||
|
// A pair (a,b) thus provides a unique coupling between 'a' and 'b' so that 'b' can be found when 'a' is used as a key and 'a' can be found when 'b' is used as a key.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/Bidirectional_map
|
||||||
|
package treebidimap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/maps"
|
||||||
|
"github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertMapImplementation() {
|
||||||
|
var _ maps.BidiMap = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map holds the elements in two red-black trees.
|
||||||
|
type Map struct {
|
||||||
|
forwardMap redblacktree.Tree
|
||||||
|
inverseMap redblacktree.Tree
|
||||||
|
keyComparator utils.Comparator
|
||||||
|
valueComparator utils.Comparator
|
||||||
|
}
|
||||||
|
|
||||||
|
type data struct {
|
||||||
|
key interface{}
|
||||||
|
value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWith instantiates a bidirectional map.
|
||||||
|
func NewWith(keyComparator utils.Comparator, valueComparator utils.Comparator) *Map {
|
||||||
|
return &Map{
|
||||||
|
forwardMap: *redblacktree.NewWith(keyComparator),
|
||||||
|
inverseMap: *redblacktree.NewWith(valueComparator),
|
||||||
|
keyComparator: keyComparator,
|
||||||
|
valueComparator: valueComparator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithIntComparators instantiates a bidirectional map with the IntComparator for key and value, i.e. keys and values are of type int.
|
||||||
|
func NewWithIntComparators() *Map {
|
||||||
|
return NewWith(utils.IntComparator, utils.IntComparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithStringComparators instantiates a bidirectional map with the StringComparator for key and value, i.e. keys and values are of type string.
|
||||||
|
func NewWithStringComparators() *Map {
|
||||||
|
return NewWith(utils.StringComparator, utils.StringComparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put inserts element into the map.
|
||||||
|
func (m *Map) Put(key interface{}, value interface{}) {
|
||||||
|
if d, ok := m.forwardMap.Get(key); ok {
|
||||||
|
m.inverseMap.Remove(d.(*data).value)
|
||||||
|
}
|
||||||
|
if d, ok := m.inverseMap.Get(value); ok {
|
||||||
|
m.forwardMap.Remove(d.(*data).key)
|
||||||
|
}
|
||||||
|
d := &data{key: key, value: value}
|
||||||
|
m.forwardMap.Put(key, d)
|
||||||
|
m.inverseMap.Put(value, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get searches the element in the map by key and returns its value or nil if key is not found in map.
|
||||||
|
// Second return parameter is true if key was found, otherwise false.
|
||||||
|
func (m *Map) Get(key interface{}) (value interface{}, found bool) {
|
||||||
|
if d, ok := m.forwardMap.Get(key); ok {
|
||||||
|
return d.(*data).value, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetKey searches the element in the map by value and returns its key or nil if value is not found in map.
|
||||||
|
// Second return parameter is true if value was found, otherwise false.
|
||||||
|
func (m *Map) GetKey(value interface{}) (key interface{}, found bool) {
|
||||||
|
if d, ok := m.inverseMap.Get(value); ok {
|
||||||
|
return d.(*data).key, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the element from the map by key.
|
||||||
|
func (m *Map) Remove(key interface{}) {
|
||||||
|
if d, found := m.forwardMap.Get(key); found {
|
||||||
|
m.forwardMap.Remove(key)
|
||||||
|
m.inverseMap.Remove(d.(*data).value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if map does not contain any elements
|
||||||
|
func (m *Map) Empty() bool {
|
||||||
|
return m.Size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements in the map.
|
||||||
|
func (m *Map) Size() int {
|
||||||
|
return m.forwardMap.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys (ordered).
|
||||||
|
func (m *Map) Keys() []interface{} {
|
||||||
|
return m.forwardMap.Keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all values (ordered).
|
||||||
|
func (m *Map) Values() []interface{} {
|
||||||
|
return m.inverseMap.Keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the map.
|
||||||
|
func (m *Map) Clear() {
|
||||||
|
m.forwardMap.Clear()
|
||||||
|
m.inverseMap.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (m *Map) String() string {
|
||||||
|
str := "TreeBidiMap\nmap["
|
||||||
|
it := m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
str += fmt.Sprintf("%v:%v ", it.Key(), it.Value())
|
||||||
|
}
|
||||||
|
return strings.TrimRight(str, " ") + "]"
|
||||||
|
}
|
658
vendor/github.com/emirpasic/gods/maps/treebidimap/treebidimap_test.go
generated
vendored
Normal file
658
vendor/github.com/emirpasic/gods/maps/treebidimap/treebidimap_test.go
generated
vendored
Normal file
|
@ -0,0 +1,658 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treebidimap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapPut(t *testing.T) {
|
||||||
|
m := NewWith(utils.IntComparator, utils.StringComparator)
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
if actualValue := m.Size(); actualValue != 7 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// key,expectedValue,expectedFound
|
||||||
|
tests1 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, "e", true},
|
||||||
|
{6, "f", true},
|
||||||
|
{7, "g", true},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests1 {
|
||||||
|
// retrievals
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapRemove(t *testing.T) {
|
||||||
|
m := NewWith(utils.IntComparator, utils.StringComparator)
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
m.Remove(5)
|
||||||
|
m.Remove(6)
|
||||||
|
m.Remove(7)
|
||||||
|
m.Remove(8)
|
||||||
|
m.Remove(5)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests2 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, nil, false},
|
||||||
|
{6, nil, false},
|
||||||
|
{7, nil, false},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests2 {
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Remove(1)
|
||||||
|
m.Remove(4)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(3)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(2)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
if actualValue := m.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapGetKey(t *testing.T) {
|
||||||
|
m := NewWith(utils.IntComparator, utils.StringComparator)
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
// key,expectedValue,expectedFound
|
||||||
|
tests1 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, "e", true},
|
||||||
|
{6, "f", true},
|
||||||
|
{7, "g", true},
|
||||||
|
{nil, "x", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests1 {
|
||||||
|
// retrievals
|
||||||
|
actualValue, actualFound := m.GetKey(test[1])
|
||||||
|
if actualValue != test[0] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sameElements(a []interface{}, b []interface{}) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, av := range a {
|
||||||
|
found := false
|
||||||
|
for _, bv := range b {
|
||||||
|
if av == bv {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapEach(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
count := 0
|
||||||
|
m.Each(func(key interface{}, value interface{}) {
|
||||||
|
count++
|
||||||
|
if actualValue, expectedValue := count, value; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
switch value {
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := key, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := key, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
if actualValue, expectedValue := key, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapMap(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
mappedMap := m.Map(func(key1 interface{}, value1 interface{}) (key2 interface{}, value2 interface{}) {
|
||||||
|
return key1, value1.(int) * value1.(int)
|
||||||
|
})
|
||||||
|
if actualValue, _ := mappedMap.Get("a"); actualValue != 1 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedMap.Get("b"); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: b")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedMap.Get("c"); actualValue != 9 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: c")
|
||||||
|
}
|
||||||
|
if mappedMap.Size() != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", mappedMap.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapSelect(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
selectedMap := m.Select(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "b"
|
||||||
|
})
|
||||||
|
if actualValue, _ := selectedMap.Get("a"); actualValue != 1 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := selectedMap.Get("b"); actualValue != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: b")
|
||||||
|
}
|
||||||
|
if selectedMap.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", selectedMap.Size(), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapAny(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
any := m.Any(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) == 3
|
||||||
|
})
|
||||||
|
if any != true {
|
||||||
|
t.Errorf("Got %v expected %v", any, true)
|
||||||
|
}
|
||||||
|
any = m.Any(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) == 4
|
||||||
|
})
|
||||||
|
if any != false {
|
||||||
|
t.Errorf("Got %v expected %v", any, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapAll(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
all := m.All(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "c"
|
||||||
|
})
|
||||||
|
if all != true {
|
||||||
|
t.Errorf("Got %v expected %v", all, true)
|
||||||
|
}
|
||||||
|
all = m.All(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "b"
|
||||||
|
})
|
||||||
|
if all != false {
|
||||||
|
t.Errorf("Got %v expected %v", all, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFind(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
foundKey, foundValue := m.Find(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) == "c"
|
||||||
|
})
|
||||||
|
if foundKey != "c" || foundValue != 3 {
|
||||||
|
t.Errorf("Got %v -> %v expected %v -> %v", foundKey, foundValue, "c", 3)
|
||||||
|
}
|
||||||
|
foundKey, foundValue = m.Find(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) == "x"
|
||||||
|
})
|
||||||
|
if foundKey != nil || foundValue != nil {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundKey, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapChaining(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
chainedMap := m.Select(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) > 1
|
||||||
|
}).Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
|
||||||
|
return key.(string) + key.(string), value.(int) * value.(int)
|
||||||
|
})
|
||||||
|
if actualValue := chainedMap.Size(); actualValue != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("aa"); actualValue != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("bb"); actualValue != 4 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("cc"); actualValue != 9 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 9)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
m := NewWithStringComparators()
|
||||||
|
it := m.Iterator()
|
||||||
|
it = m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorPrevOnEmpty(t *testing.T) {
|
||||||
|
m := NewWithStringComparators()
|
||||||
|
it := m.Iterator()
|
||||||
|
it = m.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorNext(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
|
||||||
|
it := m.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
value := it.Value()
|
||||||
|
switch key {
|
||||||
|
case "a":
|
||||||
|
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "b":
|
||||||
|
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "c":
|
||||||
|
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorPrev(t *testing.T) {
|
||||||
|
m := NewWith(utils.StringComparator, utils.IntComparator)
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
|
||||||
|
it := m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := m.Size()
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
value := it.Value()
|
||||||
|
switch key {
|
||||||
|
case "a":
|
||||||
|
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "b":
|
||||||
|
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "c":
|
||||||
|
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := value, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorBegin(t *testing.T) {
|
||||||
|
m := NewWith(utils.IntComparator, utils.StringComparator)
|
||||||
|
it := m.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapTreeIteratorEnd(t *testing.T) {
|
||||||
|
m := NewWith(utils.IntComparator, utils.StringComparator)
|
||||||
|
it := m.Iterator()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it.End()
|
||||||
|
it.Prev()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorFirst(t *testing.T) {
|
||||||
|
m := NewWith(utils.IntComparator, utils.StringComparator)
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it := m.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorLast(t *testing.T) {
|
||||||
|
m := NewWith(utils.IntComparator, utils.StringComparator)
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it := m.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapSerialization(t *testing.T) {
|
||||||
|
m := NewWithStringComparators()
|
||||||
|
m.Put("a", "1")
|
||||||
|
m.Put("b", "2")
|
||||||
|
m.Put("c", "3")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue := m.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[a,b,c]")
|
||||||
|
}
|
||||||
|
if actualValue := m.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := m.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = m.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPut(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapPut100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapPut1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapPut10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapPut100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeBidiMapRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := NewWithIntComparators()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
83
vendor/github.com/emirpasic/gods/maps/treemap/enumerable.go
generated
vendored
Normal file
83
vendor/github.com/emirpasic/gods/maps/treemap/enumerable.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treemap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertEnumerableImplementation() {
|
||||||
|
var _ containers.EnumerableWithKey = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each calls the given function once for each element, passing that element's key and value.
|
||||||
|
func (m *Map) Each(f func(key interface{}, value interface{})) {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
f(iterator.Key(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a container
|
||||||
|
// containing the values returned by the given function as key/value pairs.
|
||||||
|
func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, interface{})) *Map {
|
||||||
|
newMap := &Map{tree: rbt.NewWith(m.tree.Comparator)}
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
key2, value2 := f(iterator.Key(), iterator.Value())
|
||||||
|
newMap.Put(key2, value2)
|
||||||
|
}
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map {
|
||||||
|
newMap := &Map{tree: rbt.NewWith(m.tree.Comparator)}
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
newMap.Put(iterator.Key(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any passes each element of the container to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
func (m *Map) Any(f func(key interface{}, value interface{}) bool) bool {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// All passes each element of the container to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
func (m *Map) All(f func(key interface{}, value interface{}) bool) bool {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if !f(iterator.Key(), iterator.Value()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (key,value) for which the function is true or nil,nil otherwise if no element
|
||||||
|
// matches the criteria.
|
||||||
|
func (m *Map) Find(f func(key interface{}, value interface{}) bool) (interface{}, interface{}) {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
return iterator.Key(), iterator.Value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
77
vendor/github.com/emirpasic/gods/maps/treemap/iterator.go
generated
vendored
Normal file
77
vendor/github.com/emirpasic/gods/maps/treemap/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treemap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
iterator rbt.Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose elements are key/value pairs.
|
||||||
|
func (m *Map) Iterator() Iterator {
|
||||||
|
return Iterator{iterator: m.tree.Iterator()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
return iterator.iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
return iterator.iterator.Prev()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
return iterator.iterator.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the current element's key.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Key() interface{} {
|
||||||
|
return iterator.iterator.Key()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.iterator.Begin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.iterator.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
return iterator.iterator.First()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
return iterator.iterator.Last()
|
||||||
|
}
|
22
vendor/github.com/emirpasic/gods/maps/treemap/serialization.go
generated
vendored
Normal file
22
vendor/github.com/emirpasic/gods/maps/treemap/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treemap
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Map)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
|
return m.tree.ToJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
|
return m.tree.FromJSON(data)
|
||||||
|
}
|
117
vendor/github.com/emirpasic/gods/maps/treemap/treemap.go
generated
vendored
Normal file
117
vendor/github.com/emirpasic/gods/maps/treemap/treemap.go
generated
vendored
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package treemap implements a map backed by red-black tree.
|
||||||
|
//
|
||||||
|
// Elements are ordered by key in the map.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: http://en.wikipedia.org/wiki/Associative_array
|
||||||
|
package treemap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/maps"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertMapImplementation() {
|
||||||
|
var _ maps.Map = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map holds the elements in a red-black tree
|
||||||
|
type Map struct {
|
||||||
|
tree *rbt.Tree
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWith instantiates a tree map with the custom comparator.
|
||||||
|
func NewWith(comparator utils.Comparator) *Map {
|
||||||
|
return &Map{tree: rbt.NewWith(comparator)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithIntComparator instantiates a tree map with the IntComparator, i.e. keys are of type int.
|
||||||
|
func NewWithIntComparator() *Map {
|
||||||
|
return &Map{tree: rbt.NewWithIntComparator()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithStringComparator instantiates a tree map with the StringComparator, i.e. keys are of type string.
|
||||||
|
func NewWithStringComparator() *Map {
|
||||||
|
return &Map{tree: rbt.NewWithStringComparator()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put inserts key-value pair into the map.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (m *Map) Put(key interface{}, value interface{}) {
|
||||||
|
m.tree.Put(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get searches the element in the map by key and returns its value or nil if key is not found in tree.
|
||||||
|
// Second return parameter is true if key was found, otherwise false.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (m *Map) Get(key interface{}) (value interface{}, found bool) {
|
||||||
|
return m.tree.Get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the element from the map by key.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (m *Map) Remove(key interface{}) {
|
||||||
|
m.tree.Remove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if map does not contain any elements
|
||||||
|
func (m *Map) Empty() bool {
|
||||||
|
return m.tree.Empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements in the map.
|
||||||
|
func (m *Map) Size() int {
|
||||||
|
return m.tree.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys in-order
|
||||||
|
func (m *Map) Keys() []interface{} {
|
||||||
|
return m.tree.Keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all values in-order based on the key.
|
||||||
|
func (m *Map) Values() []interface{} {
|
||||||
|
return m.tree.Values()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the map.
|
||||||
|
func (m *Map) Clear() {
|
||||||
|
m.tree.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Min returns the minimum key and its value from the tree map.
|
||||||
|
// Returns nil, nil if map is empty.
|
||||||
|
func (m *Map) Min() (key interface{}, value interface{}) {
|
||||||
|
if node := m.tree.Left(); node != nil {
|
||||||
|
return node.Key, node.Value
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max returns the maximum key and its value from the tree map.
|
||||||
|
// Returns nil, nil if map is empty.
|
||||||
|
func (m *Map) Max() (key interface{}, value interface{}) {
|
||||||
|
if node := m.tree.Right(); node != nil {
|
||||||
|
return node.Key, node.Value
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (m *Map) String() string {
|
||||||
|
str := "TreeMap\nmap["
|
||||||
|
it := m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
str += fmt.Sprintf("%v:%v ", it.Key(), it.Value())
|
||||||
|
}
|
||||||
|
return strings.TrimRight(str, " ") + "]"
|
||||||
|
|
||||||
|
}
|
625
vendor/github.com/emirpasic/gods/maps/treemap/treemap_test.go
generated
vendored
Normal file
625
vendor/github.com/emirpasic/gods/maps/treemap/treemap_test.go
generated
vendored
Normal file
|
@ -0,0 +1,625 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treemap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapPut(t *testing.T) {
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
if actualValue := m.Size(); actualValue != 7 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// key,expectedValue,expectedFound
|
||||||
|
tests1 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, "e", true},
|
||||||
|
{6, "f", true},
|
||||||
|
{7, "g", true},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests1 {
|
||||||
|
// retrievals
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapRemove(t *testing.T) {
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
m.Put(5, "e")
|
||||||
|
m.Put(6, "f")
|
||||||
|
m.Put(7, "g")
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(4, "d")
|
||||||
|
m.Put(1, "x")
|
||||||
|
m.Put(2, "b")
|
||||||
|
m.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
m.Remove(5)
|
||||||
|
m.Remove(6)
|
||||||
|
m.Remove(7)
|
||||||
|
m.Remove(8)
|
||||||
|
m.Remove(5)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests2 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, nil, false},
|
||||||
|
{6, nil, false},
|
||||||
|
{7, nil, false},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests2 {
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Remove(1)
|
||||||
|
m.Remove(4)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(3)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(2)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
if actualValue := m.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sameElements(a []interface{}, b []interface{}) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, av := range a {
|
||||||
|
found := false
|
||||||
|
for _, bv := range b {
|
||||||
|
if av == bv {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapEach(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
count := 0
|
||||||
|
m.Each(func(key interface{}, value interface{}) {
|
||||||
|
count++
|
||||||
|
if actualValue, expectedValue := count, value; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
switch value {
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := key, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := key, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
if actualValue, expectedValue := key, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapMap(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
mappedMap := m.Map(func(key1 interface{}, value1 interface{}) (key2 interface{}, value2 interface{}) {
|
||||||
|
return key1, value1.(int) * value1.(int)
|
||||||
|
})
|
||||||
|
if actualValue, _ := mappedMap.Get("a"); actualValue != 1 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedMap.Get("b"); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: b")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedMap.Get("c"); actualValue != 9 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: c")
|
||||||
|
}
|
||||||
|
if mappedMap.Size() != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", mappedMap.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapSelect(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
selectedMap := m.Select(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "b"
|
||||||
|
})
|
||||||
|
if actualValue, _ := selectedMap.Get("a"); actualValue != 1 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := selectedMap.Get("b"); actualValue != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: b")
|
||||||
|
}
|
||||||
|
if selectedMap.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", selectedMap.Size(), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapAny(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
any := m.Any(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) == 3
|
||||||
|
})
|
||||||
|
if any != true {
|
||||||
|
t.Errorf("Got %v expected %v", any, true)
|
||||||
|
}
|
||||||
|
any = m.Any(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) == 4
|
||||||
|
})
|
||||||
|
if any != false {
|
||||||
|
t.Errorf("Got %v expected %v", any, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapAll(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
all := m.All(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "c"
|
||||||
|
})
|
||||||
|
if all != true {
|
||||||
|
t.Errorf("Got %v expected %v", all, true)
|
||||||
|
}
|
||||||
|
all = m.All(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "b"
|
||||||
|
})
|
||||||
|
if all != false {
|
||||||
|
t.Errorf("Got %v expected %v", all, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFind(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
foundKey, foundValue := m.Find(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) == "c"
|
||||||
|
})
|
||||||
|
if foundKey != "c" || foundValue != 3 {
|
||||||
|
t.Errorf("Got %v -> %v expected %v -> %v", foundKey, foundValue, "c", 3)
|
||||||
|
}
|
||||||
|
foundKey, foundValue = m.Find(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) == "x"
|
||||||
|
})
|
||||||
|
if foundKey != nil || foundValue != nil {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundKey, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapChaining(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
chainedMap := m.Select(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) > 1
|
||||||
|
}).Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
|
||||||
|
return key.(string) + key.(string), value.(int) * value.(int)
|
||||||
|
})
|
||||||
|
if actualValue := chainedMap.Size(); actualValue != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("aa"); actualValue != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("bb"); actualValue != 4 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("cc"); actualValue != 9 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 9)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
it := m.Iterator()
|
||||||
|
it = m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorPrevOnEmpty(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
it := m.Iterator()
|
||||||
|
it = m.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorNext(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
|
||||||
|
it := m.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
value := it.Value()
|
||||||
|
switch key {
|
||||||
|
case "a":
|
||||||
|
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "b":
|
||||||
|
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "c":
|
||||||
|
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorPrev(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
|
||||||
|
it := m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := m.Size()
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
value := it.Value()
|
||||||
|
switch key {
|
||||||
|
case "a":
|
||||||
|
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "b":
|
||||||
|
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "c":
|
||||||
|
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := value, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorBegin(t *testing.T) {
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
it := m.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapTreeIteratorEnd(t *testing.T) {
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
it := m.Iterator()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it.End()
|
||||||
|
it.Prev()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorFirst(t *testing.T) {
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it := m.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorLast(t *testing.T) {
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it := m.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapSerialization(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
m.Put("a", "1")
|
||||||
|
m.Put("b", "2")
|
||||||
|
m.Put("c", "3")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue := m.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[a,b,c]")
|
||||||
|
}
|
||||||
|
if actualValue := m.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := m.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = m.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPut(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapPut100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapPut1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapPut10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapPut100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
95
vendor/github.com/emirpasic/gods/sets/hashset/hashset.go
generated
vendored
Normal file
95
vendor/github.com/emirpasic/gods/sets/hashset/hashset.go
generated
vendored
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package hashset implements a set backed by a hash table.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// References: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29
|
||||||
|
package hashset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/sets"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSetImplementation() {
|
||||||
|
var _ sets.Set = (*Set)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set holds elements in go's native map
|
||||||
|
type Set struct {
|
||||||
|
items map[interface{}]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemExists = struct{}{}
|
||||||
|
|
||||||
|
// New instantiates a new empty set
|
||||||
|
func New() *Set {
|
||||||
|
return &Set{items: make(map[interface{}]struct{})}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the items (one or more) to the set.
|
||||||
|
func (set *Set) Add(items ...interface{}) {
|
||||||
|
for _, item := range items {
|
||||||
|
set.items[item] = itemExists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the items (one or more) from the set.
|
||||||
|
func (set *Set) Remove(items ...interface{}) {
|
||||||
|
for _, item := range items {
|
||||||
|
delete(set.items, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains check if items (one or more) are present in the set.
|
||||||
|
// All items have to be present in the set for the method to return true.
|
||||||
|
// Returns true if no arguments are passed at all, i.e. set is always superset of empty set.
|
||||||
|
func (set *Set) Contains(items ...interface{}) bool {
|
||||||
|
for _, item := range items {
|
||||||
|
if _, contains := set.items[item]; !contains {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if set does not contain any elements.
|
||||||
|
func (set *Set) Empty() bool {
|
||||||
|
return set.Size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements within the set.
|
||||||
|
func (set *Set) Size() int {
|
||||||
|
return len(set.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clears all values in the set.
|
||||||
|
func (set *Set) Clear() {
|
||||||
|
set.items = make(map[interface{}]struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all items in the set.
|
||||||
|
func (set *Set) Values() []interface{} {
|
||||||
|
values := make([]interface{}, set.Size())
|
||||||
|
count := 0
|
||||||
|
for item := range set.items {
|
||||||
|
values[count] = item
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (set *Set) String() string {
|
||||||
|
str := "HashSet\n"
|
||||||
|
items := []string{}
|
||||||
|
for k := range set.items {
|
||||||
|
items = append(items, fmt.Sprintf("%v", k))
|
||||||
|
}
|
||||||
|
str += strings.Join(items, ", ")
|
||||||
|
return str
|
||||||
|
}
|
242
vendor/github.com/emirpasic/gods/sets/hashset/hashset_test.go
generated
vendored
Normal file
242
vendor/github.com/emirpasic/gods/sets/hashset/hashset_test.go
generated
vendored
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hashset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSetAdd(t *testing.T) {
|
||||||
|
set := New()
|
||||||
|
set.Add()
|
||||||
|
set.Add(1)
|
||||||
|
set.Add(2)
|
||||||
|
set.Add(2, 3)
|
||||||
|
set.Add()
|
||||||
|
if actualValue := set.Empty(); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := set.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetContains(t *testing.T) {
|
||||||
|
set := New()
|
||||||
|
set.Add(3, 1, 2)
|
||||||
|
set.Add(2, 3)
|
||||||
|
set.Add()
|
||||||
|
if actualValue := set.Contains(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := set.Contains(1); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := set.Contains(1, 2, 3); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := set.Contains(1, 2, 3, 4); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetRemove(t *testing.T) {
|
||||||
|
set := New()
|
||||||
|
set.Add(3, 1, 2)
|
||||||
|
set.Remove()
|
||||||
|
if actualValue := set.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
set.Remove(1)
|
||||||
|
if actualValue := set.Size(); actualValue != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
set.Remove(3)
|
||||||
|
set.Remove(3)
|
||||||
|
set.Remove()
|
||||||
|
set.Remove(2)
|
||||||
|
if actualValue := set.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetSerialization(t *testing.T) {
|
||||||
|
set := New()
|
||||||
|
set.Add("a", "b", "c")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := set.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := set.Contains("a", "b", "c"); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := set.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = set.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkContains(b *testing.B, set *Set, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Contains(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkAdd(b *testing.B, set *Set, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, set *Set, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetContains100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkContains(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetContains1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkContains(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetContains10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkContains(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetContains100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkContains(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetAdd100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
set := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetAdd1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetAdd10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetAdd100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHashSetRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
set := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, set, size)
|
||||||
|
}
|
31
vendor/github.com/emirpasic/gods/sets/hashset/serialization.go
generated
vendored
Normal file
31
vendor/github.com/emirpasic/gods/sets/hashset/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package hashset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Set)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Set)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (set *Set) ToJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(set.Values())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (set *Set) FromJSON(data []byte) error {
|
||||||
|
elements := []interface{}{}
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
set.Clear()
|
||||||
|
set.Add(elements...)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
25
vendor/github.com/emirpasic/gods/sets/sets.go
generated
vendored
Normal file
25
vendor/github.com/emirpasic/gods/sets/sets.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package sets provides an abstract Set interface.
|
||||||
|
//
|
||||||
|
// In computer science, a set is an abstract data type that can store certain values and no repeated values. It is a computer implementation of the mathematical concept of a finite set. Unlike most other collection types, rather than retrieving a specific element from a set, one typically tests a value for membership in a set.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/Set_%28abstract_data_type%29
|
||||||
|
package sets
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
// Set interface that all sets implement
|
||||||
|
type Set interface {
|
||||||
|
Add(elements ...interface{})
|
||||||
|
Remove(elements ...interface{})
|
||||||
|
Contains(elements ...interface{}) bool
|
||||||
|
|
||||||
|
containers.Container
|
||||||
|
// Empty() bool
|
||||||
|
// Size() int
|
||||||
|
// Clear()
|
||||||
|
// Values() []interface{}
|
||||||
|
}
|
82
vendor/github.com/emirpasic/gods/sets/treeset/enumerable.go
generated
vendored
Normal file
82
vendor/github.com/emirpasic/gods/sets/treeset/enumerable.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treeset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertEnumerableImplementation() {
|
||||||
|
var _ containers.EnumerableWithIndex = (*Set)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each calls the given function once for each element, passing that element's index and value.
|
||||||
|
func (set *Set) Each(f func(index int, value interface{})) {
|
||||||
|
iterator := set.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
f(iterator.Index(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a
|
||||||
|
// container containing the values returned by the given function.
|
||||||
|
func (set *Set) Map(f func(index int, value interface{}) interface{}) *Set {
|
||||||
|
newSet := &Set{tree: rbt.NewWith(set.tree.Comparator)}
|
||||||
|
iterator := set.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
newSet.Add(f(iterator.Index(), iterator.Value()))
|
||||||
|
}
|
||||||
|
return newSet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
func (set *Set) Select(f func(index int, value interface{}) bool) *Set {
|
||||||
|
newSet := &Set{tree: rbt.NewWith(set.tree.Comparator)}
|
||||||
|
iterator := set.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
newSet.Add(iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newSet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any passes each element of the container to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
func (set *Set) Any(f func(index int, value interface{}) bool) bool {
|
||||||
|
iterator := set.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// All passes each element of the container to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
func (set *Set) All(f func(index int, value interface{}) bool) bool {
|
||||||
|
iterator := set.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if !f(iterator.Index(), iterator.Value()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (index,value) for which the function is true or -1,nil otherwise
|
||||||
|
// if no element matches the criteria.
|
||||||
|
func (set *Set) Find(f func(index int, value interface{}) bool) (int, interface{}) {
|
||||||
|
iterator := set.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Index(), iterator.Value()) {
|
||||||
|
return iterator.Index(), iterator.Value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1, nil
|
||||||
|
}
|
89
vendor/github.com/emirpasic/gods/sets/treeset/iterator.go
generated
vendored
Normal file
89
vendor/github.com/emirpasic/gods/sets/treeset/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treeset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
type Iterator struct {
|
||||||
|
index int
|
||||||
|
iterator rbt.Iterator
|
||||||
|
tree *rbt.Tree
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
func (set *Set) Iterator() Iterator {
|
||||||
|
return Iterator{index: -1, iterator: set.tree.Iterator(), tree: set.tree}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
if iterator.index < iterator.tree.Size() {
|
||||||
|
iterator.index++
|
||||||
|
}
|
||||||
|
return iterator.iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
if iterator.index >= 0 {
|
||||||
|
iterator.index--
|
||||||
|
}
|
||||||
|
return iterator.iterator.Prev()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
return iterator.iterator.Key()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index returns the current element's index.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Index() int {
|
||||||
|
return iterator.index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.index = -1
|
||||||
|
iterator.iterator.Begin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.index = iterator.tree.Size()
|
||||||
|
iterator.iterator.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
iterator.End()
|
||||||
|
return iterator.iterator.Last()
|
||||||
|
}
|
31
vendor/github.com/emirpasic/gods/sets/treeset/serialization.go
generated
vendored
Normal file
31
vendor/github.com/emirpasic/gods/sets/treeset/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treeset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Set)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Set)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (set *Set) ToJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(set.Values())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (set *Set) FromJSON(data []byte) error {
|
||||||
|
elements := []interface{}{}
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
set.Clear()
|
||||||
|
set.Add(elements...)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
101
vendor/github.com/emirpasic/gods/sets/treeset/treeset.go
generated
vendored
Normal file
101
vendor/github.com/emirpasic/gods/sets/treeset/treeset.go
generated
vendored
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package treeset implements a tree backed by a red-black tree.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29
|
||||||
|
package treeset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/sets"
|
||||||
|
rbt "github.com/emirpasic/gods/trees/redblacktree"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSetImplementation() {
|
||||||
|
var _ sets.Set = (*Set)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set holds elements in a red-black tree
|
||||||
|
type Set struct {
|
||||||
|
tree *rbt.Tree
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemExists = struct{}{}
|
||||||
|
|
||||||
|
// NewWith instantiates a new empty set with the custom comparator.
|
||||||
|
func NewWith(comparator utils.Comparator) *Set {
|
||||||
|
return &Set{tree: rbt.NewWith(comparator)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithIntComparator instantiates a new empty set with the IntComparator, i.e. keys are of type int.
|
||||||
|
func NewWithIntComparator() *Set {
|
||||||
|
return &Set{tree: rbt.NewWithIntComparator()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithStringComparator instantiates a new empty set with the StringComparator, i.e. keys are of type string.
|
||||||
|
func NewWithStringComparator() *Set {
|
||||||
|
return &Set{tree: rbt.NewWithStringComparator()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the items (one or more) to the set.
|
||||||
|
func (set *Set) Add(items ...interface{}) {
|
||||||
|
for _, item := range items {
|
||||||
|
set.tree.Put(item, itemExists)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the items (one or more) from the set.
|
||||||
|
func (set *Set) Remove(items ...interface{}) {
|
||||||
|
for _, item := range items {
|
||||||
|
set.tree.Remove(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains checks weather items (one or more) are present in the set.
|
||||||
|
// All items have to be present in the set for the method to return true.
|
||||||
|
// Returns true if no arguments are passed at all, i.e. set is always superset of empty set.
|
||||||
|
func (set *Set) Contains(items ...interface{}) bool {
|
||||||
|
for _, item := range items {
|
||||||
|
if _, contains := set.tree.Get(item); !contains {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if set does not contain any elements.
|
||||||
|
func (set *Set) Empty() bool {
|
||||||
|
return set.tree.Size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements within the set.
|
||||||
|
func (set *Set) Size() int {
|
||||||
|
return set.tree.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clears all values in the set.
|
||||||
|
func (set *Set) Clear() {
|
||||||
|
set.tree.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all items in the set.
|
||||||
|
func (set *Set) Values() []interface{} {
|
||||||
|
return set.tree.Keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (set *Set) String() string {
|
||||||
|
str := "TreeSet\n"
|
||||||
|
items := []string{}
|
||||||
|
for _, v := range set.tree.Keys() {
|
||||||
|
items = append(items, fmt.Sprintf("%v", v))
|
||||||
|
}
|
||||||
|
str += strings.Join(items, ", ")
|
||||||
|
return str
|
||||||
|
}
|
507
vendor/github.com/emirpasic/gods/sets/treeset/treeset_test.go
generated
vendored
Normal file
507
vendor/github.com/emirpasic/gods/sets/treeset/treeset_test.go
generated
vendored
Normal file
|
@ -0,0 +1,507 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package treeset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSetAdd(t *testing.T) {
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
set.Add()
|
||||||
|
set.Add(1)
|
||||||
|
set.Add(2)
|
||||||
|
set.Add(2, 3)
|
||||||
|
set.Add()
|
||||||
|
if actualValue := set.Empty(); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := set.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d%d%d", set.Values()...), "123"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetContains(t *testing.T) {
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
set.Add(3, 1, 2)
|
||||||
|
if actualValue := set.Contains(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := set.Contains(1); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := set.Contains(1, 2, 3); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := set.Contains(1, 2, 3, 4); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetRemove(t *testing.T) {
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
set.Add(3, 1, 2)
|
||||||
|
set.Remove()
|
||||||
|
if actualValue := set.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
set.Remove(1)
|
||||||
|
if actualValue := set.Size(); actualValue != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
set.Remove(3)
|
||||||
|
set.Remove(3)
|
||||||
|
set.Remove()
|
||||||
|
set.Remove(2)
|
||||||
|
if actualValue := set.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetEach(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
set.Each(func(index int, value interface{}) {
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetMap(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
mappedSet := set.Map(func(index int, value interface{}) interface{} {
|
||||||
|
return "mapped: " + value.(string)
|
||||||
|
})
|
||||||
|
if actualValue, expectedValue := mappedSet.Contains("mapped: a", "mapped: b", "mapped: c"), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := mappedSet.Contains("mapped: a", "mapped: b", "mapped: x"), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if mappedSet.Size() != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", mappedSet.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetSelect(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
selectedSet := set.Select(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "b"
|
||||||
|
})
|
||||||
|
if actualValue, expectedValue := selectedSet.Contains("a", "b"), true; actualValue != expectedValue {
|
||||||
|
fmt.Println("A: ", selectedSet.Contains("b"))
|
||||||
|
t.Errorf("Got %v (%v) expected %v (%v)", actualValue, selectedSet.Values(), expectedValue, "[a b]")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := selectedSet.Contains("a", "b", "c"), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v (%v) expected %v (%v)", actualValue, selectedSet.Values(), expectedValue, "[a b]")
|
||||||
|
}
|
||||||
|
if selectedSet.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", selectedSet.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAny(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
any := set.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "c"
|
||||||
|
})
|
||||||
|
if any != true {
|
||||||
|
t.Errorf("Got %v expected %v", any, true)
|
||||||
|
}
|
||||||
|
any = set.Any(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "x"
|
||||||
|
})
|
||||||
|
if any != false {
|
||||||
|
t.Errorf("Got %v expected %v", any, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAll(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
all := set.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "c"
|
||||||
|
})
|
||||||
|
if all != true {
|
||||||
|
t.Errorf("Got %v expected %v", all, true)
|
||||||
|
}
|
||||||
|
all = set.All(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) >= "a" && value.(string) <= "b"
|
||||||
|
})
|
||||||
|
if all != false {
|
||||||
|
t.Errorf("Got %v expected %v", all, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetFind(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
foundIndex, foundValue := set.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "c"
|
||||||
|
})
|
||||||
|
if foundValue != "c" || foundIndex != 2 {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 2)
|
||||||
|
}
|
||||||
|
foundIndex, foundValue = set.Find(func(index int, value interface{}) bool {
|
||||||
|
return value.(string) == "x"
|
||||||
|
})
|
||||||
|
if foundValue != nil || foundIndex != -1 {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetChaining(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
it := set.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetIteratorPrevOnEmpty(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
it := set.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetIteratorNext(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
it := set.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetIteratorPrev(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("c", "a", "b")
|
||||||
|
it := set.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetIteratorBegin(t *testing.T) {
|
||||||
|
m := NewWithStringComparator()
|
||||||
|
it := m.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
m.Add("a", "b", "c")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetIteratorEnd(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
it := set.Iterator()
|
||||||
|
|
||||||
|
if index := it.Index(); index != -1 {
|
||||||
|
t.Errorf("Got %v expected %v", index, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", index, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
set.Add("a", "b", "c")
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != set.Size() {
|
||||||
|
t.Errorf("Got %v expected %v", index, set.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Prev()
|
||||||
|
if index, value := it.Index(), it.Value(); index != set.Size()-1 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, set.Size()-1, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetIteratorFirst(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("a", "b", "c")
|
||||||
|
it := set.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetIteratorLast(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("a", "b", "c")
|
||||||
|
it := set.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetSerialization(t *testing.T) {
|
||||||
|
set := NewWithStringComparator()
|
||||||
|
set.Add("a", "b", "c")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := set.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := set.Contains("a", "b", "c"); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := set.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = set.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkContains(b *testing.B, set *Set, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Contains(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkAdd(b *testing.B, set *Set, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, set *Set, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetContains100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkContains(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetContains1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkContains(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetContains10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkContains(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetContains100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkContains(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetAdd100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetAdd1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetAdd10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetAdd100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkAdd(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, set, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeSetRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
set := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
set.Add(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, set, size)
|
||||||
|
}
|
91
vendor/github.com/emirpasic/gods/stacks/arraystack/arraystack.go
generated
vendored
Normal file
91
vendor/github.com/emirpasic/gods/stacks/arraystack/arraystack.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package arraystack implements a stack backed by array list.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29#Array
|
||||||
|
package arraystack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/lists/arraylist"
|
||||||
|
"github.com/emirpasic/gods/stacks"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertStackImplementation() {
|
||||||
|
var _ stacks.Stack = (*Stack)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stack holds elements in an array-list
|
||||||
|
type Stack struct {
|
||||||
|
list *arraylist.List
|
||||||
|
}
|
||||||
|
|
||||||
|
// New instantiates a new empty stack
|
||||||
|
func New() *Stack {
|
||||||
|
return &Stack{list: arraylist.New()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push adds a value onto the top of the stack
|
||||||
|
func (stack *Stack) Push(value interface{}) {
|
||||||
|
stack.list.Add(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop removes top element on stack and returns it, or nil if stack is empty.
|
||||||
|
// Second return parameter is true, unless the stack was empty and there was nothing to pop.
|
||||||
|
func (stack *Stack) Pop() (value interface{}, ok bool) {
|
||||||
|
value, ok = stack.list.Get(stack.list.Size() - 1)
|
||||||
|
stack.list.Remove(stack.list.Size() - 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peek returns top element on the stack without removing it, or nil if stack is empty.
|
||||||
|
// Second return parameter is true, unless the stack was empty and there was nothing to peek.
|
||||||
|
func (stack *Stack) Peek() (value interface{}, ok bool) {
|
||||||
|
return stack.list.Get(stack.list.Size() - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if stack does not contain any elements.
|
||||||
|
func (stack *Stack) Empty() bool {
|
||||||
|
return stack.list.Empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements within the stack.
|
||||||
|
func (stack *Stack) Size() int {
|
||||||
|
return stack.list.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the stack.
|
||||||
|
func (stack *Stack) Clear() {
|
||||||
|
stack.list.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all elements in the stack (LIFO order).
|
||||||
|
func (stack *Stack) Values() []interface{} {
|
||||||
|
size := stack.list.Size()
|
||||||
|
elements := make([]interface{}, size, size)
|
||||||
|
for i := 1; i <= size; i++ {
|
||||||
|
elements[size-i], _ = stack.list.Get(i - 1) // in reverse (LIFO)
|
||||||
|
}
|
||||||
|
return elements
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (stack *Stack) String() string {
|
||||||
|
str := "ArrayStack\n"
|
||||||
|
values := []string{}
|
||||||
|
for _, value := range stack.list.Values() {
|
||||||
|
values = append(values, fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
|
str += strings.Join(values, ", ")
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the index is within bounds of the list
|
||||||
|
func (stack *Stack) withinRange(index int) bool {
|
||||||
|
return index >= 0 && index < stack.list.Size()
|
||||||
|
}
|
362
vendor/github.com/emirpasic/gods/stacks/arraystack/arraystack_test.go
generated
vendored
Normal file
362
vendor/github.com/emirpasic/gods/stacks/arraystack/arraystack_test.go
generated
vendored
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package arraystack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackPush(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
if actualValue := stack.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
stack.Push(1)
|
||||||
|
stack.Push(2)
|
||||||
|
stack.Push(3)
|
||||||
|
|
||||||
|
if actualValue := stack.Values(); actualValue[0].(int) != 3 || actualValue[1].(int) != 2 || actualValue[2].(int) != 1 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[3,2,1]")
|
||||||
|
}
|
||||||
|
if actualValue := stack.Empty(); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := stack.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, ok := stack.Peek(); actualValue != 3 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackPeek(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
if actualValue, ok := stack.Peek(); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
stack.Push(1)
|
||||||
|
stack.Push(2)
|
||||||
|
stack.Push(3)
|
||||||
|
if actualValue, ok := stack.Peek(); actualValue != 3 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackPop(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
stack.Push(1)
|
||||||
|
stack.Push(2)
|
||||||
|
stack.Push(3)
|
||||||
|
stack.Pop()
|
||||||
|
if actualValue, ok := stack.Peek(); actualValue != 2 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := stack.Pop(); actualValue != 2 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := stack.Pop(); actualValue != 1 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 1)
|
||||||
|
}
|
||||||
|
if actualValue, ok := stack.Pop(); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
if actualValue := stack.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := stack.Values(); len(actualValue) != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorOnEmpty(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
it := stack.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty stack")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorNext(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
|
||||||
|
it := stack.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorPrev(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
|
||||||
|
it := stack.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
for it.Prev() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := index, 3-count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorBegin(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
it := stack.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorEnd(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
it := stack.Iterator()
|
||||||
|
|
||||||
|
if index := it.Index(); index != -1 {
|
||||||
|
t.Errorf("Got %v expected %v", index, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", index, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != stack.Size() {
|
||||||
|
t.Errorf("Got %v expected %v", index, stack.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Prev()
|
||||||
|
if index, value := it.Index(), it.Value(); index != stack.Size()-1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, stack.Size()-1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorFirst(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
it := stack.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorLast(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
it := stack.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 2 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackSerialization(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", stack.Values()...), "cba"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := stack.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := stack.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = stack.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPush(b *testing.B, stack *Stack, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPop(b *testing.B, stack *Stack, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayStackPop100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayStackPop1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayStackPop10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayStackPop100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayStackPush100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
stack := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayStackPush1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayStackPush10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArrayStackPush100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, stack, size)
|
||||||
|
}
|
84
vendor/github.com/emirpasic/gods/stacks/arraystack/iterator.go
generated
vendored
Normal file
84
vendor/github.com/emirpasic/gods/stacks/arraystack/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package arraystack
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
type Iterator struct {
|
||||||
|
stack *Stack
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
func (stack *Stack) Iterator() Iterator {
|
||||||
|
return Iterator{stack: stack, index: -1}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
if iterator.index < iterator.stack.Size() {
|
||||||
|
iterator.index++
|
||||||
|
}
|
||||||
|
return iterator.stack.withinRange(iterator.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
if iterator.index >= 0 {
|
||||||
|
iterator.index--
|
||||||
|
}
|
||||||
|
return iterator.stack.withinRange(iterator.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
value, _ := iterator.stack.list.Get(iterator.stack.list.Size() - iterator.index - 1) // in reverse (LIFO)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index returns the current element's index.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Index() int {
|
||||||
|
return iterator.index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.index = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.index = iterator.stack.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
iterator.End()
|
||||||
|
return iterator.Prev()
|
||||||
|
}
|
22
vendor/github.com/emirpasic/gods/stacks/arraystack/serialization.go
generated
vendored
Normal file
22
vendor/github.com/emirpasic/gods/stacks/arraystack/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package arraystack
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Stack)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Stack)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (stack *Stack) ToJSON() ([]byte, error) {
|
||||||
|
return stack.list.ToJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (stack *Stack) FromJSON(data []byte) error {
|
||||||
|
return stack.list.FromJSON(data)
|
||||||
|
}
|
60
vendor/github.com/emirpasic/gods/stacks/linkedliststack/iterator.go
generated
vendored
Normal file
60
vendor/github.com/emirpasic/gods/stacks/linkedliststack/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package linkedliststack
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.IteratorWithIndex = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
type Iterator struct {
|
||||||
|
stack *Stack
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
func (stack *Stack) Iterator() Iterator {
|
||||||
|
return Iterator{stack: stack, index: -1}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
if iterator.index < iterator.stack.Size() {
|
||||||
|
iterator.index++
|
||||||
|
}
|
||||||
|
return iterator.stack.withinRange(iterator.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
value, _ := iterator.stack.list.Get(iterator.index) // in reverse (LIFO)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index returns the current element's index.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Index() int {
|
||||||
|
return iterator.index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.index = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
86
vendor/github.com/emirpasic/gods/stacks/linkedliststack/linkedliststack.go
generated
vendored
Normal file
86
vendor/github.com/emirpasic/gods/stacks/linkedliststack/linkedliststack.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package linkedliststack implements a stack backed by a singly-linked list.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference:https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29#Linked_list
|
||||||
|
package linkedliststack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/lists/singlylinkedlist"
|
||||||
|
"github.com/emirpasic/gods/stacks"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertStackImplementation() {
|
||||||
|
var _ stacks.Stack = (*Stack)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stack holds elements in a singly-linked-list
|
||||||
|
type Stack struct {
|
||||||
|
list *singlylinkedlist.List
|
||||||
|
}
|
||||||
|
|
||||||
|
// New nnstantiates a new empty stack
|
||||||
|
func New() *Stack {
|
||||||
|
return &Stack{list: &singlylinkedlist.List{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push adds a value onto the top of the stack
|
||||||
|
func (stack *Stack) Push(value interface{}) {
|
||||||
|
stack.list.Prepend(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop removes top element on stack and returns it, or nil if stack is empty.
|
||||||
|
// Second return parameter is true, unless the stack was empty and there was nothing to pop.
|
||||||
|
func (stack *Stack) Pop() (value interface{}, ok bool) {
|
||||||
|
value, ok = stack.list.Get(0)
|
||||||
|
stack.list.Remove(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peek returns top element on the stack without removing it, or nil if stack is empty.
|
||||||
|
// Second return parameter is true, unless the stack was empty and there was nothing to peek.
|
||||||
|
func (stack *Stack) Peek() (value interface{}, ok bool) {
|
||||||
|
return stack.list.Get(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if stack does not contain any elements.
|
||||||
|
func (stack *Stack) Empty() bool {
|
||||||
|
return stack.list.Empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements within the stack.
|
||||||
|
func (stack *Stack) Size() int {
|
||||||
|
return stack.list.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the stack.
|
||||||
|
func (stack *Stack) Clear() {
|
||||||
|
stack.list.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all elements in the stack (LIFO order).
|
||||||
|
func (stack *Stack) Values() []interface{} {
|
||||||
|
return stack.list.Values()
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (stack *Stack) String() string {
|
||||||
|
str := "LinkedListStack\n"
|
||||||
|
values := []string{}
|
||||||
|
for _, value := range stack.list.Values() {
|
||||||
|
values = append(values, fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
|
str += strings.Join(values, ", ")
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the index is within bounds of the list
|
||||||
|
func (stack *Stack) withinRange(index int) bool {
|
||||||
|
return index >= 0 && index < stack.list.Size()
|
||||||
|
}
|
278
vendor/github.com/emirpasic/gods/stacks/linkedliststack/linkedliststack_test.go
generated
vendored
Normal file
278
vendor/github.com/emirpasic/gods/stacks/linkedliststack/linkedliststack_test.go
generated
vendored
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package linkedliststack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackPush(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
if actualValue := stack.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
stack.Push(1)
|
||||||
|
stack.Push(2)
|
||||||
|
stack.Push(3)
|
||||||
|
|
||||||
|
if actualValue := stack.Values(); actualValue[0].(int) != 3 || actualValue[1].(int) != 2 || actualValue[2].(int) != 1 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[3,2,1]")
|
||||||
|
}
|
||||||
|
if actualValue := stack.Empty(); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := stack.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, ok := stack.Peek(); actualValue != 3 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackPeek(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
if actualValue, ok := stack.Peek(); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
stack.Push(1)
|
||||||
|
stack.Push(2)
|
||||||
|
stack.Push(3)
|
||||||
|
if actualValue, ok := stack.Peek(); actualValue != 3 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackPop(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
stack.Push(1)
|
||||||
|
stack.Push(2)
|
||||||
|
stack.Push(3)
|
||||||
|
stack.Pop()
|
||||||
|
if actualValue, ok := stack.Peek(); actualValue != 2 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := stack.Pop(); actualValue != 2 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := stack.Pop(); actualValue != 1 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 1)
|
||||||
|
}
|
||||||
|
if actualValue, ok := stack.Pop(); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
if actualValue := stack.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := stack.Values(); len(actualValue) != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIterator(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
|
||||||
|
// Iterator
|
||||||
|
it := stack.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.Clear()
|
||||||
|
it = stack.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty stack")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorBegin(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
it := stack.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorFirst(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
it := stack.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackSerialization(t *testing.T) {
|
||||||
|
stack := New()
|
||||||
|
stack.Push("a")
|
||||||
|
stack.Push("b")
|
||||||
|
stack.Push("c")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", stack.Values()...), "cba"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := stack.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := stack.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = stack.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPush(b *testing.B, stack *Stack, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPop(b *testing.B, stack *Stack, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLinkedListStackPop100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLinkedListStackPop1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLinkedListStackPop10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLinkedListStackPop100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLinkedListStackPush100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
stack := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLinkedListStackPush1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLinkedListStackPush10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, stack, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLinkedListStackPush100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
stack := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
stack.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, stack, size)
|
||||||
|
}
|
22
vendor/github.com/emirpasic/gods/stacks/linkedliststack/serialization.go
generated
vendored
Normal file
22
vendor/github.com/emirpasic/gods/stacks/linkedliststack/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package linkedliststack
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Stack)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Stack)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (stack *Stack) ToJSON() ([]byte, error) {
|
||||||
|
return stack.list.ToJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (stack *Stack) FromJSON(data []byte) error {
|
||||||
|
return stack.list.FromJSON(data)
|
||||||
|
}
|
25
vendor/github.com/emirpasic/gods/stacks/stacks.go
generated
vendored
Normal file
25
vendor/github.com/emirpasic/gods/stacks/stacks.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package stacks provides an abstract Stack interface.
|
||||||
|
//
|
||||||
|
// In computer science, a stack is an abstract data type that serves as a collection of elements, with two principal operations: push, which adds an element to the collection, and pop, which removes the most recently added element that was not yet removed. The order in which elements come off a stack gives rise to its alternative name, LIFO (for last in, first out). Additionally, a peek operation may give access to the top without modifying the stack.
|
||||||
|
//
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29
|
||||||
|
package stacks
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
// Stack interface that all stacks implement
|
||||||
|
type Stack interface {
|
||||||
|
Push(value interface{})
|
||||||
|
Pop() (value interface{}, ok bool)
|
||||||
|
Peek() (value interface{}, ok bool)
|
||||||
|
|
||||||
|
containers.Container
|
||||||
|
// Empty() bool
|
||||||
|
// Size() int
|
||||||
|
// Clear()
|
||||||
|
// Values() []interface{}
|
||||||
|
}
|
449
vendor/github.com/emirpasic/gods/trees/avltree/avltree.go
generated
vendored
Normal file
449
vendor/github.com/emirpasic/gods/trees/avltree/avltree.go
generated
vendored
Normal file
|
@ -0,0 +1,449 @@
|
||||||
|
// Copyright (c) 2017, Benjamin Scher Purcell. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package avltree implements an AVL balanced binary tree.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// References: https://en.wikipedia.org/wiki/AVL_tree
|
||||||
|
package avltree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/trees"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertTreeImplementation() {
|
||||||
|
var _ trees.Tree = new(Tree)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tree holds elements of the AVL tree.
|
||||||
|
type Tree struct {
|
||||||
|
Root *Node // Root node
|
||||||
|
Comparator utils.Comparator // Key comparator
|
||||||
|
size int // Total number of keys in the tree
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node is a single element within the tree
|
||||||
|
type Node struct {
|
||||||
|
Key interface{}
|
||||||
|
Value interface{}
|
||||||
|
Parent *Node // Parent node
|
||||||
|
Children [2]*Node // Children nodes
|
||||||
|
b int8
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWith instantiates an AVL tree with the custom comparator.
|
||||||
|
func NewWith(comparator utils.Comparator) *Tree {
|
||||||
|
return &Tree{Comparator: comparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithIntComparator instantiates an AVL tree with the IntComparator, i.e. keys are of type int.
|
||||||
|
func NewWithIntComparator() *Tree {
|
||||||
|
return &Tree{Comparator: utils.IntComparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithStringComparator instantiates an AVL tree with the StringComparator, i.e. keys are of type string.
|
||||||
|
func NewWithStringComparator() *Tree {
|
||||||
|
return &Tree{Comparator: utils.StringComparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put inserts node into the tree.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (t *Tree) Put(key interface{}, value interface{}) {
|
||||||
|
t.put(key, value, nil, &t.Root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get searches the node in the tree by key and returns its value or nil if key is not found in tree.
|
||||||
|
// Second return parameter is true if key was found, otherwise false.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (t *Tree) Get(key interface{}) (value interface{}, found bool) {
|
||||||
|
n := t.Root
|
||||||
|
for n != nil {
|
||||||
|
cmp := t.Comparator(key, n.Key)
|
||||||
|
switch {
|
||||||
|
case cmp == 0:
|
||||||
|
return n.Value, true
|
||||||
|
case cmp < 0:
|
||||||
|
n = n.Children[0]
|
||||||
|
case cmp > 0:
|
||||||
|
n = n.Children[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove remove the node from the tree by key.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (t *Tree) Remove(key interface{}) {
|
||||||
|
t.remove(key, &t.Root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if tree does not contain any nodes.
|
||||||
|
func (t *Tree) Empty() bool {
|
||||||
|
return t.size == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the number of elements stored in the tree.
|
||||||
|
func (t *Tree) Size() int {
|
||||||
|
return t.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys in-order
|
||||||
|
func (t *Tree) Keys() []interface{} {
|
||||||
|
keys := make([]interface{}, t.size)
|
||||||
|
it := t.Iterator()
|
||||||
|
for i := 0; it.Next(); i++ {
|
||||||
|
keys[i] = it.Key()
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all values in-order based on the key.
|
||||||
|
func (t *Tree) Values() []interface{} {
|
||||||
|
values := make([]interface{}, t.size)
|
||||||
|
it := t.Iterator()
|
||||||
|
for i := 0; it.Next(); i++ {
|
||||||
|
values[i] = it.Value()
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left returns the minimum element of the AVL tree
|
||||||
|
// or nil if the tree is empty.
|
||||||
|
func (t *Tree) Left() *Node {
|
||||||
|
return t.bottom(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right returns the maximum element of the AVL tree
|
||||||
|
// or nil if the tree is empty.
|
||||||
|
func (t *Tree) Right() *Node {
|
||||||
|
return t.bottom(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floor Finds floor node of the input key, return the floor node or nil if no ceiling is found.
|
||||||
|
// Second return parameter is true if floor was found, otherwise false.
|
||||||
|
//
|
||||||
|
// Floor node is defined as the largest node that is smaller than or equal to the given node.
|
||||||
|
// A floor node may not be found, either because the tree is empty, or because
|
||||||
|
// all nodes in the tree is larger than the given node.
|
||||||
|
//
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (t *Tree) Floor(key interface{}) (floor *Node, found bool) {
|
||||||
|
found = false
|
||||||
|
n := t.Root
|
||||||
|
for n != nil {
|
||||||
|
c := t.Comparator(key, n.Key)
|
||||||
|
switch {
|
||||||
|
case c == 0:
|
||||||
|
return n, true
|
||||||
|
case c < 0:
|
||||||
|
n = n.Children[0]
|
||||||
|
case c > 0:
|
||||||
|
floor, found = n, true
|
||||||
|
n = n.Children[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ceiling finds ceiling node of the input key, return the ceiling node or nil if no ceiling is found.
|
||||||
|
// Second return parameter is true if ceiling was found, otherwise false.
|
||||||
|
//
|
||||||
|
// Ceiling node is defined as the smallest node that is larger than or equal to the given node.
|
||||||
|
// A ceiling node may not be found, either because the tree is empty, or because
|
||||||
|
// all nodes in the tree is smaller than the given node.
|
||||||
|
//
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (t *Tree) Ceiling(key interface{}) (floor *Node, found bool) {
|
||||||
|
found = false
|
||||||
|
n := t.Root
|
||||||
|
for n != nil {
|
||||||
|
c := t.Comparator(key, n.Key)
|
||||||
|
switch {
|
||||||
|
case c == 0:
|
||||||
|
return n, true
|
||||||
|
case c < 0:
|
||||||
|
floor, found = n, true
|
||||||
|
n = n.Children[0]
|
||||||
|
case c > 0:
|
||||||
|
n = n.Children[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all nodes from the tree.
|
||||||
|
func (t *Tree) Clear() {
|
||||||
|
t.Root = nil
|
||||||
|
t.size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (t *Tree) String() string {
|
||||||
|
str := "AVLTree\n"
|
||||||
|
if !t.Empty() {
|
||||||
|
output(t.Root, "", true, &str)
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) String() string {
|
||||||
|
return fmt.Sprintf("%v", n.Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tree) put(key interface{}, value interface{}, p *Node, qp **Node) bool {
|
||||||
|
q := *qp
|
||||||
|
if q == nil {
|
||||||
|
t.size++
|
||||||
|
*qp = &Node{Key: key, Value: value, Parent: p}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
c := t.Comparator(key, q.Key)
|
||||||
|
if c == 0 {
|
||||||
|
q.Key = key
|
||||||
|
q.Value = value
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if c < 0 {
|
||||||
|
c = -1
|
||||||
|
} else {
|
||||||
|
c = 1
|
||||||
|
}
|
||||||
|
a := (c + 1) / 2
|
||||||
|
var fix bool
|
||||||
|
fix = t.put(key, value, q, &q.Children[a])
|
||||||
|
if fix {
|
||||||
|
return putFix(int8(c), qp)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tree) remove(key interface{}, qp **Node) bool {
|
||||||
|
q := *qp
|
||||||
|
if q == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
c := t.Comparator(key, q.Key)
|
||||||
|
if c == 0 {
|
||||||
|
t.size--
|
||||||
|
if q.Children[1] == nil {
|
||||||
|
if q.Children[0] != nil {
|
||||||
|
q.Children[0].Parent = q.Parent
|
||||||
|
}
|
||||||
|
*qp = q.Children[0]
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
fix := removeMin(&q.Children[1], &q.Key, &q.Value)
|
||||||
|
if fix {
|
||||||
|
return removeFix(-1, qp)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if c < 0 {
|
||||||
|
c = -1
|
||||||
|
} else {
|
||||||
|
c = 1
|
||||||
|
}
|
||||||
|
a := (c + 1) / 2
|
||||||
|
fix := t.remove(key, &q.Children[a])
|
||||||
|
if fix {
|
||||||
|
return removeFix(int8(-c), qp)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeMin(qp **Node, minKey *interface{}, minVal *interface{}) bool {
|
||||||
|
q := *qp
|
||||||
|
if q.Children[0] == nil {
|
||||||
|
*minKey = q.Key
|
||||||
|
*minVal = q.Value
|
||||||
|
if q.Children[1] != nil {
|
||||||
|
q.Children[1].Parent = q.Parent
|
||||||
|
}
|
||||||
|
*qp = q.Children[1]
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
fix := removeMin(&q.Children[0], minKey, minVal)
|
||||||
|
if fix {
|
||||||
|
return removeFix(1, qp)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func putFix(c int8, t **Node) bool {
|
||||||
|
s := *t
|
||||||
|
if s.b == 0 {
|
||||||
|
s.b = c
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.b == -c {
|
||||||
|
s.b = 0
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Children[(c+1)/2].b == c {
|
||||||
|
s = singlerot(c, s)
|
||||||
|
} else {
|
||||||
|
s = doublerot(c, s)
|
||||||
|
}
|
||||||
|
*t = s
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeFix(c int8, t **Node) bool {
|
||||||
|
s := *t
|
||||||
|
if s.b == 0 {
|
||||||
|
s.b = c
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.b == -c {
|
||||||
|
s.b = 0
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
a := (c + 1) / 2
|
||||||
|
if s.Children[a].b == 0 {
|
||||||
|
s = rotate(c, s)
|
||||||
|
s.b = -c
|
||||||
|
*t = s
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Children[a].b == c {
|
||||||
|
s = singlerot(c, s)
|
||||||
|
} else {
|
||||||
|
s = doublerot(c, s)
|
||||||
|
}
|
||||||
|
*t = s
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func singlerot(c int8, s *Node) *Node {
|
||||||
|
s.b = 0
|
||||||
|
s = rotate(c, s)
|
||||||
|
s.b = 0
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func doublerot(c int8, s *Node) *Node {
|
||||||
|
a := (c + 1) / 2
|
||||||
|
r := s.Children[a]
|
||||||
|
s.Children[a] = rotate(-c, s.Children[a])
|
||||||
|
p := rotate(c, s)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
s.b = 0
|
||||||
|
r.b = 0
|
||||||
|
case p.b == c:
|
||||||
|
s.b = -c
|
||||||
|
r.b = 0
|
||||||
|
case p.b == -c:
|
||||||
|
s.b = 0
|
||||||
|
r.b = c
|
||||||
|
}
|
||||||
|
|
||||||
|
p.b = 0
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func rotate(c int8, s *Node) *Node {
|
||||||
|
a := (c + 1) / 2
|
||||||
|
r := s.Children[a]
|
||||||
|
s.Children[a] = r.Children[a^1]
|
||||||
|
if s.Children[a] != nil {
|
||||||
|
s.Children[a].Parent = s
|
||||||
|
}
|
||||||
|
r.Children[a^1] = s
|
||||||
|
r.Parent = s.Parent
|
||||||
|
s.Parent = r
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tree) bottom(d int) *Node {
|
||||||
|
n := t.Root
|
||||||
|
if n == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for c := n.Children[d]; c != nil; c = n.Children[d] {
|
||||||
|
n = c
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev returns the previous element in an inorder
|
||||||
|
// walk of the AVL tree.
|
||||||
|
func (n *Node) Prev() *Node {
|
||||||
|
return n.walk1(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next element in an inorder
|
||||||
|
// walk of the AVL tree.
|
||||||
|
func (n *Node) Next() *Node {
|
||||||
|
return n.walk1(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) walk1(a int) *Node {
|
||||||
|
if n == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.Children[a] != nil {
|
||||||
|
n = n.Children[a]
|
||||||
|
for n.Children[a^1] != nil {
|
||||||
|
n = n.Children[a^1]
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
p := n.Parent
|
||||||
|
for p != nil && p.Children[a] == n {
|
||||||
|
n = p
|
||||||
|
p = p.Parent
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func output(node *Node, prefix string, isTail bool, str *string) {
|
||||||
|
if node.Children[1] != nil {
|
||||||
|
newPrefix := prefix
|
||||||
|
if isTail {
|
||||||
|
newPrefix += "│ "
|
||||||
|
} else {
|
||||||
|
newPrefix += " "
|
||||||
|
}
|
||||||
|
output(node.Children[1], newPrefix, false, str)
|
||||||
|
}
|
||||||
|
*str += prefix
|
||||||
|
if isTail {
|
||||||
|
*str += "└── "
|
||||||
|
} else {
|
||||||
|
*str += "┌── "
|
||||||
|
}
|
||||||
|
*str += node.String() + "\n"
|
||||||
|
if node.Children[0] != nil {
|
||||||
|
newPrefix := prefix
|
||||||
|
if isTail {
|
||||||
|
newPrefix += " "
|
||||||
|
} else {
|
||||||
|
newPrefix += "│ "
|
||||||
|
}
|
||||||
|
output(node.Children[0], newPrefix, true, str)
|
||||||
|
}
|
||||||
|
}
|
741
vendor/github.com/emirpasic/gods/trees/avltree/avltree_test.go
generated
vendored
Normal file
741
vendor/github.com/emirpasic/gods/trees/avltree/avltree_test.go
generated
vendored
Normal file
|
@ -0,0 +1,741 @@
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package avltree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAVLTreePut(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
tree.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
if actualValue := tree.Size(); actualValue != 7 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d%d%d%d", tree.Keys()...), "1234567"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s", tree.Values()...), "abcdefg"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests1 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, "e", true},
|
||||||
|
{6, "f", true},
|
||||||
|
{7, "g", true},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests1 {
|
||||||
|
// retrievals
|
||||||
|
actualValue, actualFound := tree.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeRemove(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
tree.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
tree.Remove(5)
|
||||||
|
tree.Remove(6)
|
||||||
|
tree.Remove(7)
|
||||||
|
tree.Remove(8)
|
||||||
|
tree.Remove(5)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d", tree.Keys()...), "1234"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := tree.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests2 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, nil, false},
|
||||||
|
{6, nil, false},
|
||||||
|
{7, nil, false},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests2 {
|
||||||
|
actualValue, actualFound := tree.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.Remove(1)
|
||||||
|
tree.Remove(4)
|
||||||
|
tree.Remove(2)
|
||||||
|
tree.Remove(3)
|
||||||
|
tree.Remove(2)
|
||||||
|
tree.Remove(2)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", tree.Keys()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", tree.Values()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if empty, size := tree.Empty(), tree.Size(); empty != true || size != -0 {
|
||||||
|
t.Errorf("Got %v expected %v", empty, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeLeftAndRight(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
|
||||||
|
if actualValue := tree.Left(); actualValue != nil {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
if actualValue := tree.Right(); actualValue != nil {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x") // overwrite
|
||||||
|
tree.Put(2, "b")
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d", tree.Left().Key), "1"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", tree.Left().Value), "x"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d", tree.Right().Key), "7"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", tree.Right().Value), "g"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeCeilingAndFloor(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
|
||||||
|
if node, found := tree.Floor(0); node != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", node, "<nil>")
|
||||||
|
}
|
||||||
|
if node, found := tree.Ceiling(0); node != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", node, "<nil>")
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
|
||||||
|
if node, found := tree.Floor(4); node.Key != 4 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", node.Key, 4)
|
||||||
|
}
|
||||||
|
if node, found := tree.Floor(0); node != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", node, "<nil>")
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, found := tree.Ceiling(4); node.Key != 4 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", node.Key, 4)
|
||||||
|
}
|
||||||
|
if node, found := tree.Ceiling(8); node != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", node, "<nil>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty tree")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIteratorPrevOnEmpty(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty tree")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIterator1Next(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
tree.Put(1, "a") //overwrite
|
||||||
|
// │ ┌── 7
|
||||||
|
// └── 6
|
||||||
|
// │ ┌── 5
|
||||||
|
// └── 4
|
||||||
|
// │ ┌── 3
|
||||||
|
// └── 2
|
||||||
|
// └── 1
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIterator1Prev(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
tree.Put(1, "a") //overwrite
|
||||||
|
// │ ┌── 7
|
||||||
|
// └── 6
|
||||||
|
// │ ┌── 5
|
||||||
|
// └── 4
|
||||||
|
// │ ┌── 3
|
||||||
|
// └── 2
|
||||||
|
// └── 1
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := tree.size
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case countDown:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIterator2Next(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIterator2Prev(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := tree.size
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case countDown:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIterator3Next(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(1, "a")
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIterator3Prev(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(1, "a")
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := tree.size
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case countDown:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIterator4Next(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(13, 5)
|
||||||
|
tree.Put(8, 3)
|
||||||
|
tree.Put(17, 7)
|
||||||
|
tree.Put(1, 1)
|
||||||
|
tree.Put(11, 4)
|
||||||
|
tree.Put(15, 6)
|
||||||
|
tree.Put(25, 9)
|
||||||
|
tree.Put(6, 2)
|
||||||
|
tree.Put(22, 8)
|
||||||
|
tree.Put(27, 10)
|
||||||
|
// │ ┌── 27
|
||||||
|
// │ ┌── 25
|
||||||
|
// │ │ └── 22
|
||||||
|
// │ ┌── 17
|
||||||
|
// │ │ └── 15
|
||||||
|
// └── 13
|
||||||
|
// │ ┌── 11
|
||||||
|
// └── 8
|
||||||
|
// │ ┌── 6
|
||||||
|
// └── 1
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
value := it.Value()
|
||||||
|
switch value {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIterator4Prev(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(13, 5)
|
||||||
|
tree.Put(8, 3)
|
||||||
|
tree.Put(17, 7)
|
||||||
|
tree.Put(1, 1)
|
||||||
|
tree.Put(11, 4)
|
||||||
|
tree.Put(15, 6)
|
||||||
|
tree.Put(25, 9)
|
||||||
|
tree.Put(6, 2)
|
||||||
|
tree.Put(22, 8)
|
||||||
|
tree.Put(27, 10)
|
||||||
|
// │ ┌── 27
|
||||||
|
// │ ┌── 25
|
||||||
|
// │ │ └── 22
|
||||||
|
// │ ┌── 17
|
||||||
|
// │ │ └── 15
|
||||||
|
// └── 13
|
||||||
|
// │ ┌── 11
|
||||||
|
// └── 8
|
||||||
|
// │ ┌── 6
|
||||||
|
// └── 1
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := tree.Size()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
for it.Prev() {
|
||||||
|
value := it.Value()
|
||||||
|
switch value {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIteratorBegin(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
|
||||||
|
if it.Key() != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.Key(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Begin()
|
||||||
|
|
||||||
|
if it.Key() != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.Key(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Begin()
|
||||||
|
|
||||||
|
if it.Key() != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.Key(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Next()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIteratorEnd(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
it := tree.Iterator()
|
||||||
|
|
||||||
|
if it.Key() != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.Key(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.End()
|
||||||
|
if it.Key() != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.Key(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it.End()
|
||||||
|
if it.Key() != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.Key(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Prev()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIteratorFirst(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeIteratorLast(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAVLTreeSerialization(t *testing.T) {
|
||||||
|
tree := NewWithStringComparator()
|
||||||
|
tree.Put("c", "3")
|
||||||
|
tree.Put("b", "2")
|
||||||
|
tree.Put("a", "1")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := tree.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := tree.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[a,b,c]")
|
||||||
|
}
|
||||||
|
if actualValue := tree.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := tree.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = tree.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, tree *Tree, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPut(b *testing.B, tree *Tree, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, tree *Tree, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreeGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreeGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreeGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreeGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreePut100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreePut1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreePut10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreePut100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreeRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreeRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreeRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAVLTreeRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, tree, size)
|
||||||
|
}
|
117
vendor/github.com/emirpasic/gods/trees/avltree/iterator.go
generated
vendored
Normal file
117
vendor/github.com/emirpasic/gods/trees/avltree/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
// Copyright (c) 2017, Benjamin Scher Purcell. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package avltree
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
tree *Tree
|
||||||
|
node *Node
|
||||||
|
position position
|
||||||
|
}
|
||||||
|
|
||||||
|
type position byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
begin, between, end position = 0, 1, 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose elements are key/value pairs.
|
||||||
|
func (tree *Tree) Iterator() containers.ReverseIteratorWithKey {
|
||||||
|
return &Iterator{tree: tree, node: nil, position: begin}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
switch iterator.position {
|
||||||
|
case begin:
|
||||||
|
iterator.position = between
|
||||||
|
iterator.node = iterator.tree.Left()
|
||||||
|
case between:
|
||||||
|
iterator.node = iterator.node.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
if iterator.node == nil {
|
||||||
|
iterator.position = end
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the next element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||||
|
// If Prev() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
switch iterator.position {
|
||||||
|
case end:
|
||||||
|
iterator.position = between
|
||||||
|
iterator.node = iterator.tree.Right()
|
||||||
|
case between:
|
||||||
|
iterator.node = iterator.node.Prev()
|
||||||
|
}
|
||||||
|
|
||||||
|
if iterator.node == nil {
|
||||||
|
iterator.position = begin
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
if iterator.node == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return iterator.node.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the current element's key.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Key() interface{} {
|
||||||
|
if iterator.node == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return iterator.node.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.node = nil
|
||||||
|
iterator.position = begin
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.node = nil
|
||||||
|
iterator.position = end
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
iterator.End()
|
||||||
|
return iterator.Prev()
|
||||||
|
}
|
39
vendor/github.com/emirpasic/gods/trees/avltree/serialization.go
generated
vendored
Normal file
39
vendor/github.com/emirpasic/gods/trees/avltree/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package avltree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Tree)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Tree)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (tree *Tree) ToJSON() ([]byte, error) {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
elements[utils.ToString(it.Key())] = it.Value()
|
||||||
|
}
|
||||||
|
return json.Marshal(&elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (tree *Tree) FromJSON(data []byte) error {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
tree.Clear()
|
||||||
|
for key, value := range elements {
|
||||||
|
tree.Put(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
163
vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap.go
generated
vendored
Normal file
163
vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap.go
generated
vendored
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package binaryheap implements a binary heap backed by array list.
|
||||||
|
//
|
||||||
|
// Comparator defines this heap as either min or max heap.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// References: http://en.wikipedia.org/wiki/Binary_heap
|
||||||
|
package binaryheap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/lists/arraylist"
|
||||||
|
"github.com/emirpasic/gods/trees"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertTreeImplementation() {
|
||||||
|
var _ trees.Tree = (*Heap)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heap holds elements in an array-list
|
||||||
|
type Heap struct {
|
||||||
|
list *arraylist.List
|
||||||
|
Comparator utils.Comparator
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWith instantiates a new empty heap tree with the custom comparator.
|
||||||
|
func NewWith(comparator utils.Comparator) *Heap {
|
||||||
|
return &Heap{list: arraylist.New(), Comparator: comparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithIntComparator instantiates a new empty heap with the IntComparator, i.e. elements are of type int.
|
||||||
|
func NewWithIntComparator() *Heap {
|
||||||
|
return &Heap{list: arraylist.New(), Comparator: utils.IntComparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithStringComparator instantiates a new empty heap with the StringComparator, i.e. elements are of type string.
|
||||||
|
func NewWithStringComparator() *Heap {
|
||||||
|
return &Heap{list: arraylist.New(), Comparator: utils.StringComparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push adds a value onto the heap and bubbles it up accordingly.
|
||||||
|
func (heap *Heap) Push(values ...interface{}) {
|
||||||
|
if len(values) == 1 {
|
||||||
|
heap.list.Add(values[0])
|
||||||
|
heap.bubbleUp()
|
||||||
|
} else {
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/Binary_heap#Building_a_heap
|
||||||
|
for _, value := range values {
|
||||||
|
heap.list.Add(value)
|
||||||
|
}
|
||||||
|
size := heap.list.Size()/2 + 1
|
||||||
|
for i := size; i >= 0; i-- {
|
||||||
|
heap.bubbleDownIndex(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop removes top element on heap and returns it, or nil if heap is empty.
|
||||||
|
// Second return parameter is true, unless the heap was empty and there was nothing to pop.
|
||||||
|
func (heap *Heap) Pop() (value interface{}, ok bool) {
|
||||||
|
value, ok = heap.list.Get(0)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastIndex := heap.list.Size() - 1
|
||||||
|
heap.list.Swap(0, lastIndex)
|
||||||
|
heap.list.Remove(lastIndex)
|
||||||
|
heap.bubbleDown()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peek returns top element on the heap without removing it, or nil if heap is empty.
|
||||||
|
// Second return parameter is true, unless the heap was empty and there was nothing to peek.
|
||||||
|
func (heap *Heap) Peek() (value interface{}, ok bool) {
|
||||||
|
return heap.list.Get(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if heap does not contain any elements.
|
||||||
|
func (heap *Heap) Empty() bool {
|
||||||
|
return heap.list.Empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements within the heap.
|
||||||
|
func (heap *Heap) Size() int {
|
||||||
|
return heap.list.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the heap.
|
||||||
|
func (heap *Heap) Clear() {
|
||||||
|
heap.list.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all elements in the heap.
|
||||||
|
func (heap *Heap) Values() []interface{} {
|
||||||
|
return heap.list.Values()
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (heap *Heap) String() string {
|
||||||
|
str := "BinaryHeap\n"
|
||||||
|
values := []string{}
|
||||||
|
for _, value := range heap.list.Values() {
|
||||||
|
values = append(values, fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
|
str += strings.Join(values, ", ")
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs the "bubble down" operation. This is to place the element that is at the root
|
||||||
|
// of the heap in its correct place so that the heap maintains the min/max-heap order property.
|
||||||
|
func (heap *Heap) bubbleDown() {
|
||||||
|
heap.bubbleDownIndex(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs the "bubble down" operation. This is to place the element that is at the index
|
||||||
|
// of the heap in its correct place so that the heap maintains the min/max-heap order property.
|
||||||
|
func (heap *Heap) bubbleDownIndex(index int) {
|
||||||
|
size := heap.list.Size()
|
||||||
|
for leftIndex := index<<1 + 1; leftIndex < size; leftIndex = index<<1 + 1 {
|
||||||
|
rightIndex := index<<1 + 2
|
||||||
|
smallerIndex := leftIndex
|
||||||
|
leftValue, _ := heap.list.Get(leftIndex)
|
||||||
|
rightValue, _ := heap.list.Get(rightIndex)
|
||||||
|
if rightIndex < size && heap.Comparator(leftValue, rightValue) > 0 {
|
||||||
|
smallerIndex = rightIndex
|
||||||
|
}
|
||||||
|
indexValue, _ := heap.list.Get(index)
|
||||||
|
smallerValue, _ := heap.list.Get(smallerIndex)
|
||||||
|
if heap.Comparator(indexValue, smallerValue) > 0 {
|
||||||
|
heap.list.Swap(index, smallerIndex)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
index = smallerIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs the "bubble up" operation. This is to place a newly inserted
|
||||||
|
// element (i.e. last element in the list) in its correct place so that
|
||||||
|
// the heap maintains the min/max-heap order property.
|
||||||
|
func (heap *Heap) bubbleUp() {
|
||||||
|
index := heap.list.Size() - 1
|
||||||
|
for parentIndex := (index - 1) >> 1; index > 0; parentIndex = (index - 1) >> 1 {
|
||||||
|
indexValue, _ := heap.list.Get(index)
|
||||||
|
parentValue, _ := heap.list.Get(parentIndex)
|
||||||
|
if heap.Comparator(parentValue, indexValue) <= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
heap.list.Swap(index, parentIndex)
|
||||||
|
index = parentIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the index is within bounds of the list
|
||||||
|
func (heap *Heap) withinRange(index int) bool {
|
||||||
|
return index >= 0 && index < heap.list.Size()
|
||||||
|
}
|
393
vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap_test.go
generated
vendored
Normal file
393
vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap_test.go
generated
vendored
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package binaryheap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBinaryHeapPush(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
|
||||||
|
if actualValue := heap.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
heap.Push(3) // [3]
|
||||||
|
heap.Push(2) // [2,3]
|
||||||
|
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
|
||||||
|
|
||||||
|
if actualValue := heap.Values(); actualValue[0].(int) != 1 || actualValue[1].(int) != 3 || actualValue[2].(int) != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
|
||||||
|
}
|
||||||
|
if actualValue := heap.Empty(); actualValue != false {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, false)
|
||||||
|
}
|
||||||
|
if actualValue := heap.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, ok := heap.Peek(); actualValue != 1 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapPushBulk(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
|
||||||
|
heap.Push(15, 20, 3, 1, 2)
|
||||||
|
|
||||||
|
if actualValue := heap.Values(); actualValue[0].(int) != 1 || actualValue[1].(int) != 2 || actualValue[2].(int) != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
|
||||||
|
}
|
||||||
|
if actualValue, ok := heap.Pop(); actualValue != 1 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapPop(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
|
||||||
|
if actualValue := heap.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
heap.Push(3) // [3]
|
||||||
|
heap.Push(2) // [2,3]
|
||||||
|
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
|
||||||
|
heap.Pop() // [3,2]
|
||||||
|
|
||||||
|
if actualValue, ok := heap.Peek(); actualValue != 2 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := heap.Pop(); actualValue != 2 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, ok := heap.Pop(); actualValue != 3 || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, ok := heap.Pop(); actualValue != nil || ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
if actualValue := heap.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
if actualValue := heap.Values(); len(actualValue) != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapRandom(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
|
||||||
|
rand.Seed(3)
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
r := int(rand.Int31n(30))
|
||||||
|
heap.Push(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
prev, _ := heap.Pop()
|
||||||
|
for !heap.Empty() {
|
||||||
|
curr, _ := heap.Pop()
|
||||||
|
if prev.(int) > curr.(int) {
|
||||||
|
t.Errorf("Heap property invalidated. prev: %v current: %v", prev, curr)
|
||||||
|
}
|
||||||
|
prev = curr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapIteratorOnEmpty(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
it := heap.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty heap")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapIteratorNext(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
heap.Push(3) // [3]
|
||||||
|
heap.Push(2) // [2,3]
|
||||||
|
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
|
||||||
|
|
||||||
|
it := heap.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapIteratorPrev(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
heap.Push(3) // [3]
|
||||||
|
heap.Push(2) // [2,3]
|
||||||
|
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
|
||||||
|
|
||||||
|
it := heap.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
for it.Prev() {
|
||||||
|
count++
|
||||||
|
index := it.Index()
|
||||||
|
value := it.Value()
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := index, 3-count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapIteratorBegin(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
it := heap.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
heap.Push(2)
|
||||||
|
heap.Push(3)
|
||||||
|
heap.Push(1)
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != 1 {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListIteratorEnd(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
it := heap.Iterator()
|
||||||
|
|
||||||
|
if index := it.Index(); index != -1 {
|
||||||
|
t.Errorf("Got %v expected %v", index, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", index, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
heap.Push(3) // [3]
|
||||||
|
heap.Push(2) // [2,3]
|
||||||
|
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
|
||||||
|
it.End()
|
||||||
|
if index := it.Index(); index != heap.Size() {
|
||||||
|
t.Errorf("Got %v expected %v", index, heap.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Prev()
|
||||||
|
if index, value := it.Index(), it.Value(); index != heap.Size()-1 || value != 2 {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, heap.Size()-1, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStackIteratorFirst(t *testing.T) {
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
it := heap.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
heap.Push(3) // [3]
|
||||||
|
heap.Push(2) // [2,3]
|
||||||
|
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 0 || value != 1 {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapIteratorLast(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
it := tree.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
tree.Push(2)
|
||||||
|
tree.Push(3)
|
||||||
|
tree.Push(1) // [1,3,2](2 swapped with 1, hence last)
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if index, value := it.Index(), it.Value(); index != 2 || value != 2 {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryHeapSerialization(t *testing.T) {
|
||||||
|
heap := NewWithStringComparator()
|
||||||
|
|
||||||
|
heap.Push("c") // ["c"]
|
||||||
|
heap.Push("b") // ["b","c"]
|
||||||
|
heap.Push("a") // ["a","c","b"]("b" swapped with "a", hence last)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue := heap.Values(); actualValue[0].(string) != "a" || actualValue[1].(string) != "c" || actualValue[2].(string) != "b" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[1,3,2]")
|
||||||
|
}
|
||||||
|
if actualValue := heap.Size(); actualValue != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||||
|
}
|
||||||
|
if actualValue, ok := heap.Peek(); actualValue != "a" || !ok {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "a")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := heap.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = heap.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPush(b *testing.B, heap *Heap, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Push(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPop(b *testing.B, heap *Heap, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBinaryHeapPop100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, heap, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBinaryHeapPop1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, heap, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBinaryHeapPop10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, heap, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBinaryHeapPop100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPop(b, heap, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBinaryHeapPush100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, heap, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBinaryHeapPush1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, heap, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBinaryHeapPush10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, heap, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBinaryHeapPush100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
heap := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
heap.Push(n)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPush(b, heap, size)
|
||||||
|
}
|
84
vendor/github.com/emirpasic/gods/trees/binaryheap/iterator.go
generated
vendored
Normal file
84
vendor/github.com/emirpasic/gods/trees/binaryheap/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package binaryheap
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
type Iterator struct {
|
||||||
|
heap *Heap
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
|
func (heap *Heap) Iterator() Iterator {
|
||||||
|
return Iterator{heap: heap, index: -1}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
if iterator.index < iterator.heap.Size() {
|
||||||
|
iterator.index++
|
||||||
|
}
|
||||||
|
return iterator.heap.withinRange(iterator.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
if iterator.index >= 0 {
|
||||||
|
iterator.index--
|
||||||
|
}
|
||||||
|
return iterator.heap.withinRange(iterator.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
value, _ := iterator.heap.list.Get(iterator.index)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index returns the current element's index.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Index() int {
|
||||||
|
return iterator.index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.index = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.index = iterator.heap.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
iterator.End()
|
||||||
|
return iterator.Prev()
|
||||||
|
}
|
22
vendor/github.com/emirpasic/gods/trees/binaryheap/serialization.go
generated
vendored
Normal file
22
vendor/github.com/emirpasic/gods/trees/binaryheap/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package binaryheap
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Heap)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Heap)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (heap *Heap) ToJSON() ([]byte, error) {
|
||||||
|
return heap.list.ToJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (heap *Heap) FromJSON(data []byte) error {
|
||||||
|
return heap.list.FromJSON(data)
|
||||||
|
}
|
577
vendor/github.com/emirpasic/gods/trees/btree/btree.go
generated
vendored
Normal file
577
vendor/github.com/emirpasic/gods/trees/btree/btree.go
generated
vendored
Normal file
|
@ -0,0 +1,577 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package btree implements a B tree.
|
||||||
|
//
|
||||||
|
// According to Knuth's definition, a B-tree of order m is a tree which satisfies the following properties:
|
||||||
|
// - Every node has at most m children.
|
||||||
|
// - Every non-leaf node (except root) has at least ⌈m/2⌉ children.
|
||||||
|
// - The root has at least two children if it is not a leaf node.
|
||||||
|
// - A non-leaf node with k children contains k−1 keys.
|
||||||
|
// - All leaves appear in the same level
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// References: https://en.wikipedia.org/wiki/B-tree
|
||||||
|
package btree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/trees"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertTreeImplementation() {
|
||||||
|
var _ trees.Tree = (*Tree)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tree holds elements of the B-tree
|
||||||
|
type Tree struct {
|
||||||
|
Root *Node // Root node
|
||||||
|
Comparator utils.Comparator // Key comparator
|
||||||
|
size int // Total number of keys in the tree
|
||||||
|
m int // order (maximum number of children)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node is a single element within the tree
|
||||||
|
type Node struct {
|
||||||
|
Parent *Node
|
||||||
|
Entries []*Entry // Contained keys in node
|
||||||
|
Children []*Node // Children nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry represents the key-value pair contained within nodes
|
||||||
|
type Entry struct {
|
||||||
|
Key interface{}
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWith instantiates a B-tree with the order (maximum number of children) and a custom key comparator.
|
||||||
|
func NewWith(order int, comparator utils.Comparator) *Tree {
|
||||||
|
if order < 3 {
|
||||||
|
panic("Invalid order, should be at least 3")
|
||||||
|
}
|
||||||
|
return &Tree{m: order, Comparator: comparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithIntComparator instantiates a B-tree with the order (maximum number of children) and the IntComparator, i.e. keys are of type int.
|
||||||
|
func NewWithIntComparator(order int) *Tree {
|
||||||
|
return NewWith(order, utils.IntComparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithStringComparator instantiates a B-tree with the order (maximum number of children) and the StringComparator, i.e. keys are of type string.
|
||||||
|
func NewWithStringComparator(order int) *Tree {
|
||||||
|
return NewWith(order, utils.StringComparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put inserts key-value pair node into the tree.
|
||||||
|
// If key already exists, then its value is updated with the new value.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (tree *Tree) Put(key interface{}, value interface{}) {
|
||||||
|
entry := &Entry{Key: key, Value: value}
|
||||||
|
|
||||||
|
if tree.Root == nil {
|
||||||
|
tree.Root = &Node{Entries: []*Entry{entry}, Children: []*Node{}}
|
||||||
|
tree.size++
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if tree.insert(tree.Root, entry) {
|
||||||
|
tree.size++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get searches the node in the tree by key and returns its value or nil if key is not found in tree.
|
||||||
|
// Second return parameter is true if key was found, otherwise false.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (tree *Tree) Get(key interface{}) (value interface{}, found bool) {
|
||||||
|
node, index, found := tree.searchRecursively(tree.Root, key)
|
||||||
|
if found {
|
||||||
|
return node.Entries[index].Value, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove remove the node from the tree by key.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (tree *Tree) Remove(key interface{}) {
|
||||||
|
node, index, found := tree.searchRecursively(tree.Root, key)
|
||||||
|
if found {
|
||||||
|
tree.delete(node, index)
|
||||||
|
tree.size--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if tree does not contain any nodes
|
||||||
|
func (tree *Tree) Empty() bool {
|
||||||
|
return tree.size == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of nodes in the tree.
|
||||||
|
func (tree *Tree) Size() int {
|
||||||
|
return tree.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys in-order
|
||||||
|
func (tree *Tree) Keys() []interface{} {
|
||||||
|
keys := make([]interface{}, tree.size)
|
||||||
|
it := tree.Iterator()
|
||||||
|
for i := 0; it.Next(); i++ {
|
||||||
|
keys[i] = it.Key()
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all values in-order based on the key.
|
||||||
|
func (tree *Tree) Values() []interface{} {
|
||||||
|
values := make([]interface{}, tree.size)
|
||||||
|
it := tree.Iterator()
|
||||||
|
for i := 0; it.Next(); i++ {
|
||||||
|
values[i] = it.Value()
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all nodes from the tree.
|
||||||
|
func (tree *Tree) Clear() {
|
||||||
|
tree.Root = nil
|
||||||
|
tree.size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Height returns the height of the tree.
|
||||||
|
func (tree *Tree) Height() int {
|
||||||
|
return tree.Root.height()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left returns the left-most (min) node or nil if tree is empty.
|
||||||
|
func (tree *Tree) Left() *Node {
|
||||||
|
return tree.left(tree.Root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeftKey returns the left-most (min) key or nil if tree is empty.
|
||||||
|
func (tree *Tree) LeftKey() interface{} {
|
||||||
|
if left := tree.Left(); left != nil {
|
||||||
|
return left.Entries[0].Key
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeftValue returns the left-most value or nil if tree is empty.
|
||||||
|
func (tree *Tree) LeftValue() interface{} {
|
||||||
|
if left := tree.Left(); left != nil {
|
||||||
|
return left.Entries[0].Value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right returns the right-most (max) node or nil if tree is empty.
|
||||||
|
func (tree *Tree) Right() *Node {
|
||||||
|
return tree.right(tree.Root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RightKey returns the right-most (max) key or nil if tree is empty.
|
||||||
|
func (tree *Tree) RightKey() interface{} {
|
||||||
|
if right := tree.Right(); right != nil {
|
||||||
|
return right.Entries[len(right.Entries)-1].Key
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RightValue returns the right-most value or nil if tree is empty.
|
||||||
|
func (tree *Tree) RightValue() interface{} {
|
||||||
|
if right := tree.Right(); right != nil {
|
||||||
|
return right.Entries[len(right.Entries)-1].Value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container (for debugging purposes)
|
||||||
|
func (tree *Tree) String() string {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
if _, err := buffer.WriteString("BTree\n"); err != nil {
|
||||||
|
}
|
||||||
|
if !tree.Empty() {
|
||||||
|
tree.output(&buffer, tree.Root, 0, true)
|
||||||
|
}
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) String() string {
|
||||||
|
return fmt.Sprintf("%v", entry.Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) output(buffer *bytes.Buffer, node *Node, level int, isTail bool) {
|
||||||
|
for e := 0; e < len(node.Entries)+1; e++ {
|
||||||
|
if e < len(node.Children) {
|
||||||
|
tree.output(buffer, node.Children[e], level+1, true)
|
||||||
|
}
|
||||||
|
if e < len(node.Entries) {
|
||||||
|
if _, err := buffer.WriteString(strings.Repeat(" ", level)); err != nil {
|
||||||
|
}
|
||||||
|
if _, err := buffer.WriteString(fmt.Sprintf("%v", node.Entries[e].Key) + "\n"); err != nil {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *Node) height() int {
|
||||||
|
height := 0
|
||||||
|
for ; node != nil; node = node.Children[0] {
|
||||||
|
height++
|
||||||
|
if len(node.Children) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return height
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) isLeaf(node *Node) bool {
|
||||||
|
return len(node.Children) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) isFull(node *Node) bool {
|
||||||
|
return len(node.Entries) == tree.maxEntries()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) shouldSplit(node *Node) bool {
|
||||||
|
return len(node.Entries) > tree.maxEntries()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) maxChildren() int {
|
||||||
|
return tree.m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) minChildren() int {
|
||||||
|
return (tree.m + 1) / 2 // ceil(m/2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) maxEntries() int {
|
||||||
|
return tree.maxChildren() - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) minEntries() int {
|
||||||
|
return tree.minChildren() - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) middle() int {
|
||||||
|
return (tree.m - 1) / 2 // "-1" to favor right nodes to have more keys when splitting
|
||||||
|
}
|
||||||
|
|
||||||
|
// search searches only within the single node among its entries
|
||||||
|
func (tree *Tree) search(node *Node, key interface{}) (index int, found bool) {
|
||||||
|
low, high := 0, len(node.Entries)-1
|
||||||
|
var mid int
|
||||||
|
for low <= high {
|
||||||
|
mid = (high + low) / 2
|
||||||
|
compare := tree.Comparator(key, node.Entries[mid].Key)
|
||||||
|
switch {
|
||||||
|
case compare > 0:
|
||||||
|
low = mid + 1
|
||||||
|
case compare < 0:
|
||||||
|
high = mid - 1
|
||||||
|
case compare == 0:
|
||||||
|
return mid, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return low, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// searchRecursively searches recursively down the tree starting at the startNode
|
||||||
|
func (tree *Tree) searchRecursively(startNode *Node, key interface{}) (node *Node, index int, found bool) {
|
||||||
|
if tree.Empty() {
|
||||||
|
return nil, -1, false
|
||||||
|
}
|
||||||
|
node = startNode
|
||||||
|
for {
|
||||||
|
index, found = tree.search(node, key)
|
||||||
|
if found {
|
||||||
|
return node, index, true
|
||||||
|
}
|
||||||
|
if tree.isLeaf(node) {
|
||||||
|
return nil, -1, false
|
||||||
|
}
|
||||||
|
node = node.Children[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) insert(node *Node, entry *Entry) (inserted bool) {
|
||||||
|
if tree.isLeaf(node) {
|
||||||
|
return tree.insertIntoLeaf(node, entry)
|
||||||
|
}
|
||||||
|
return tree.insertIntoInternal(node, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) insertIntoLeaf(node *Node, entry *Entry) (inserted bool) {
|
||||||
|
insertPosition, found := tree.search(node, entry.Key)
|
||||||
|
if found {
|
||||||
|
node.Entries[insertPosition] = entry
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Insert entry's key in the middle of the node
|
||||||
|
node.Entries = append(node.Entries, nil)
|
||||||
|
copy(node.Entries[insertPosition+1:], node.Entries[insertPosition:])
|
||||||
|
node.Entries[insertPosition] = entry
|
||||||
|
tree.split(node)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) insertIntoInternal(node *Node, entry *Entry) (inserted bool) {
|
||||||
|
insertPosition, found := tree.search(node, entry.Key)
|
||||||
|
if found {
|
||||||
|
node.Entries[insertPosition] = entry
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return tree.insert(node.Children[insertPosition], entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) split(node *Node) {
|
||||||
|
if !tree.shouldSplit(node) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if node == tree.Root {
|
||||||
|
tree.splitRoot()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.splitNonRoot(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) splitNonRoot(node *Node) {
|
||||||
|
middle := tree.middle()
|
||||||
|
parent := node.Parent
|
||||||
|
|
||||||
|
left := &Node{Entries: append([]*Entry(nil), node.Entries[:middle]...), Parent: parent}
|
||||||
|
right := &Node{Entries: append([]*Entry(nil), node.Entries[middle+1:]...), Parent: parent}
|
||||||
|
|
||||||
|
// Move children from the node to be split into left and right nodes
|
||||||
|
if !tree.isLeaf(node) {
|
||||||
|
left.Children = append([]*Node(nil), node.Children[:middle+1]...)
|
||||||
|
right.Children = append([]*Node(nil), node.Children[middle+1:]...)
|
||||||
|
setParent(left.Children, left)
|
||||||
|
setParent(right.Children, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
insertPosition, _ := tree.search(parent, node.Entries[middle].Key)
|
||||||
|
|
||||||
|
// Insert middle key into parent
|
||||||
|
parent.Entries = append(parent.Entries, nil)
|
||||||
|
copy(parent.Entries[insertPosition+1:], parent.Entries[insertPosition:])
|
||||||
|
parent.Entries[insertPosition] = node.Entries[middle]
|
||||||
|
|
||||||
|
// Set child left of inserted key in parent to the created left node
|
||||||
|
parent.Children[insertPosition] = left
|
||||||
|
|
||||||
|
// Set child right of inserted key in parent to the created right node
|
||||||
|
parent.Children = append(parent.Children, nil)
|
||||||
|
copy(parent.Children[insertPosition+2:], parent.Children[insertPosition+1:])
|
||||||
|
parent.Children[insertPosition+1] = right
|
||||||
|
|
||||||
|
tree.split(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) splitRoot() {
|
||||||
|
middle := tree.middle()
|
||||||
|
|
||||||
|
left := &Node{Entries: append([]*Entry(nil), tree.Root.Entries[:middle]...)}
|
||||||
|
right := &Node{Entries: append([]*Entry(nil), tree.Root.Entries[middle+1:]...)}
|
||||||
|
|
||||||
|
// Move children from the node to be split into left and right nodes
|
||||||
|
if !tree.isLeaf(tree.Root) {
|
||||||
|
left.Children = append([]*Node(nil), tree.Root.Children[:middle+1]...)
|
||||||
|
right.Children = append([]*Node(nil), tree.Root.Children[middle+1:]...)
|
||||||
|
setParent(left.Children, left)
|
||||||
|
setParent(right.Children, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root is a node with one entry and two children (left and right)
|
||||||
|
newRoot := &Node{
|
||||||
|
Entries: []*Entry{tree.Root.Entries[middle]},
|
||||||
|
Children: []*Node{left, right},
|
||||||
|
}
|
||||||
|
|
||||||
|
left.Parent = newRoot
|
||||||
|
right.Parent = newRoot
|
||||||
|
tree.Root = newRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
func setParent(nodes []*Node, parent *Node) {
|
||||||
|
for _, node := range nodes {
|
||||||
|
node.Parent = parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) left(node *Node) *Node {
|
||||||
|
if tree.Empty() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
current := node
|
||||||
|
for {
|
||||||
|
if tree.isLeaf(current) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
current = current.Children[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) right(node *Node) *Node {
|
||||||
|
if tree.Empty() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
current := node
|
||||||
|
for {
|
||||||
|
if tree.isLeaf(current) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
current = current.Children[len(current.Children)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// leftSibling returns the node's left sibling and child index (in parent) if it exists, otherwise (nil,-1)
|
||||||
|
// key is any of keys in node (could even be deleted).
|
||||||
|
func (tree *Tree) leftSibling(node *Node, key interface{}) (*Node, int) {
|
||||||
|
if node.Parent != nil {
|
||||||
|
index, _ := tree.search(node.Parent, key)
|
||||||
|
index--
|
||||||
|
if index >= 0 && index < len(node.Parent.Children) {
|
||||||
|
return node.Parent.Children[index], index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// rightSibling returns the node's right sibling and child index (in parent) if it exists, otherwise (nil,-1)
|
||||||
|
// key is any of keys in node (could even be deleted).
|
||||||
|
func (tree *Tree) rightSibling(node *Node, key interface{}) (*Node, int) {
|
||||||
|
if node.Parent != nil {
|
||||||
|
index, _ := tree.search(node.Parent, key)
|
||||||
|
index++
|
||||||
|
if index < len(node.Parent.Children) {
|
||||||
|
return node.Parent.Children[index], index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete deletes an entry in node at entries' index
|
||||||
|
// ref.: https://en.wikipedia.org/wiki/B-tree#Deletion
|
||||||
|
func (tree *Tree) delete(node *Node, index int) {
|
||||||
|
// deleting from a leaf node
|
||||||
|
if tree.isLeaf(node) {
|
||||||
|
deletedKey := node.Entries[index].Key
|
||||||
|
tree.deleteEntry(node, index)
|
||||||
|
tree.rebalance(node, deletedKey)
|
||||||
|
if len(tree.Root.Entries) == 0 {
|
||||||
|
tree.Root = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleting from an internal node
|
||||||
|
leftLargestNode := tree.right(node.Children[index]) // largest node in the left sub-tree (assumed to exist)
|
||||||
|
leftLargestEntryIndex := len(leftLargestNode.Entries) - 1
|
||||||
|
node.Entries[index] = leftLargestNode.Entries[leftLargestEntryIndex]
|
||||||
|
deletedKey := leftLargestNode.Entries[leftLargestEntryIndex].Key
|
||||||
|
tree.deleteEntry(leftLargestNode, leftLargestEntryIndex)
|
||||||
|
tree.rebalance(leftLargestNode, deletedKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rebalance rebalances the tree after deletion if necessary and returns true, otherwise false.
|
||||||
|
// Note that we first delete the entry and then call rebalance, thus the passed deleted key as reference.
|
||||||
|
func (tree *Tree) rebalance(node *Node, deletedKey interface{}) {
|
||||||
|
// check if rebalancing is needed
|
||||||
|
if node == nil || len(node.Entries) >= tree.minEntries() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to borrow from left sibling
|
||||||
|
leftSibling, leftSiblingIndex := tree.leftSibling(node, deletedKey)
|
||||||
|
if leftSibling != nil && len(leftSibling.Entries) > tree.minEntries() {
|
||||||
|
// rotate right
|
||||||
|
node.Entries = append([]*Entry{node.Parent.Entries[leftSiblingIndex]}, node.Entries...) // prepend parent's separator entry to node's entries
|
||||||
|
node.Parent.Entries[leftSiblingIndex] = leftSibling.Entries[len(leftSibling.Entries)-1]
|
||||||
|
tree.deleteEntry(leftSibling, len(leftSibling.Entries)-1)
|
||||||
|
if !tree.isLeaf(leftSibling) {
|
||||||
|
leftSiblingRightMostChild := leftSibling.Children[len(leftSibling.Children)-1]
|
||||||
|
leftSiblingRightMostChild.Parent = node
|
||||||
|
node.Children = append([]*Node{leftSiblingRightMostChild}, node.Children...)
|
||||||
|
tree.deleteChild(leftSibling, len(leftSibling.Children)-1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to borrow from right sibling
|
||||||
|
rightSibling, rightSiblingIndex := tree.rightSibling(node, deletedKey)
|
||||||
|
if rightSibling != nil && len(rightSibling.Entries) > tree.minEntries() {
|
||||||
|
// rotate left
|
||||||
|
node.Entries = append(node.Entries, node.Parent.Entries[rightSiblingIndex-1]) // append parent's separator entry to node's entries
|
||||||
|
node.Parent.Entries[rightSiblingIndex-1] = rightSibling.Entries[0]
|
||||||
|
tree.deleteEntry(rightSibling, 0)
|
||||||
|
if !tree.isLeaf(rightSibling) {
|
||||||
|
rightSiblingLeftMostChild := rightSibling.Children[0]
|
||||||
|
rightSiblingLeftMostChild.Parent = node
|
||||||
|
node.Children = append(node.Children, rightSiblingLeftMostChild)
|
||||||
|
tree.deleteChild(rightSibling, 0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge with siblings
|
||||||
|
if rightSibling != nil {
|
||||||
|
// merge with right sibling
|
||||||
|
node.Entries = append(node.Entries, node.Parent.Entries[rightSiblingIndex-1])
|
||||||
|
node.Entries = append(node.Entries, rightSibling.Entries...)
|
||||||
|
deletedKey = node.Parent.Entries[rightSiblingIndex-1].Key
|
||||||
|
tree.deleteEntry(node.Parent, rightSiblingIndex-1)
|
||||||
|
tree.appendChildren(node.Parent.Children[rightSiblingIndex], node)
|
||||||
|
tree.deleteChild(node.Parent, rightSiblingIndex)
|
||||||
|
} else if leftSibling != nil {
|
||||||
|
// merge with left sibling
|
||||||
|
entries := append([]*Entry(nil), leftSibling.Entries...)
|
||||||
|
entries = append(entries, node.Parent.Entries[leftSiblingIndex])
|
||||||
|
node.Entries = append(entries, node.Entries...)
|
||||||
|
deletedKey = node.Parent.Entries[leftSiblingIndex].Key
|
||||||
|
tree.deleteEntry(node.Parent, leftSiblingIndex)
|
||||||
|
tree.prependChildren(node.Parent.Children[leftSiblingIndex], node)
|
||||||
|
tree.deleteChild(node.Parent, leftSiblingIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the merged node the root if its parent was the root and the root is empty
|
||||||
|
if node.Parent == tree.Root && len(tree.Root.Entries) == 0 {
|
||||||
|
tree.Root = node
|
||||||
|
node.Parent = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// parent might underflow, so try to rebalance if necessary
|
||||||
|
tree.rebalance(node.Parent, deletedKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) prependChildren(fromNode *Node, toNode *Node) {
|
||||||
|
children := append([]*Node(nil), fromNode.Children...)
|
||||||
|
toNode.Children = append(children, toNode.Children...)
|
||||||
|
setParent(fromNode.Children, toNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) appendChildren(fromNode *Node, toNode *Node) {
|
||||||
|
toNode.Children = append(toNode.Children, fromNode.Children...)
|
||||||
|
setParent(fromNode.Children, toNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) deleteEntry(node *Node, index int) {
|
||||||
|
copy(node.Entries[index:], node.Entries[index+1:])
|
||||||
|
node.Entries[len(node.Entries)-1] = nil
|
||||||
|
node.Entries = node.Entries[:len(node.Entries)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) deleteChild(node *Node, index int) {
|
||||||
|
if index >= len(node.Children) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
copy(node.Children[index:], node.Children[index+1:])
|
||||||
|
node.Children[len(node.Children)-1] = nil
|
||||||
|
node.Children = node.Children[:len(node.Children)-1]
|
||||||
|
}
|
1259
vendor/github.com/emirpasic/gods/trees/btree/btree_test.go
generated
vendored
Normal file
1259
vendor/github.com/emirpasic/gods/trees/btree/btree_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
193
vendor/github.com/emirpasic/gods/trees/btree/iterator.go
generated
vendored
Normal file
193
vendor/github.com/emirpasic/gods/trees/btree/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package btree
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
tree *Tree
|
||||||
|
node *Node
|
||||||
|
entry *Entry
|
||||||
|
position position
|
||||||
|
}
|
||||||
|
|
||||||
|
type position byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
begin, between, end position = 0, 1, 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose elements are key/value pairs.
|
||||||
|
func (tree *Tree) Iterator() Iterator {
|
||||||
|
return Iterator{tree: tree, node: nil, position: begin}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
// If already at end, go to end
|
||||||
|
if iterator.position == end {
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
// If at beginning, get the left-most entry in the tree
|
||||||
|
if iterator.position == begin {
|
||||||
|
left := iterator.tree.Left()
|
||||||
|
if left == nil {
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
iterator.node = left
|
||||||
|
iterator.entry = left.Entries[0]
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Find current entry position in current node
|
||||||
|
e, _ := iterator.tree.search(iterator.node, iterator.entry.Key)
|
||||||
|
// Try to go down to the child right of the current entry
|
||||||
|
if e+1 < len(iterator.node.Children) {
|
||||||
|
iterator.node = iterator.node.Children[e+1]
|
||||||
|
// Try to go down to the child left of the current node
|
||||||
|
for len(iterator.node.Children) > 0 {
|
||||||
|
iterator.node = iterator.node.Children[0]
|
||||||
|
}
|
||||||
|
// Return the left-most entry
|
||||||
|
iterator.entry = iterator.node.Entries[0]
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
// Above assures that we have reached a leaf node, so return the next entry in current node (if any)
|
||||||
|
if e+1 < len(iterator.node.Entries) {
|
||||||
|
iterator.entry = iterator.node.Entries[e+1]
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reached leaf node and there are no entries to the right of the current entry, so go up to the parent
|
||||||
|
for iterator.node.Parent != nil {
|
||||||
|
iterator.node = iterator.node.Parent
|
||||||
|
// Find next entry position in current node (note: search returns the first equal or bigger than entry)
|
||||||
|
e, _ := iterator.tree.search(iterator.node, iterator.entry.Key)
|
||||||
|
// Check that there is a next entry position in current node
|
||||||
|
if e < len(iterator.node.Entries) {
|
||||||
|
iterator.entry = iterator.node.Entries[e]
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
iterator.End()
|
||||||
|
return false
|
||||||
|
|
||||||
|
between:
|
||||||
|
iterator.position = between
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
// If already at beginning, go to begin
|
||||||
|
if iterator.position == begin {
|
||||||
|
goto begin
|
||||||
|
}
|
||||||
|
// If at end, get the right-most entry in the tree
|
||||||
|
if iterator.position == end {
|
||||||
|
right := iterator.tree.Right()
|
||||||
|
if right == nil {
|
||||||
|
goto begin
|
||||||
|
}
|
||||||
|
iterator.node = right
|
||||||
|
iterator.entry = right.Entries[len(right.Entries)-1]
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Find current entry position in current node
|
||||||
|
e, _ := iterator.tree.search(iterator.node, iterator.entry.Key)
|
||||||
|
// Try to go down to the child left of the current entry
|
||||||
|
if e < len(iterator.node.Children) {
|
||||||
|
iterator.node = iterator.node.Children[e]
|
||||||
|
// Try to go down to the child right of the current node
|
||||||
|
for len(iterator.node.Children) > 0 {
|
||||||
|
iterator.node = iterator.node.Children[len(iterator.node.Children)-1]
|
||||||
|
}
|
||||||
|
// Return the right-most entry
|
||||||
|
iterator.entry = iterator.node.Entries[len(iterator.node.Entries)-1]
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
// Above assures that we have reached a leaf node, so return the previous entry in current node (if any)
|
||||||
|
if e-1 >= 0 {
|
||||||
|
iterator.entry = iterator.node.Entries[e-1]
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reached leaf node and there are no entries to the left of the current entry, so go up to the parent
|
||||||
|
for iterator.node.Parent != nil {
|
||||||
|
iterator.node = iterator.node.Parent
|
||||||
|
// Find previous entry position in current node (note: search returns the first equal or bigger than entry)
|
||||||
|
e, _ := iterator.tree.search(iterator.node, iterator.entry.Key)
|
||||||
|
// Check that there is a previous entry position in current node
|
||||||
|
if e-1 >= 0 {
|
||||||
|
iterator.entry = iterator.node.Entries[e-1]
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
begin:
|
||||||
|
iterator.Begin()
|
||||||
|
return false
|
||||||
|
|
||||||
|
between:
|
||||||
|
iterator.position = between
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
return iterator.entry.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the current element's key.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Key() interface{} {
|
||||||
|
return iterator.entry.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.node = nil
|
||||||
|
iterator.position = begin
|
||||||
|
iterator.entry = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.node = nil
|
||||||
|
iterator.position = end
|
||||||
|
iterator.entry = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
iterator.End()
|
||||||
|
return iterator.Prev()
|
||||||
|
}
|
39
vendor/github.com/emirpasic/gods/trees/btree/serialization.go
generated
vendored
Normal file
39
vendor/github.com/emirpasic/gods/trees/btree/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package btree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Tree)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Tree)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (tree *Tree) ToJSON() ([]byte, error) {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
elements[utils.ToString(it.Key())] = it.Value()
|
||||||
|
}
|
||||||
|
return json.Marshal(&elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (tree *Tree) FromJSON(data []byte) error {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
tree.Clear()
|
||||||
|
for key, value := range elements {
|
||||||
|
tree.Put(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
156
vendor/github.com/emirpasic/gods/trees/redblacktree/iterator.go
generated
vendored
Normal file
156
vendor/github.com/emirpasic/gods/trees/redblacktree/iterator.go
generated
vendored
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package redblacktree
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
tree *Tree
|
||||||
|
node *Node
|
||||||
|
position position
|
||||||
|
}
|
||||||
|
|
||||||
|
type position byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
begin, between, end position = 0, 1, 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose elements are key/value pairs.
|
||||||
|
func (tree *Tree) Iterator() Iterator {
|
||||||
|
return Iterator{tree: tree, node: nil, position: begin}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
if iterator.position == end {
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
if iterator.position == begin {
|
||||||
|
left := iterator.tree.Left()
|
||||||
|
if left == nil {
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
iterator.node = left
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
if iterator.node.Right != nil {
|
||||||
|
iterator.node = iterator.node.Right
|
||||||
|
for iterator.node.Left != nil {
|
||||||
|
iterator.node = iterator.node.Left
|
||||||
|
}
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
if iterator.node.Parent != nil {
|
||||||
|
node := iterator.node
|
||||||
|
for iterator.node.Parent != nil {
|
||||||
|
iterator.node = iterator.node.Parent
|
||||||
|
if iterator.tree.Comparator(node.Key, iterator.node.Key) <= 0 {
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
iterator.node = nil
|
||||||
|
iterator.position = end
|
||||||
|
return false
|
||||||
|
|
||||||
|
between:
|
||||||
|
iterator.position = between
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
if iterator.position == begin {
|
||||||
|
goto begin
|
||||||
|
}
|
||||||
|
if iterator.position == end {
|
||||||
|
right := iterator.tree.Right()
|
||||||
|
if right == nil {
|
||||||
|
goto begin
|
||||||
|
}
|
||||||
|
iterator.node = right
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
if iterator.node.Left != nil {
|
||||||
|
iterator.node = iterator.node.Left
|
||||||
|
for iterator.node.Right != nil {
|
||||||
|
iterator.node = iterator.node.Right
|
||||||
|
}
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
if iterator.node.Parent != nil {
|
||||||
|
node := iterator.node
|
||||||
|
for iterator.node.Parent != nil {
|
||||||
|
iterator.node = iterator.node.Parent
|
||||||
|
if iterator.tree.Comparator(node.Key, iterator.node.Key) >= 0 {
|
||||||
|
goto between
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
begin:
|
||||||
|
iterator.node = nil
|
||||||
|
iterator.position = begin
|
||||||
|
return false
|
||||||
|
|
||||||
|
between:
|
||||||
|
iterator.position = between
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
return iterator.node.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the current element's key.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Key() interface{} {
|
||||||
|
return iterator.node.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.node = nil
|
||||||
|
iterator.position = begin
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.node = nil
|
||||||
|
iterator.position = end
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
iterator.Begin()
|
||||||
|
return iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
iterator.End()
|
||||||
|
return iterator.Prev()
|
||||||
|
}
|
522
vendor/github.com/emirpasic/gods/trees/redblacktree/redblacktree.go
generated
vendored
Normal file
522
vendor/github.com/emirpasic/gods/trees/redblacktree/redblacktree.go
generated
vendored
Normal file
|
@ -0,0 +1,522 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package redblacktree implements a red-black tree.
|
||||||
|
//
|
||||||
|
// Used by TreeSet and TreeMap.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// References: http://en.wikipedia.org/wiki/Red%E2%80%93black_tree
|
||||||
|
package redblacktree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/trees"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertTreeImplementation() {
|
||||||
|
var _ trees.Tree = (*Tree)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
type color bool
|
||||||
|
|
||||||
|
const (
|
||||||
|
black, red color = true, false
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tree holds elements of the red-black tree
|
||||||
|
type Tree struct {
|
||||||
|
Root *Node
|
||||||
|
size int
|
||||||
|
Comparator utils.Comparator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node is a single element within the tree
|
||||||
|
type Node struct {
|
||||||
|
Key interface{}
|
||||||
|
Value interface{}
|
||||||
|
color color
|
||||||
|
Left *Node
|
||||||
|
Right *Node
|
||||||
|
Parent *Node
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWith instantiates a red-black tree with the custom comparator.
|
||||||
|
func NewWith(comparator utils.Comparator) *Tree {
|
||||||
|
return &Tree{Comparator: comparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithIntComparator instantiates a red-black tree with the IntComparator, i.e. keys are of type int.
|
||||||
|
func NewWithIntComparator() *Tree {
|
||||||
|
return &Tree{Comparator: utils.IntComparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithStringComparator instantiates a red-black tree with the StringComparator, i.e. keys are of type string.
|
||||||
|
func NewWithStringComparator() *Tree {
|
||||||
|
return &Tree{Comparator: utils.StringComparator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put inserts node into the tree.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (tree *Tree) Put(key interface{}, value interface{}) {
|
||||||
|
insertedNode := &Node{Key: key, Value: value, color: red}
|
||||||
|
if tree.Root == nil {
|
||||||
|
tree.Root = insertedNode
|
||||||
|
} else {
|
||||||
|
node := tree.Root
|
||||||
|
loop := true
|
||||||
|
for loop {
|
||||||
|
compare := tree.Comparator(key, node.Key)
|
||||||
|
switch {
|
||||||
|
case compare == 0:
|
||||||
|
node.Key = key
|
||||||
|
node.Value = value
|
||||||
|
return
|
||||||
|
case compare < 0:
|
||||||
|
if node.Left == nil {
|
||||||
|
node.Left = insertedNode
|
||||||
|
loop = false
|
||||||
|
} else {
|
||||||
|
node = node.Left
|
||||||
|
}
|
||||||
|
case compare > 0:
|
||||||
|
if node.Right == nil {
|
||||||
|
node.Right = insertedNode
|
||||||
|
loop = false
|
||||||
|
} else {
|
||||||
|
node = node.Right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
insertedNode.Parent = node
|
||||||
|
}
|
||||||
|
tree.insertCase1(insertedNode)
|
||||||
|
tree.size++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get searches the node in the tree by key and returns its value or nil if key is not found in tree.
|
||||||
|
// Second return parameter is true if key was found, otherwise false.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (tree *Tree) Get(key interface{}) (value interface{}, found bool) {
|
||||||
|
node := tree.lookup(key)
|
||||||
|
if node != nil {
|
||||||
|
return node.Value, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove remove the node from the tree by key.
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (tree *Tree) Remove(key interface{}) {
|
||||||
|
var child *Node
|
||||||
|
node := tree.lookup(key)
|
||||||
|
if node == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if node.Left != nil && node.Right != nil {
|
||||||
|
pred := node.Left.maximumNode()
|
||||||
|
node.Key = pred.Key
|
||||||
|
node.Value = pred.Value
|
||||||
|
node = pred
|
||||||
|
}
|
||||||
|
if node.Left == nil || node.Right == nil {
|
||||||
|
if node.Right == nil {
|
||||||
|
child = node.Left
|
||||||
|
} else {
|
||||||
|
child = node.Right
|
||||||
|
}
|
||||||
|
if node.color == black {
|
||||||
|
node.color = nodeColor(child)
|
||||||
|
tree.deleteCase1(node)
|
||||||
|
}
|
||||||
|
tree.replaceNode(node, child)
|
||||||
|
if node.Parent == nil && child != nil {
|
||||||
|
child.color = black
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tree.size--
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if tree does not contain any nodes
|
||||||
|
func (tree *Tree) Empty() bool {
|
||||||
|
return tree.size == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of nodes in the tree.
|
||||||
|
func (tree *Tree) Size() int {
|
||||||
|
return tree.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys in-order
|
||||||
|
func (tree *Tree) Keys() []interface{} {
|
||||||
|
keys := make([]interface{}, tree.size)
|
||||||
|
it := tree.Iterator()
|
||||||
|
for i := 0; it.Next(); i++ {
|
||||||
|
keys[i] = it.Key()
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all values in-order based on the key.
|
||||||
|
func (tree *Tree) Values() []interface{} {
|
||||||
|
values := make([]interface{}, tree.size)
|
||||||
|
it := tree.Iterator()
|
||||||
|
for i := 0; it.Next(); i++ {
|
||||||
|
values[i] = it.Value()
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left returns the left-most (min) node or nil if tree is empty.
|
||||||
|
func (tree *Tree) Left() *Node {
|
||||||
|
var parent *Node
|
||||||
|
current := tree.Root
|
||||||
|
for current != nil {
|
||||||
|
parent = current
|
||||||
|
current = current.Left
|
||||||
|
}
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right returns the right-most (max) node or nil if tree is empty.
|
||||||
|
func (tree *Tree) Right() *Node {
|
||||||
|
var parent *Node
|
||||||
|
current := tree.Root
|
||||||
|
for current != nil {
|
||||||
|
parent = current
|
||||||
|
current = current.Right
|
||||||
|
}
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floor Finds floor node of the input key, return the floor node or nil if no ceiling is found.
|
||||||
|
// Second return parameter is true if floor was found, otherwise false.
|
||||||
|
//
|
||||||
|
// Floor node is defined as the largest node that is smaller than or equal to the given node.
|
||||||
|
// A floor node may not be found, either because the tree is empty, or because
|
||||||
|
// all nodes in the tree is larger than the given node.
|
||||||
|
//
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (tree *Tree) Floor(key interface{}) (floor *Node, found bool) {
|
||||||
|
found = false
|
||||||
|
node := tree.Root
|
||||||
|
for node != nil {
|
||||||
|
compare := tree.Comparator(key, node.Key)
|
||||||
|
switch {
|
||||||
|
case compare == 0:
|
||||||
|
return node, true
|
||||||
|
case compare < 0:
|
||||||
|
node = node.Left
|
||||||
|
case compare > 0:
|
||||||
|
floor, found = node, true
|
||||||
|
node = node.Right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
return floor, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ceiling finds ceiling node of the input key, return the ceiling node or nil if no ceiling is found.
|
||||||
|
// Second return parameter is true if ceiling was found, otherwise false.
|
||||||
|
//
|
||||||
|
// Ceiling node is defined as the smallest node that is larger than or equal to the given node.
|
||||||
|
// A ceiling node may not be found, either because the tree is empty, or because
|
||||||
|
// all nodes in the tree is smaller than the given node.
|
||||||
|
//
|
||||||
|
// Key should adhere to the comparator's type assertion, otherwise method panics.
|
||||||
|
func (tree *Tree) Ceiling(key interface{}) (ceiling *Node, found bool) {
|
||||||
|
found = false
|
||||||
|
node := tree.Root
|
||||||
|
for node != nil {
|
||||||
|
compare := tree.Comparator(key, node.Key)
|
||||||
|
switch {
|
||||||
|
case compare == 0:
|
||||||
|
return node, true
|
||||||
|
case compare < 0:
|
||||||
|
ceiling, found = node, true
|
||||||
|
node = node.Left
|
||||||
|
case compare > 0:
|
||||||
|
node = node.Right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
return ceiling, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all nodes from the tree.
|
||||||
|
func (tree *Tree) Clear() {
|
||||||
|
tree.Root = nil
|
||||||
|
tree.size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (tree *Tree) String() string {
|
||||||
|
str := "RedBlackTree\n"
|
||||||
|
if !tree.Empty() {
|
||||||
|
output(tree.Root, "", true, &str)
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *Node) String() string {
|
||||||
|
return fmt.Sprintf("%v", node.Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func output(node *Node, prefix string, isTail bool, str *string) {
|
||||||
|
if node.Right != nil {
|
||||||
|
newPrefix := prefix
|
||||||
|
if isTail {
|
||||||
|
newPrefix += "│ "
|
||||||
|
} else {
|
||||||
|
newPrefix += " "
|
||||||
|
}
|
||||||
|
output(node.Right, newPrefix, false, str)
|
||||||
|
}
|
||||||
|
*str += prefix
|
||||||
|
if isTail {
|
||||||
|
*str += "└── "
|
||||||
|
} else {
|
||||||
|
*str += "┌── "
|
||||||
|
}
|
||||||
|
*str += node.String() + "\n"
|
||||||
|
if node.Left != nil {
|
||||||
|
newPrefix := prefix
|
||||||
|
if isTail {
|
||||||
|
newPrefix += " "
|
||||||
|
} else {
|
||||||
|
newPrefix += "│ "
|
||||||
|
}
|
||||||
|
output(node.Left, newPrefix, true, str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) lookup(key interface{}) *Node {
|
||||||
|
node := tree.Root
|
||||||
|
for node != nil {
|
||||||
|
compare := tree.Comparator(key, node.Key)
|
||||||
|
switch {
|
||||||
|
case compare == 0:
|
||||||
|
return node
|
||||||
|
case compare < 0:
|
||||||
|
node = node.Left
|
||||||
|
case compare > 0:
|
||||||
|
node = node.Right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *Node) grandparent() *Node {
|
||||||
|
if node != nil && node.Parent != nil {
|
||||||
|
return node.Parent.Parent
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *Node) uncle() *Node {
|
||||||
|
if node == nil || node.Parent == nil || node.Parent.Parent == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return node.Parent.sibling()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *Node) sibling() *Node {
|
||||||
|
if node == nil || node.Parent == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if node == node.Parent.Left {
|
||||||
|
return node.Parent.Right
|
||||||
|
}
|
||||||
|
return node.Parent.Left
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) rotateLeft(node *Node) {
|
||||||
|
right := node.Right
|
||||||
|
tree.replaceNode(node, right)
|
||||||
|
node.Right = right.Left
|
||||||
|
if right.Left != nil {
|
||||||
|
right.Left.Parent = node
|
||||||
|
}
|
||||||
|
right.Left = node
|
||||||
|
node.Parent = right
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) rotateRight(node *Node) {
|
||||||
|
left := node.Left
|
||||||
|
tree.replaceNode(node, left)
|
||||||
|
node.Left = left.Right
|
||||||
|
if left.Right != nil {
|
||||||
|
left.Right.Parent = node
|
||||||
|
}
|
||||||
|
left.Right = node
|
||||||
|
node.Parent = left
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) replaceNode(old *Node, new *Node) {
|
||||||
|
if old.Parent == nil {
|
||||||
|
tree.Root = new
|
||||||
|
} else {
|
||||||
|
if old == old.Parent.Left {
|
||||||
|
old.Parent.Left = new
|
||||||
|
} else {
|
||||||
|
old.Parent.Right = new
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if new != nil {
|
||||||
|
new.Parent = old.Parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) insertCase1(node *Node) {
|
||||||
|
if node.Parent == nil {
|
||||||
|
node.color = black
|
||||||
|
} else {
|
||||||
|
tree.insertCase2(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) insertCase2(node *Node) {
|
||||||
|
if nodeColor(node.Parent) == black {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tree.insertCase3(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) insertCase3(node *Node) {
|
||||||
|
uncle := node.uncle()
|
||||||
|
if nodeColor(uncle) == red {
|
||||||
|
node.Parent.color = black
|
||||||
|
uncle.color = black
|
||||||
|
node.grandparent().color = red
|
||||||
|
tree.insertCase1(node.grandparent())
|
||||||
|
} else {
|
||||||
|
tree.insertCase4(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) insertCase4(node *Node) {
|
||||||
|
grandparent := node.grandparent()
|
||||||
|
if node == node.Parent.Right && node.Parent == grandparent.Left {
|
||||||
|
tree.rotateLeft(node.Parent)
|
||||||
|
node = node.Left
|
||||||
|
} else if node == node.Parent.Left && node.Parent == grandparent.Right {
|
||||||
|
tree.rotateRight(node.Parent)
|
||||||
|
node = node.Right
|
||||||
|
}
|
||||||
|
tree.insertCase5(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) insertCase5(node *Node) {
|
||||||
|
node.Parent.color = black
|
||||||
|
grandparent := node.grandparent()
|
||||||
|
grandparent.color = red
|
||||||
|
if node == node.Parent.Left && node.Parent == grandparent.Left {
|
||||||
|
tree.rotateRight(grandparent)
|
||||||
|
} else if node == node.Parent.Right && node.Parent == grandparent.Right {
|
||||||
|
tree.rotateLeft(grandparent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *Node) maximumNode() *Node {
|
||||||
|
if node == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for node.Right != nil {
|
||||||
|
node = node.Right
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) deleteCase1(node *Node) {
|
||||||
|
if node.Parent == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tree.deleteCase2(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) deleteCase2(node *Node) {
|
||||||
|
sibling := node.sibling()
|
||||||
|
if nodeColor(sibling) == red {
|
||||||
|
node.Parent.color = red
|
||||||
|
sibling.color = black
|
||||||
|
if node == node.Parent.Left {
|
||||||
|
tree.rotateLeft(node.Parent)
|
||||||
|
} else {
|
||||||
|
tree.rotateRight(node.Parent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tree.deleteCase3(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) deleteCase3(node *Node) {
|
||||||
|
sibling := node.sibling()
|
||||||
|
if nodeColor(node.Parent) == black &&
|
||||||
|
nodeColor(sibling) == black &&
|
||||||
|
nodeColor(sibling.Left) == black &&
|
||||||
|
nodeColor(sibling.Right) == black {
|
||||||
|
sibling.color = red
|
||||||
|
tree.deleteCase1(node.Parent)
|
||||||
|
} else {
|
||||||
|
tree.deleteCase4(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) deleteCase4(node *Node) {
|
||||||
|
sibling := node.sibling()
|
||||||
|
if nodeColor(node.Parent) == red &&
|
||||||
|
nodeColor(sibling) == black &&
|
||||||
|
nodeColor(sibling.Left) == black &&
|
||||||
|
nodeColor(sibling.Right) == black {
|
||||||
|
sibling.color = red
|
||||||
|
node.Parent.color = black
|
||||||
|
} else {
|
||||||
|
tree.deleteCase5(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) deleteCase5(node *Node) {
|
||||||
|
sibling := node.sibling()
|
||||||
|
if node == node.Parent.Left &&
|
||||||
|
nodeColor(sibling) == black &&
|
||||||
|
nodeColor(sibling.Left) == red &&
|
||||||
|
nodeColor(sibling.Right) == black {
|
||||||
|
sibling.color = red
|
||||||
|
sibling.Left.color = black
|
||||||
|
tree.rotateRight(sibling)
|
||||||
|
} else if node == node.Parent.Right &&
|
||||||
|
nodeColor(sibling) == black &&
|
||||||
|
nodeColor(sibling.Right) == red &&
|
||||||
|
nodeColor(sibling.Left) == black {
|
||||||
|
sibling.color = red
|
||||||
|
sibling.Right.color = black
|
||||||
|
tree.rotateLeft(sibling)
|
||||||
|
}
|
||||||
|
tree.deleteCase6(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree *Tree) deleteCase6(node *Node) {
|
||||||
|
sibling := node.sibling()
|
||||||
|
sibling.color = nodeColor(node.Parent)
|
||||||
|
node.Parent.color = black
|
||||||
|
if node == node.Parent.Left && nodeColor(sibling.Right) == red {
|
||||||
|
sibling.Right.color = black
|
||||||
|
tree.rotateLeft(node.Parent)
|
||||||
|
} else if nodeColor(sibling.Left) == red {
|
||||||
|
sibling.Left.color = black
|
||||||
|
tree.rotateRight(node.Parent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nodeColor(node *Node) color {
|
||||||
|
if node == nil {
|
||||||
|
return black
|
||||||
|
}
|
||||||
|
return node.color
|
||||||
|
}
|
742
vendor/github.com/emirpasic/gods/trees/redblacktree/redblacktree_test.go
generated
vendored
Normal file
742
vendor/github.com/emirpasic/gods/trees/redblacktree/redblacktree_test.go
generated
vendored
Normal file
|
@ -0,0 +1,742 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package redblacktree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRedBlackTreePut(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
tree.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
if actualValue := tree.Size(); actualValue != 7 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d%d%d%d", tree.Keys()...), "1234567"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s", tree.Values()...), "abcdefg"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests1 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, "e", true},
|
||||||
|
{6, "f", true},
|
||||||
|
{7, "g", true},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests1 {
|
||||||
|
// retrievals
|
||||||
|
actualValue, actualFound := tree.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeRemove(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
tree.Put(1, "a") //overwrite
|
||||||
|
|
||||||
|
tree.Remove(5)
|
||||||
|
tree.Remove(6)
|
||||||
|
tree.Remove(7)
|
||||||
|
tree.Remove(8)
|
||||||
|
tree.Remove(5)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d", tree.Keys()...), "1234"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", tree.Values()...), "abcd"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := tree.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests2 := [][]interface{}{
|
||||||
|
{1, "a", true},
|
||||||
|
{2, "b", true},
|
||||||
|
{3, "c", true},
|
||||||
|
{4, "d", true},
|
||||||
|
{5, nil, false},
|
||||||
|
{6, nil, false},
|
||||||
|
{7, nil, false},
|
||||||
|
{8, nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests2 {
|
||||||
|
actualValue, actualFound := tree.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.Remove(1)
|
||||||
|
tree.Remove(4)
|
||||||
|
tree.Remove(2)
|
||||||
|
tree.Remove(3)
|
||||||
|
tree.Remove(2)
|
||||||
|
tree.Remove(2)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", tree.Keys()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", tree.Values()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if empty, size := tree.Empty(), tree.Size(); empty != true || size != -0 {
|
||||||
|
t.Errorf("Got %v expected %v", empty, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeLeftAndRight(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
|
||||||
|
if actualValue := tree.Left(); actualValue != nil {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
if actualValue := tree.Right(); actualValue != nil {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x") // overwrite
|
||||||
|
tree.Put(2, "b")
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d", tree.Left().Key), "1"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", tree.Left().Value), "x"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%d", tree.Right().Key), "7"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", tree.Right().Value), "g"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeCeilingAndFloor(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
|
||||||
|
if node, found := tree.Floor(0); node != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", node, "<nil>")
|
||||||
|
}
|
||||||
|
if node, found := tree.Ceiling(0); node != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", node, "<nil>")
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
|
||||||
|
if node, found := tree.Floor(4); node.Key != 4 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", node.Key, 4)
|
||||||
|
}
|
||||||
|
if node, found := tree.Floor(0); node != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", node, "<nil>")
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, found := tree.Ceiling(4); node.Key != 4 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", node.Key, 4)
|
||||||
|
}
|
||||||
|
if node, found := tree.Ceiling(8); node != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", node, "<nil>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty tree")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIteratorPrevOnEmpty(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty tree")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIterator1Next(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
tree.Put(1, "a") //overwrite
|
||||||
|
// │ ┌── 7
|
||||||
|
// └── 6
|
||||||
|
// │ ┌── 5
|
||||||
|
// └── 4
|
||||||
|
// │ ┌── 3
|
||||||
|
// └── 2
|
||||||
|
// └── 1
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIterator1Prev(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(5, "e")
|
||||||
|
tree.Put(6, "f")
|
||||||
|
tree.Put(7, "g")
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(4, "d")
|
||||||
|
tree.Put(1, "x")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
tree.Put(1, "a") //overwrite
|
||||||
|
// │ ┌── 7
|
||||||
|
// └── 6
|
||||||
|
// │ ┌── 5
|
||||||
|
// └── 4
|
||||||
|
// │ ┌── 3
|
||||||
|
// └── 2
|
||||||
|
// └── 1
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := tree.size
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case countDown:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIterator2Next(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIterator2Prev(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := tree.size
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case countDown:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIterator3Next(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(1, "a")
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIterator3Prev(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(1, "a")
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := tree.size
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
switch key {
|
||||||
|
case countDown:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := key, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIterator4Next(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(13, 5)
|
||||||
|
tree.Put(8, 3)
|
||||||
|
tree.Put(17, 7)
|
||||||
|
tree.Put(1, 1)
|
||||||
|
tree.Put(11, 4)
|
||||||
|
tree.Put(15, 6)
|
||||||
|
tree.Put(25, 9)
|
||||||
|
tree.Put(6, 2)
|
||||||
|
tree.Put(22, 8)
|
||||||
|
tree.Put(27, 10)
|
||||||
|
// │ ┌── 27
|
||||||
|
// │ ┌── 25
|
||||||
|
// │ │ └── 22
|
||||||
|
// │ ┌── 17
|
||||||
|
// │ │ └── 15
|
||||||
|
// └── 13
|
||||||
|
// │ ┌── 11
|
||||||
|
// └── 8
|
||||||
|
// │ ┌── 6
|
||||||
|
// └── 1
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
value := it.Value()
|
||||||
|
switch value {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIterator4Prev(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(13, 5)
|
||||||
|
tree.Put(8, 3)
|
||||||
|
tree.Put(17, 7)
|
||||||
|
tree.Put(1, 1)
|
||||||
|
tree.Put(11, 4)
|
||||||
|
tree.Put(15, 6)
|
||||||
|
tree.Put(25, 9)
|
||||||
|
tree.Put(6, 2)
|
||||||
|
tree.Put(22, 8)
|
||||||
|
tree.Put(27, 10)
|
||||||
|
// │ ┌── 27
|
||||||
|
// │ ┌── 25
|
||||||
|
// │ │ └── 22
|
||||||
|
// │ ┌── 17
|
||||||
|
// │ │ └── 15
|
||||||
|
// └── 13
|
||||||
|
// │ ┌── 11
|
||||||
|
// └── 8
|
||||||
|
// │ ┌── 6
|
||||||
|
// └── 1
|
||||||
|
it := tree.Iterator()
|
||||||
|
count := tree.Size()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
for it.Prev() {
|
||||||
|
value := it.Value()
|
||||||
|
switch value {
|
||||||
|
case count:
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIteratorBegin(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
|
||||||
|
if it.node != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.node, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Begin()
|
||||||
|
|
||||||
|
if it.node != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.node, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Begin()
|
||||||
|
|
||||||
|
if it.node != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.node, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Next()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIteratorEnd(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
it := tree.Iterator()
|
||||||
|
|
||||||
|
if it.node != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.node, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.End()
|
||||||
|
if it.node != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.node, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it.End()
|
||||||
|
if it.node != nil {
|
||||||
|
t.Errorf("Got %v expected %v", it.node, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Prev()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIteratorFirst(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 1 || value != "a" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 1, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeIteratorLast(t *testing.T) {
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
tree.Put(3, "c")
|
||||||
|
tree.Put(1, "a")
|
||||||
|
tree.Put(2, "b")
|
||||||
|
it := tree.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedBlackTreeSerialization(t *testing.T) {
|
||||||
|
tree := NewWithStringComparator()
|
||||||
|
tree.Put("c", "3")
|
||||||
|
tree.Put("b", "2")
|
||||||
|
tree.Put("a", "1")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
assert := func() {
|
||||||
|
if actualValue, expectedValue := tree.Size(), 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := tree.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[a,b,c]")
|
||||||
|
}
|
||||||
|
if actualValue := tree.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert()
|
||||||
|
|
||||||
|
json, err := tree.ToJSON()
|
||||||
|
assert()
|
||||||
|
|
||||||
|
err = tree.FromJSON(json)
|
||||||
|
assert()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, tree *Tree, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPut(b *testing.B, tree *Tree, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, tree *Tree, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreeGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreeGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreeGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreeGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreePut100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreePut1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreePut10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreePut100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreeRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreeRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreeRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, tree, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRedBlackTreeRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
tree := NewWithIntComparator()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
tree.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, tree, size)
|
||||||
|
}
|
39
vendor/github.com/emirpasic/gods/trees/redblacktree/serialization.go
generated
vendored
Normal file
39
vendor/github.com/emirpasic/gods/trees/redblacktree/serialization.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package redblacktree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Tree)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Tree)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of list's elements.
|
||||||
|
func (tree *Tree) ToJSON() ([]byte, error) {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
it := tree.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
elements[utils.ToString(it.Key())] = it.Value()
|
||||||
|
}
|
||||||
|
return json.Marshal(&elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates list's elements from the input JSON representation.
|
||||||
|
func (tree *Tree) FromJSON(data []byte) error {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err == nil {
|
||||||
|
tree.Clear()
|
||||||
|
for key, value := range elements {
|
||||||
|
tree.Put(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue