Skip to content

Commit

Permalink
Set interface improvements (#10)
Browse files Browse the repository at this point in the history
* add set constructor that takes an iterable as arg

* add Base.in for AVLSet

* add Base.* set ops

* add union

* add setdiff, intersect

* update CI

* update CI
  • Loading branch information
krynju authored Jul 24, 2021
1 parent f01703c commit 241f652
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ os:
- osx
julia:
- nightly
- 1.6
- 1.3
- 1.2
- 1.1
codecov: true
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name = "AVLTrees"
uuid = "4459d02e-7d0b-4014-b2a2-e38a540ff820"
authors = ["krynju <[email protected]>"]
version = "0.2.2"
version = "0.3.0"

[compat]
julia = "1"
julia = "1.1"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
41 changes: 39 additions & 2 deletions src/set.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import Base: union, union!, setdiff, setdiff!, intersect!, intersect

struct AVLSet{K} <: AbstractSet{K}
tree::AVLTree{K,Nothing}
end

AVLSet() = AVLSet{Any}(AVLTree{Any,Nothing}())
AVLSet{K}() where {K} = AVLSet{K}(AVLTree{K,Nothing}())

function AVLSet(x::K) where {K <: AbstractVector}
t = AVLTree{eltype(x),Nothing}()
for i in x
insert!(t, i, nothing)
end
return AVLSet{eltype(x)}(t)
end

Base.eltype(::Type{AVLSet{K}}) where {K} = K
Base.length(set::AVLSet) = length(set.tree)

Base.in(x::K, set::AVLSet{K}) where {K} = !isnothing(find_node(set.tree, x))

function iterate(set::AVLSet{K}) where {K}
ret = iterate(set.tree)
Expand All @@ -21,4 +31,31 @@ end

Base.push!(set::AVLSet{K}, item::K) where {K} = insert!(set.tree, item, nothing)

function delete!(set::AVLSet{K}, item) where {K} delete!(set.tree, item) end
Base.delete!(set::AVLSet{K}, item) where {K} = delete!(set.tree, item)

Base.union(set::AVLSet{K}, sets...) where {K} = union!(deepcopy(set), sets...)

function Base.union!(set::AVLSet{K}, sets...) where {K}
(key -> push!.(Ref(set), key)).(sets)
return set
end


Base.setdiff(set::AVLSet{K}, sets...) where {K} = setdiff!(deepcopy(set), sets...)

function Base.setdiff!(set::AVLSet{K}, sets...) where {K}
(key -> delete!.(Ref(set), key)).(sets)
return set
end

Base.intersect(set::AVLSet{K}, s::AbstractSet) where {K} = intersect!(deepcopy(set), s)

function Base.intersect!(set::AVLSet{K}, s::AbstractSet) where {K}
_set = collect(set)
for key in _set
if key s
delete!(set, key)
end
end
return set
end
12 changes: 12 additions & 0 deletions test/node.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@testset "node" begin
@testset "constructors" begin
n = AVLTrees.Node(10, 10)
@test n.key == 10
@test n.data == 10
@test isnothing(n.parent)

n1 = AVLTrees.Node(12, 12, n)
@test n1.parent == n
@test isnothing(n1.parent.parent)
end
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ using AVLTrees
using Test

@testset "AVLTrees.jl" begin
include("node.jl")
include("tree.jl")
include("set.jl")
end
60 changes: 58 additions & 2 deletions test/set.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@testset "set.jl" begin
let
@testset "basic" begin
s = AVLSet()
items = ["anything", "anything2"]
push!(s, items[1])
Expand All @@ -16,4 +16,60 @@
@test isempty(s)
end

end
@testset "constructor with AbstractVector input" begin
items = rand(1_000)
s = AVLSet(items)
@test eltype(items) == eltype(s)
@test all(items .∈ Ref(s))
@test all(items .∈ Ref(collect(s)))
end

@testset "union" begin
a = rand(1:1000, 800)
b = rand(1:1000, 800)

avl_a = AVLSet(a)
avl_b = AVLSet(b)

sa = Set(a)
sb = Set(b)

@test union(avl_a, avl_b) == union(sa, sb)
@test union(avl_a, avl_a) == union(sa, sa)
@test union(avl_a, avl_b, avl_b) == union(sa, sb)
@test union(avl_a, sb, avl_b, avl_a, sb) == union(sa, sb)
@test union!(avl_a, avl_b) == union(sa, sb)
@test union!(avl_b, avl_a) == union(sa, sb)
end

@testset "setdiff" begin
a = rand(1:1000, 800)
b = rand(1:1000, 800)

avl_a = AVLSet(a)
avl_b = AVLSet(b)

sa = Set(a)
sb = Set(b)

@test setdiff(avl_a, avl_b, avl_b) == setdiff(sa, sb)
@test setdiff(avl_a, avl_a) == setdiff(sa, sa)
@test setdiff(avl_a, sb) == setdiff(sa, sb)
end

@testset "intersect" begin
a = rand(1:1000, 800)
b = rand(1:1000, 800)

avl_a = AVLSet(a)
avl_b = AVLSet(b)

sa = Set(a)
sb = Set(b)


@test intersect(avl_a, avl_b) == intersect(sa, sb)
@test intersect(avl_a, avl_a) == intersect(sa, sa)

end
end

2 comments on commit 241f652

@krynju
Copy link
Owner Author

@krynju krynju commented on 241f652 Jul 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/41463

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.0 -m "<description of version>" 241f6529055cb98444c1878d39d3eca48f826312
git push origin v0.3.0

Please sign in to comment.