mirror of
https://github.com/Luzifer/ansible-role-version.git
synced 2024-12-22 18:41:22 +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'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/emirpasic/gods"
|
||||
packages = [
|
||||
"containers",
|
||||
"lists",
|
||||
"lists/arraylist",
|
||||
"trees",
|
||||
"trees/binaryheap",
|
||||
"utils"
|
||||
]
|
||||
revision = "f6c17b524822278a87e3b3bd809fec33b51f5b46"
|
||||
version = "v1.9.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/inconshreveable/mousetrap"
|
||||
packages = ["."]
|
||||
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||
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]]
|
||||
name = "github.com/spf13/cobra"
|
||||
packages = ["."]
|
||||
|
@ -20,14 +63,144 @@
|
|||
version = "v1.0.0"
|
||||
|
||||
[[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"
|
||||
packages = ["."]
|
||||
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
|
||||
revision = "7f97868eec74b32b0982dd158a51a446d1da7eb5"
|
||||
version = "v2.1.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "7ff1f45772d06d809a7ce689131011edc8fbd443f3b3d5b819110f42ad9d5283"
|
||||
inputs-digest = "232dd462ee87625b6d06a386c00dff327b7e8f1033800dd1383ea2d9e2c94dd4"
|
||||
solver-name = "gps-cdcl"
|
||||
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