data_structures_101 0.2.5 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +9 -0
- data/.rubocop.yml +17 -0
- data/.travis.yml +20 -9
- data/.yardopts +2 -0
- data/README.md +13 -3
- data/_config.yml +2 -1
- data/config.reek +6 -0
- data/data_structures_101.gemspec +6 -1
- data/lib/data_structures_101/chained_hash_table.rb +41 -36
- data/lib/data_structures_101/hash/base_hash_table.rb +80 -68
- data/lib/data_structures_101/hash/bucket.rb +61 -56
- data/lib/data_structures_101/linked_list.rb +28 -20
- data/lib/data_structures_101/probe_hash_table.rb +73 -66
- data/lib/data_structures_101/version.rb +3 -1
- data/lib/data_structures_101.rb +10 -6
- metadata +77 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e15be8b700463083c82dda684ae895dde3d8baa7
|
4
|
+
data.tar.gz: 2d63d489be4c9eafac10a425f7f4b52e68a90d6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11947ea941d77805167838c153543e3db5215817e4d614e78e7d27d9021917cf0cdd21ef312dd8e2f53ca6acecbcc88c2a20eac7430f3e0234e86219f5392b66
|
7
|
+
data.tar.gz: c4f82b40b433e5156bd8a20492a2833d9d1cf104c0c49b71e97aa67e33098cd3725d559bc34c202b2250d915d74c19e3b9010a8d2e4784231a5252607e8cc382
|
data/.editorconfig
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.4
|
3
|
+
Metrics/MethodLength:
|
4
|
+
Max: 25
|
5
|
+
CountComments: false
|
6
|
+
Metrics/AbcSize:
|
7
|
+
Max: 20
|
8
|
+
Metrics/CyclomaticComplexity:
|
9
|
+
Max: 10
|
10
|
+
Metrics/BlockLength:
|
11
|
+
Exclude:
|
12
|
+
- spec/**/*
|
13
|
+
Metrics/LineLength:
|
14
|
+
Exclude:
|
15
|
+
- spec/**/*
|
16
|
+
Style/FrozenStringLiteralComment:
|
17
|
+
EnforcedStyle: always
|
data/.travis.yml
CHANGED
@@ -2,13 +2,24 @@ sudo: false
|
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
4
|
- 2.4.0
|
5
|
-
script:
|
5
|
+
script:
|
6
|
+
- bundle exec rspec
|
7
|
+
- bundle exec rubocop lib
|
8
|
+
- bundle exec rubocop spec
|
9
|
+
before_deploy: bundle exec yard doc
|
6
10
|
deploy:
|
7
|
-
provider:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
- provider: pages
|
12
|
+
skip_cleanup: true
|
13
|
+
github_token: $GITHUB_TOKEN
|
14
|
+
local_dir: doc
|
15
|
+
target_branch: gh-pages
|
16
|
+
on:
|
17
|
+
branch: master
|
18
|
+
- provider: rubygems
|
19
|
+
api_key:
|
20
|
+
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=
|
21
|
+
gem: data_structures_101
|
22
|
+
on:
|
23
|
+
tags: true
|
24
|
+
repo: renehernandez/data_structures_101
|
25
|
+
branch: master
|
data/.yardopts
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# DataStructures101 [![Build Status](https://travis-ci.org/renehernandez/data_structures_101.svg
|
1
|
+
# DataStructures101 [![Build Status](https://travis-ci.org/renehernandez/data_structures_101.svg)](https://travis-ci.org/renehernandez/data_structures_101) [![Gem Version](https://badge.fury.io/rb/data_structures_101.svg)](https://badge.fury.io/rb/data_structures_101)
|
2
2
|
|
3
3
|
DataStructures101 is a simple gem that groups several implementations of common data structures usually taught in Computer Science courses. The overall goal of the gem is to provide easy to use functionality (trying to match the behavior of existent structures in Ruby) while providing the user with a framework to test and compare their implementations against.
|
4
4
|
|
@@ -24,7 +24,7 @@ Or install it yourself as:
|
|
24
24
|
require 'data_structures_101'
|
25
25
|
```
|
26
26
|
|
27
|
-
### LinkedList
|
27
|
+
### LinkedList example
|
28
28
|
|
29
29
|
To create a LinkedList
|
30
30
|
|
@@ -32,7 +32,17 @@ To create a LinkedList
|
|
32
32
|
list = DataStructures101::LinkedList.new
|
33
33
|
```
|
34
34
|
|
35
|
-
|
35
|
+
### HashTable example
|
36
|
+
|
37
|
+
To create a hash table using *separate chaining* strategy:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
hash = DataStructures101::ChainedHashTable.new
|
41
|
+
```
|
42
|
+
|
43
|
+
### Documentation
|
44
|
+
|
45
|
+
The website documentation lives at the [github pages](https://renehernandez.github.io/data_structures_101/). You can also chec several posts on [https://bitsofknowledge.net](https://bitsofknowledge.net) where I have discusses some implementations.
|
36
46
|
|
37
47
|
## Contributing
|
38
48
|
|
data/_config.yml
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
theme: jekyll-theme-slate
|
1
|
+
theme: jekyll-theme-slate
|
2
|
+
title: Welcome to DataStructures101
|
data/config.reek
ADDED
data/data_structures_101.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'data_structures_101/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "data_structures_101"
|
8
8
|
spec.version = DataStructures101::VERSION
|
9
|
-
spec.authors = ["
|
9
|
+
spec.authors = ["renehernandez"]
|
10
10
|
spec.email = ["renehr9102@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{DataStructures101 is a simple gem that groups several implementations of common data structures usually taught in Computer Science courses.}
|
@@ -23,4 +23,9 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.14"
|
24
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
25
|
spec.add_development_dependency "rspec", "~> 3.5"
|
26
|
+
spec.add_development_dependency "reek", "~> 4.7"
|
27
|
+
spec.add_development_dependency "rubocop", "~> 0.49"
|
28
|
+
spec.add_development_dependency "yard"
|
29
|
+
spec.add_development_dependency "redcarpet"
|
30
|
+
spec.add_development_dependency "github-markup"
|
26
31
|
end
|
@@ -1,50 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DataStructures101
|
4
|
+
# HashTable implementation using separate chaining strategy
|
5
|
+
# for collision-resolution
|
6
|
+
# It subclasses Hash::BaseHashTable
|
7
|
+
# @author Rene Hernandez
|
8
|
+
# @since 0.2
|
9
|
+
class ChainedHashTable < Hash::BaseHashTable
|
10
|
+
def initialize(capacity: 31, prime: 109_345_121, compression_lambda: nil)
|
11
|
+
super
|
12
|
+
end
|
2
13
|
|
3
|
-
|
14
|
+
private
|
4
15
|
|
5
|
-
|
6
|
-
|
7
|
-
|
16
|
+
def bucket_find(hash_code, key)
|
17
|
+
bucket = @table[hash_code]
|
18
|
+
return nil if bucket.nil?
|
8
19
|
|
9
|
-
|
20
|
+
bucket.find(key)
|
21
|
+
end
|
10
22
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
bucket.find(key)
|
16
|
-
end
|
23
|
+
def bucket_insert(hash_code, key, value)
|
24
|
+
bucket = @table[hash_code]
|
25
|
+
bucket = @table[hash_code] = Hash::Bucket.new if bucket.nil?
|
17
26
|
|
18
|
-
|
19
|
-
|
20
|
-
|
27
|
+
old_size = bucket.size
|
28
|
+
old_value = bucket.insert(key, value)
|
29
|
+
@size += (bucket.size - old_size)
|
21
30
|
|
22
|
-
|
23
|
-
|
24
|
-
@size += (bucket.size - old_size)
|
31
|
+
old_value
|
32
|
+
end
|
25
33
|
|
26
|
-
|
27
|
-
|
34
|
+
def bucket_delete(hash_code, key)
|
35
|
+
bucket = @table[hash_code]
|
36
|
+
return nil if bucket.nil?
|
28
37
|
|
29
|
-
|
30
|
-
|
31
|
-
|
38
|
+
old_size = bucket.size
|
39
|
+
value = bucket.delete(key)
|
40
|
+
@size -= (old_size - bucket.size)
|
32
41
|
|
33
|
-
|
34
|
-
|
35
|
-
@size -= (old_size - bucket.size)
|
42
|
+
value
|
43
|
+
end
|
36
44
|
|
37
|
-
|
38
|
-
|
45
|
+
def bucket_each
|
46
|
+
@table.each do |bucket|
|
47
|
+
next if bucket.nil?
|
39
48
|
|
40
|
-
|
41
|
-
|
42
|
-
next if bucket.nil?
|
43
|
-
|
44
|
-
bucket.each do |key, value|
|
45
|
-
yield(key, value)
|
46
|
-
end
|
47
|
-
end
|
49
|
+
bucket.each do |key, value|
|
50
|
+
yield(key, value)
|
48
51
|
end
|
52
|
+
end
|
49
53
|
end
|
50
|
-
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,70 +1,82 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
resize(new_capacity) if @size > @capacity / 2
|
32
|
-
|
33
|
-
old_value
|
34
|
-
end
|
35
|
-
|
36
|
-
def [](key)
|
37
|
-
bucket_find(compression_lambda.call(key, @capacity), key)
|
38
|
-
end
|
39
|
-
|
40
|
-
def delete(key)
|
41
|
-
bucket_delete(compression_lambda.call(key, @capacity), key)
|
42
|
-
end
|
43
|
-
|
44
|
-
def each
|
45
|
-
return enum_for(:each) unless block_given?
|
46
|
-
|
47
|
-
bucket_each do |key, value|
|
48
|
-
yield(key, value)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def new_capacity
|
55
|
-
2 * @capacity - 1
|
56
|
-
end
|
57
|
-
|
58
|
-
def resize(new_cap)
|
59
|
-
@capacity = new_cap
|
60
|
-
|
61
|
-
buffer = self.map { |key, value| [key, value] }
|
62
|
-
|
63
|
-
@table = Array.new(@capacity)
|
64
|
-
@size = 0
|
65
|
-
|
66
|
-
buffer.each { |key, value| self[key] = value }
|
67
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DataStructures101
|
4
|
+
# @author Rene Hernandez
|
5
|
+
# @since 0.2
|
6
|
+
module Hash
|
7
|
+
# Abstract class for shared HashTable functionalities.
|
8
|
+
# @see ChainedHashTable
|
9
|
+
# @see ProbeHashTable
|
10
|
+
# @author Rene Hernandez
|
11
|
+
# @since 0.2
|
12
|
+
class BaseHashTable
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
attr_reader :size, :compression_lambda, :capacity
|
16
|
+
|
17
|
+
def initialize(capacity:, prime:, compression_lambda:)
|
18
|
+
@capacity = capacity
|
19
|
+
@size = 0
|
20
|
+
@table = Array.new(@capacity)
|
21
|
+
|
22
|
+
@compression_lambda = compression_lambda
|
23
|
+
|
24
|
+
return unless @compression_lambda.nil?
|
25
|
+
|
26
|
+
random = Random.new
|
27
|
+
scale = random.rand(prime - 1) + 1
|
28
|
+
shift = random.rand(prime)
|
29
|
+
@compression_lambda = lambda do |key, cap|
|
30
|
+
return (((key.hash * scale + shift) % prime) % cap).abs
|
68
31
|
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def []=(key, value)
|
35
|
+
insert(key, value)
|
36
|
+
end
|
37
|
+
|
38
|
+
def insert(key, value)
|
39
|
+
hash_code = compression_lambda.call(key, @capacity)
|
40
|
+
old_value = bucket_insert(hash_code, key, value)
|
41
|
+
|
42
|
+
# Keep load factor below 0.5.
|
43
|
+
resize(new_capacity) if @size > @capacity / 2
|
44
|
+
|
45
|
+
old_value
|
46
|
+
end
|
47
|
+
|
48
|
+
def [](key)
|
49
|
+
bucket_find(compression_lambda.call(key, @capacity), key)
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete(key)
|
53
|
+
bucket_delete(compression_lambda.call(key, @capacity), key)
|
54
|
+
end
|
55
|
+
|
56
|
+
def each
|
57
|
+
return enum_for(:each) unless block_given?
|
58
|
+
|
59
|
+
bucket_each do |key, value|
|
60
|
+
yield(key, value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def new_capacity
|
67
|
+
2 * @capacity - 1
|
68
|
+
end
|
69
|
+
|
70
|
+
def resize(new_cap)
|
71
|
+
@capacity = new_cap
|
72
|
+
|
73
|
+
buffer = map { |key, value| [key, value] }
|
74
|
+
|
75
|
+
@table = Array.new(@capacity)
|
76
|
+
@size = 0
|
77
|
+
|
78
|
+
buffer.each { |key, value| self[key] = value }
|
79
|
+
end
|
69
80
|
end
|
70
|
-
end
|
81
|
+
end
|
82
|
+
end
|
@@ -1,59 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DataStructures101
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
4
|
+
module Hash
|
5
|
+
# Utility class to manipulate (key, pairs) that have same hash code.
|
6
|
+
# @see ChainedHashTable
|
7
|
+
# @author Rene Hernandez
|
8
|
+
# @since 0.2
|
9
|
+
class Bucket
|
10
|
+
attr_reader :table
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@table = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](key)
|
17
|
+
find(key)
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(key, value)
|
21
|
+
insert(key, value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def insert(key, value)
|
25
|
+
idx = @table.find_index { |table_key, _| table_key == key }
|
26
|
+
|
27
|
+
if idx.nil?
|
28
|
+
@table << [key, value]
|
29
|
+
return nil
|
30
|
+
else
|
31
|
+
value, @table[idx][1] = @table[idx][1], value
|
32
|
+
return value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def size
|
37
|
+
@table.size
|
38
|
+
end
|
39
|
+
|
40
|
+
def find(key)
|
41
|
+
pair = @table.find { |table_key, _| table_key == key }
|
42
|
+
pair.nil? ? nil : pair.last
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete(key)
|
46
|
+
idx = @table.find_index { |table_key, _| table_key == key }
|
47
|
+
return nil if idx.nil?
|
48
|
+
|
49
|
+
value = @table[idx].last
|
50
|
+
@table[idx] = @table.last if idx != @table.size - 1
|
51
|
+
@table.pop
|
52
|
+
value
|
53
|
+
end
|
54
|
+
|
55
|
+
def each
|
56
|
+
return enum_for(:each) unless block_given?
|
57
|
+
|
58
|
+
@table.each do |key, value|
|
59
|
+
yield(key, value)
|
57
60
|
end
|
61
|
+
end
|
58
62
|
end
|
59
|
-
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,15 +1,23 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module DataStructures101
|
4
|
+
# @author Rene Hernandez
|
5
|
+
# @since 0.1
|
3
6
|
class LinkedList
|
4
7
|
include Enumerable
|
5
8
|
|
9
|
+
# Internal class to store a given value in the LinkedList.
|
10
|
+
# Provides reference to next and previous node in the list
|
11
|
+
# @see LinkedList
|
12
|
+
# @author Rene Hernandez
|
13
|
+
# @since 0.1
|
6
14
|
class Node
|
7
15
|
attr_accessor :value, :prev, :next
|
8
16
|
|
9
|
-
def initialize(value,
|
17
|
+
def initialize(value, previous_node = nil, next_node = nil)
|
10
18
|
@value = value
|
11
|
-
@
|
12
|
-
@
|
19
|
+
@prev = previous_node
|
20
|
+
@next = next_node
|
13
21
|
end
|
14
22
|
|
15
23
|
def to_s
|
@@ -46,10 +54,12 @@ module DataStructures101
|
|
46
54
|
return_value
|
47
55
|
end
|
48
56
|
|
49
|
-
def each
|
57
|
+
def each
|
58
|
+
return enum_for(:each) unless block_given?
|
59
|
+
|
50
60
|
curr = head.next
|
51
61
|
until curr.nil?
|
52
|
-
|
62
|
+
yield curr.value
|
53
63
|
curr = curr.next
|
54
64
|
end
|
55
65
|
end
|
@@ -61,7 +71,7 @@ module DataStructures101
|
|
61
71
|
def insert(index, *values)
|
62
72
|
curr = fetch_node(index)
|
63
73
|
|
64
|
-
curr = index
|
74
|
+
curr = index.negative? ? curr : curr.prev
|
65
75
|
|
66
76
|
values.each do |value|
|
67
77
|
curr = add_node(value, curr.next)
|
@@ -72,17 +82,17 @@ module DataStructures101
|
|
72
82
|
def first(n = nil)
|
73
83
|
return @head.next.value if n.nil?
|
74
84
|
|
75
|
-
raise ArgumentError,
|
85
|
+
raise ArgumentError, 'negative array size' if n.negative?
|
76
86
|
|
77
|
-
|
87
|
+
new_list_from_range(0, n - 1)
|
78
88
|
end
|
79
89
|
|
80
90
|
def last(n = nil)
|
81
91
|
return @tail.prev.value if n.nil?
|
82
|
-
|
83
|
-
raise ArgumentError, "negative array size" if n < 0
|
84
92
|
|
85
|
-
|
93
|
+
raise ArgumentError, 'negative array size' if n.negative?
|
94
|
+
|
95
|
+
new_list_from_range(size - n, size - 1)
|
86
96
|
end
|
87
97
|
|
88
98
|
def push(*values)
|
@@ -95,10 +105,10 @@ module DataStructures101
|
|
95
105
|
private
|
96
106
|
|
97
107
|
def fetch_node(index)
|
98
|
-
index += size if index
|
99
|
-
|
100
|
-
|
101
|
-
|
108
|
+
index += size if index.negative?
|
109
|
+
|
110
|
+
error_msg = "index #{index} outside of array bounds: #{-size}...#{size}"
|
111
|
+
raise IndexError, error_msg if index.negative? || index >= size
|
102
112
|
|
103
113
|
pos = 0
|
104
114
|
curr = @head.next
|
@@ -127,9 +137,9 @@ module DataStructures101
|
|
127
137
|
def new_list_from_range(start_index, finish_index)
|
128
138
|
new_list = LinkedList.new
|
129
139
|
|
130
|
-
return new_list if size
|
140
|
+
return new_list if size.zero? || start_index == size || finish_index == -1
|
131
141
|
|
132
|
-
start_index = 0 if start_index
|
142
|
+
start_index = 0 if start_index.negative?
|
133
143
|
finish_index = size - 1 if finish_index >= size
|
134
144
|
|
135
145
|
start_node = fetch_node(start_index)
|
@@ -142,7 +152,5 @@ module DataStructures101
|
|
142
152
|
|
143
153
|
new_list
|
144
154
|
end
|
145
|
-
|
146
155
|
end
|
147
|
-
|
148
156
|
end
|
@@ -1,86 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'singleton'
|
2
4
|
|
3
5
|
module DataStructures101
|
4
|
-
|
6
|
+
# HashTable implementation using probing strategy for collision-resolution
|
7
|
+
# It subclasses Hash::BaseHashTable
|
8
|
+
# @author Rene Hernandez
|
9
|
+
# @since 0.2
|
10
|
+
class ProbeHashTable < Hash::BaseHashTable
|
11
|
+
attr_reader :probe_lambda
|
5
12
|
|
6
|
-
|
13
|
+
def initialize(capacity: 31, prime: 109_345_121,
|
14
|
+
compression_lambda: nil, probe_lambda: nil)
|
15
|
+
super(capacity: capacity, prime: prime,
|
16
|
+
compression_lambda: compression_lambda)
|
7
17
|
|
8
|
-
|
9
|
-
super(capacity: capacity, prime: prime, compression_lambda: compression_lambda)
|
18
|
+
@probe_lambda = probe_lambda
|
10
19
|
|
11
|
-
|
12
|
-
->(h, i) { return (h + i) % @capacity }
|
13
|
-
else
|
14
|
-
probe_lambda
|
15
|
-
end
|
16
|
-
end
|
20
|
+
return unless @probe_lambda.nil?
|
17
21
|
|
18
|
-
|
22
|
+
@probe_lambda = ->(h, i) { return (h + i) % @capacity }
|
23
|
+
end
|
19
24
|
|
20
|
-
|
21
|
-
include Singleton
|
22
|
-
end
|
25
|
+
private
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
slot_available?(idx) ? nil : @table[idx].last
|
28
|
-
end
|
27
|
+
Sentinel = Class.new do
|
28
|
+
include Singleton
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
def bucket_find(hash_code, key)
|
32
|
+
idx = find_slot(hash_code, key)
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
@table[idx] = [key, value]
|
36
|
-
return old_value
|
37
|
-
end
|
38
|
-
|
39
|
-
@table[idx] = [key, value]
|
40
|
-
@size += 1
|
34
|
+
slot_available?(idx) ? nil : @table[idx].last
|
35
|
+
end
|
41
36
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
def bucket_delete(hash_code, key)
|
46
|
-
idx = find_slot(hash_code, key)
|
47
|
-
return nil if slot_available?(idx)
|
37
|
+
def bucket_insert(hash_code, key, value)
|
38
|
+
idx = find_slot(hash_code, key)
|
48
39
|
|
49
|
-
|
50
|
-
|
51
|
-
|
40
|
+
unless slot_available?(idx)
|
41
|
+
old_value = @table[idx].last
|
42
|
+
@table[idx] = [key, value]
|
43
|
+
return old_value
|
44
|
+
end
|
52
45
|
|
53
|
-
|
54
|
-
|
46
|
+
@table[idx] = [key, value]
|
47
|
+
@size += 1
|
48
|
+
|
49
|
+
nil
|
50
|
+
end
|
55
51
|
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
def bucket_delete(hash_code, key)
|
53
|
+
idx = find_slot(hash_code, key)
|
54
|
+
return nil if slot_available?(idx)
|
59
55
|
|
60
|
-
|
61
|
-
|
62
|
-
|
56
|
+
value = @table[idx].last
|
57
|
+
@table[idx] = Sentinel.instance
|
58
|
+
@size -= 1
|
63
59
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
if slot_available?(i)
|
71
|
-
idx = i if idx == -1
|
72
|
-
break if @table[i].nil?
|
73
|
-
elsif @table[i].first == key
|
74
|
-
return i
|
75
|
-
end
|
76
|
-
j += 1
|
77
|
-
end
|
78
|
-
|
79
|
-
idx
|
80
|
-
end
|
60
|
+
value
|
61
|
+
end
|
62
|
+
|
63
|
+
def bucket_each
|
64
|
+
@table.each do |elem|
|
65
|
+
next if elem.nil? || elem == Sentinel.instance
|
81
66
|
|
82
|
-
|
83
|
-
|
67
|
+
yield(elem.first, elem.last)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_slot(h, key)
|
72
|
+
idx = -1
|
73
|
+
|
74
|
+
j = 0
|
75
|
+
loop do
|
76
|
+
i = @probe_lambda.call(h, j)
|
77
|
+
if slot_available?(i)
|
78
|
+
idx = i if idx == -1
|
79
|
+
break if @table[i].nil?
|
80
|
+
elsif @table[i].first == key
|
81
|
+
return i
|
84
82
|
end
|
83
|
+
j += 1
|
84
|
+
end
|
85
|
+
|
86
|
+
idx
|
87
|
+
end
|
88
|
+
|
89
|
+
def slot_available?(i)
|
90
|
+
@table[i].nil? || @table[i] == Sentinel.instance
|
85
91
|
end
|
86
|
-
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/data_structures_101.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
|
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"
|
1
|
+
# frozen_string_literal: true
|
7
2
|
|
3
|
+
require 'data_structures_101/version'
|
4
|
+
require 'data_structures_101/linked_list'
|
5
|
+
require 'data_structures_101/hash/base_hash_table'
|
6
|
+
require 'data_structures_101/hash/bucket'
|
7
|
+
require 'data_structures_101/chained_hash_table'
|
8
|
+
require 'data_structures_101/probe_hash_table'
|
9
|
+
|
10
|
+
# @author Rene Hernandez
|
11
|
+
# @since 0.1
|
8
12
|
module DataStructures101
|
9
13
|
# Your code goes here...
|
10
14
|
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.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- renehernandez
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,76 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: reek
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.7'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.7'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.49'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.49'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: redcarpet
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: github-markup
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
55
125
|
description:
|
56
126
|
email:
|
57
127
|
- renehr9102@gmail.com
|
@@ -59,9 +129,12 @@ executables: []
|
|
59
129
|
extensions: []
|
60
130
|
extra_rdoc_files: []
|
61
131
|
files:
|
132
|
+
- ".editorconfig"
|
62
133
|
- ".gitignore"
|
63
134
|
- ".rspec"
|
135
|
+
- ".rubocop.yml"
|
64
136
|
- ".travis.yml"
|
137
|
+
- ".yardopts"
|
65
138
|
- Gemfile
|
66
139
|
- LICENSE.txt
|
67
140
|
- README.md
|
@@ -69,6 +142,7 @@ files:
|
|
69
142
|
- _config.yml
|
70
143
|
- bin/console
|
71
144
|
- bin/setup
|
145
|
+
- config.reek
|
72
146
|
- data_structures_101.gemspec
|
73
147
|
- lib/data_structures_101.rb
|
74
148
|
- lib/data_structures_101/chained_hash_table.rb
|