data_structures_101 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +10 -2
- data/_config.yml +1 -0
- data/lib/data_structures_101.rb +4 -0
- data/lib/data_structures_101/chained_hash_table.rb +40 -0
- data/lib/data_structures_101/hash/base_hash_table.rb +62 -0
- data/lib/data_structures_101/hash/bucket.rb +52 -0
- data/lib/data_structures_101/linked_list.rb +9 -25
- data/lib/data_structures_101/probe_hash_table.rb +79 -0
- data/lib/data_structures_101/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f215d1362121ff577224993028a8870cd3fd1b82
|
4
|
+
data.tar.gz: 9785b4159ec72926f1fb81c5baeda8281d2840cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 005a8f910dad00e6db443761b725eac89b384e1f6f79a0deb94d526c511d791b1b110d111159c80d202d142f3b0d2cb11aac984e925e468e25158fd3416f89e3
|
7
|
+
data.tar.gz: f477fe15da1f404dc753690b7d0ae27861f9785d81bcf6725ce2d8f862a8ad491075871e2883ac122d0a6f29edbe35ce35477975c1657afe39995b4df952b5b2
|
data/.travis.yml
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
|
5
|
-
before_install: gem install bundler -v 1.14.6
|
4
|
+
- 2.4.0
|
6
5
|
script: bundle exec rspec
|
6
|
+
deploy:
|
7
|
+
provider: rubygems
|
8
|
+
api_key:
|
9
|
+
secure: YDkCNjnzyBTEcZLjKqt6ep1rIHYGF6tbqwNVUXEOFiBpQA534xl8AcsNIcb4MZGcNzn9ZeJiHstIeHKKP135sLKnA00RptoVtNAHn9F5hBgDyPc5GyIEzml4wDv7NM+jcM4df39CEBIyYi+77vRUvUfrOJ+0RF7CxvlGX4ZUvbI+5edFXjt9ioVPOhG+V6FyTbGlNEG2Rj4lx6jjUF3HYVVhwHCva3F4uXNh/3CjZXvcJ6ZahKCiO0/pqxZsS6L/xfDaih/jg/8B3nQ2L7Lx+g5A8uNLCZ4u2G4SPoCg0a+mrttJAkIgTNC8reVBAbS9V7BV6/OJcJwwhJKNQ+UsleTv0oDdOWsSFgL8I2qtUJb7r1cpmFHi/LC5fnfpfC6xcoRk7sxrFboYsbm8yGt2KEk68Jregl9j0EqrHynog/9zFKx9Sfcrw2Fo+6oMACDYm3NzlcAo+6bQHni/kV94oaD58nZ3OQgvBMh4jeZ854jjCbpJaCMs2u2CgezjlTZCY7+E38t+/tiFlAOakVBSC9oGEYCFxh5X/clKXi7Q2PZj8j/pmcc51wmVFEMB5Led7kj1R1YWCnalhIZO4hpz83yBGCYZQgm2AZy0r8k741L9ab0H/KhMSJHGN2ym2Dgdpg1a0QdlMGVidIQGNjeSEx7TPkkDStuM588qKcR8C6M=
|
10
|
+
gem: data_structures_101
|
11
|
+
on:
|
12
|
+
tags: true
|
13
|
+
repo: renehernandez/data_structures_101
|
14
|
+
branch: master
|
data/_config.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
theme: jekyll-theme-slate
|
data/lib/data_structures_101.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
require "data_structures_101/version"
|
2
2
|
require "data_structures_101/linked_list"
|
3
|
+
require "data_structures_101/hash/base_hash_table"
|
4
|
+
require "data_structures_101/hash/bucket"
|
5
|
+
require "data_structures_101/chained_hash_table"
|
6
|
+
require "data_structures_101/probe_hash_table"
|
3
7
|
|
4
8
|
module DataStructures101
|
5
9
|
# Your code goes here...
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module DataStructures101
|
2
|
+
|
3
|
+
class ChainedHashTable < Hash::BaseHashTable
|
4
|
+
|
5
|
+
def initialize(capacity = 31, prime = 109345121, hash_lambda = nil)
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def bucket_find(hash_code, key)
|
12
|
+
bucket = @table[hash_code]
|
13
|
+
return nil if bucket.nil?
|
14
|
+
|
15
|
+
bucket.find(key)
|
16
|
+
end
|
17
|
+
|
18
|
+
def bucket_insert(hash_code, key, value)
|
19
|
+
bucket = @table[hash_code]
|
20
|
+
bucket = @table[hash_code] = Hash::Bucket.new if bucket.nil?
|
21
|
+
|
22
|
+
old_size = bucket.size()
|
23
|
+
old_value = bucket.insert(key, value)
|
24
|
+
@size += (bucket.size - old_size)
|
25
|
+
|
26
|
+
old_value
|
27
|
+
end
|
28
|
+
|
29
|
+
def bucket_delete(hash_code, key)
|
30
|
+
bucket = @table[hash_code]
|
31
|
+
return nil if bucket.nil?
|
32
|
+
|
33
|
+
old_size = bucket.size
|
34
|
+
value = bucket.delete(key)
|
35
|
+
@size -= (old_size - bucket.size)
|
36
|
+
|
37
|
+
value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module DataStructures101
|
2
|
+
module Hash
|
3
|
+
class BaseHashTable
|
4
|
+
|
5
|
+
attr_reader :size, :hash_lambda
|
6
|
+
|
7
|
+
def initialize(capacity, prime, hash_lambda = nil)
|
8
|
+
@capacity = capacity
|
9
|
+
@size = 0
|
10
|
+
@table = Array.new(@capacity)
|
11
|
+
|
12
|
+
random = Random.new
|
13
|
+
scale = random.rand(prime - 1) + 1
|
14
|
+
shift = random.rand(prime)
|
15
|
+
|
16
|
+
@hash_lambda = if hash_lambda.nil?
|
17
|
+
->(key) { return (((key.hash * scale + shift) % prime) % @capacity).abs }
|
18
|
+
else
|
19
|
+
hash_lambda
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def []=(key, value)
|
24
|
+
insert(key, value)
|
25
|
+
end
|
26
|
+
|
27
|
+
def insert(key, value)
|
28
|
+
old_value = bucket_insert(hash_lambda.call(key), key, value)
|
29
|
+
|
30
|
+
# keep load factor <= 0.5
|
31
|
+
resize(new_capacity) if @size > @capacity / 2
|
32
|
+
|
33
|
+
old_value
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](key)
|
37
|
+
bucket_find(hash_lambda.call(key), key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete(key)
|
41
|
+
bucket_delete(hash_lambda.call(key), key)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def new_capacity()
|
47
|
+
2 * capacity - 1
|
48
|
+
end
|
49
|
+
|
50
|
+
def resize(new_capacity)
|
51
|
+
@capacity = new_capacity
|
52
|
+
|
53
|
+
buffer = self.map { |key, value| [key, value] }
|
54
|
+
|
55
|
+
create_table
|
56
|
+
@size = 0
|
57
|
+
|
58
|
+
buffer.each { |key, value| self[key] = value }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module DataStructures101
|
2
|
+
module Hash
|
3
|
+
class Bucket
|
4
|
+
|
5
|
+
attr_reader :table
|
6
|
+
|
7
|
+
def initialize()
|
8
|
+
@table = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
find(key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(key, value)
|
16
|
+
insert(key, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def insert(key, value)
|
20
|
+
idx = @table.find_index {|_key, _| _key == key}
|
21
|
+
|
22
|
+
if idx.nil?
|
23
|
+
@table << [key, value]
|
24
|
+
return nil
|
25
|
+
else
|
26
|
+
value, @table[idx][1] = @table[idx][1], value
|
27
|
+
return value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def size()
|
32
|
+
@table.size
|
33
|
+
end
|
34
|
+
|
35
|
+
def find(key)
|
36
|
+
pair = @table.find {|_key, _| _key == key}
|
37
|
+
pair.nil? ? nil : pair.last
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete(key)
|
41
|
+
idx = @table.find_index {|_key, _| _key == key}
|
42
|
+
return nil if idx.nil?
|
43
|
+
|
44
|
+
value = @table[idx].last
|
45
|
+
@table[idx] = @table.last if idx != @table.size - 1
|
46
|
+
@table.pop
|
47
|
+
value
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -69,36 +69,20 @@ module DataStructures101
|
|
69
69
|
self
|
70
70
|
end
|
71
71
|
|
72
|
-
def first(
|
73
|
-
|
74
|
-
return @head.next.value
|
75
|
-
end
|
72
|
+
def first(n = nil)
|
73
|
+
return @head.next.value if n.nil?
|
76
74
|
|
77
|
-
|
78
|
-
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1)"
|
79
|
-
end
|
75
|
+
raise ArgumentError, "negative array size" if n < 0
|
80
76
|
|
81
|
-
|
82
|
-
raise ArgumentError, "negative array size"
|
83
|
-
end
|
84
|
-
|
85
|
-
return new_list_from_range(0, args.first - 1)
|
77
|
+
return new_list_from_range(0, n - 1)
|
86
78
|
end
|
87
79
|
|
88
|
-
def last(
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
if args.size > 1
|
94
|
-
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1)"
|
95
|
-
end
|
96
|
-
|
97
|
-
if args.first < 0
|
98
|
-
raise ArgumentError, "negative array size"
|
99
|
-
end
|
80
|
+
def last(n = nil)
|
81
|
+
return @tail.prev.value if n.nil?
|
82
|
+
|
83
|
+
raise ArgumentError, "negative array size" if n < 0
|
100
84
|
|
101
|
-
return new_list_from_range(size -
|
85
|
+
return new_list_from_range(size - n, size - 1)
|
102
86
|
end
|
103
87
|
|
104
88
|
def push(*values)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module DataStructures101
|
4
|
+
class ProbeHashTable < Hash::BaseHashTable
|
5
|
+
|
6
|
+
attr_reader :probe_lambda
|
7
|
+
|
8
|
+
def initialize(capacity = 31, prime = 109345121,
|
9
|
+
hash_lambda = nil, probe_lambda = nil)
|
10
|
+
super(capacity, prime, hash_lambda)
|
11
|
+
|
12
|
+
@probe_lambda = if probe_lambda.nil?
|
13
|
+
->(h, i) { return (h + i) % @capacity }
|
14
|
+
else
|
15
|
+
probe_lambda
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
Sentinel = Class.new do
|
22
|
+
include Singleton
|
23
|
+
end
|
24
|
+
|
25
|
+
def bucket_find(hash_code, key)
|
26
|
+
idx = find_slot(hash_code, key)
|
27
|
+
|
28
|
+
slot_available?(idx) ? nil : @table[idx].last
|
29
|
+
end
|
30
|
+
|
31
|
+
def bucket_insert(hash_code, key, value)
|
32
|
+
idx = find_slot(hash_code, key)
|
33
|
+
|
34
|
+
if !slot_available?(idx)
|
35
|
+
old_value = @table[idx].last
|
36
|
+
@table[idx] = [key, value]
|
37
|
+
return old_value
|
38
|
+
end
|
39
|
+
|
40
|
+
@table[idx] = [key, value]
|
41
|
+
@size += 1
|
42
|
+
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def bucket_delete(hash_code, key)
|
47
|
+
idx = find_slot(hash_code, key)
|
48
|
+
return nil if slot_available?(idx)
|
49
|
+
|
50
|
+
value = @table[idx].last
|
51
|
+
@table[idx] = Sentinel.instance
|
52
|
+
@size -= 1
|
53
|
+
|
54
|
+
value
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_slot(h, key)
|
58
|
+
idx = -1
|
59
|
+
|
60
|
+
j = 0
|
61
|
+
loop do
|
62
|
+
i = @probe_lambda.call(h, j)
|
63
|
+
if slot_available?(i)
|
64
|
+
idx = i if idx == -1
|
65
|
+
break if @table[i].nil?
|
66
|
+
elsif @table[i].first == key
|
67
|
+
return i
|
68
|
+
end
|
69
|
+
j += 1
|
70
|
+
end
|
71
|
+
|
72
|
+
idx
|
73
|
+
end
|
74
|
+
|
75
|
+
def slot_available?(i)
|
76
|
+
@table[i].nil? || @table[i] == Sentinel.instance
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: data_structures_101
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aegis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,11 +66,16 @@ files:
|
|
66
66
|
- LICENSE.txt
|
67
67
|
- README.md
|
68
68
|
- Rakefile
|
69
|
+
- _config.yml
|
69
70
|
- bin/console
|
70
71
|
- bin/setup
|
71
72
|
- data_structures_101.gemspec
|
72
73
|
- lib/data_structures_101.rb
|
74
|
+
- lib/data_structures_101/chained_hash_table.rb
|
75
|
+
- lib/data_structures_101/hash/base_hash_table.rb
|
76
|
+
- lib/data_structures_101/hash/bucket.rb
|
73
77
|
- lib/data_structures_101/linked_list.rb
|
78
|
+
- lib/data_structures_101/probe_hash_table.rb
|
74
79
|
- lib/data_structures_101/version.rb
|
75
80
|
homepage: https://github.com/renehernandez/bok-data_structures_101
|
76
81
|
licenses:
|
@@ -92,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
97
|
version: '0'
|
93
98
|
requirements: []
|
94
99
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.6.
|
100
|
+
rubygems_version: 2.6.11
|
96
101
|
signing_key:
|
97
102
|
specification_version: 4
|
98
103
|
summary: DataStructures101 is a simple gem that groups several implementations of
|