kaninchen 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +21 -0
- data/README.md +212 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/kaninchen.gemspec +37 -0
- data/lib/kaninchen.rb +12 -0
- data/lib/kaninchen/algorithm.rb +6 -0
- data/lib/kaninchen/data_structure.rb +15 -0
- data/lib/kaninchen/data_structure/extension.rb +8 -0
- data/lib/kaninchen/data_structure/node.rb +48 -0
- data/lib/kaninchen/data_structure/queue.rb +8 -0
- data/lib/kaninchen/data_structure/set.rb +8 -0
- data/lib/kaninchen/data_structure/stack.rb +35 -0
- data/lib/kaninchen/data_structure/tree.rb +59 -0
- data/lib/kaninchen/data_structure/tree/each_node.rb +71 -0
- data/lib/kaninchen/data_structure/tree/nodes.rb +43 -0
- data/lib/kaninchen/data_structure/tree/properties.rb +102 -0
- data/lib/kaninchen/errors.rb +6 -0
- data/lib/kaninchen/version.rb +3 -0
- data/readme_img/kaninchen_tree.png +0 -0
- metadata +112 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 60f8b15a393a1f3f445c31196352d7e4d7233099
|
|
4
|
+
data.tar.gz: cfd89d83ea909a2801e2a280807c2150a1d7cf41
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 36f7653de76ebe90837cfe8dede0d9a0cc0ad72ee1e1297614e2921445254ad9929960038bfd854d4e7650562bf7939882c6a3bb15f151bf0d10747d00d4be72
|
|
7
|
+
data.tar.gz: 732eb364ce1df34e7aabc7f6475505a556cfe11e8a35d9259ad1b932727164508fd8b37a687d56dcaecc45c6ff3d2328aef6e26331e30cf16177cb20dfe7f206
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 Maxwell-Alexius
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Kaninchen
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.org/travis-ci/travis-web)
|
|
4
|
+
|
|
5
|
+
Simple implementation of data structures (and algorithms in future) in Ruby programming language.
|
|
6
|
+
|
|
7
|
+
Currently support data structures:
|
|
8
|
+
|
|
9
|
+
- Stacks
|
|
10
|
+
- Trees
|
|
11
|
+
|
|
12
|
+
Currently working on data structures:
|
|
13
|
+
|
|
14
|
+
- Queues
|
|
15
|
+
- Sets
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Add this line to your application's Gemfile:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
gem 'kaninchen'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
And then execute:
|
|
26
|
+
|
|
27
|
+
$ bundle
|
|
28
|
+
|
|
29
|
+
Or install it yourself as:
|
|
30
|
+
|
|
31
|
+
$ gem install kaninchen
|
|
32
|
+
|
|
33
|
+
## Stack
|
|
34
|
+
|
|
35
|
+
### Basic Usage
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
# Creata a new stack data structure
|
|
39
|
+
stack = Kaninchen::DataStructure::Stack.new
|
|
40
|
+
|
|
41
|
+
# Use the push method to push in data
|
|
42
|
+
stack.push(1)
|
|
43
|
+
|
|
44
|
+
# Chained method is also allowed
|
|
45
|
+
stack.push(2).push(3).push(4)
|
|
46
|
+
|
|
47
|
+
# Or you can use the #<< method which is alias to push
|
|
48
|
+
stack << 5 << 6 << 7
|
|
49
|
+
|
|
50
|
+
# Check the size of the stack
|
|
51
|
+
stack.size # -> 7
|
|
52
|
+
|
|
53
|
+
# Pop out stack
|
|
54
|
+
stack.pop # -> 7
|
|
55
|
+
stack.pop # -> 6
|
|
56
|
+
stack.pop # -> 5
|
|
57
|
+
|
|
58
|
+
# Empty stack will pop out nil value
|
|
59
|
+
empty_stack = Kaninchen::DataStructure::Stack.new
|
|
60
|
+
empty_stack.pop # -> nil
|
|
61
|
+
|
|
62
|
+
# Using bang method pop! in empty stack will raise error
|
|
63
|
+
empty_stack.pop!
|
|
64
|
+
# -> Kaninchen::PopEmptyStackError: Popping out empty stack
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Tree
|
|
68
|
+
|
|
69
|
+

|
|
70
|
+
|
|
71
|
+
### Basic Usage
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
# Create a new tree data structure and initialize the root node value
|
|
75
|
+
tree = Kaninchen::DataStructure::Tree.new 'ROOT'
|
|
76
|
+
tree.class # -> Kaninchen::DataStructure::Tree
|
|
77
|
+
|
|
78
|
+
# Tree has a root node which holds the string value 'ROOT'
|
|
79
|
+
tree.root.class # -> Kaninchen::DataStructure::Node
|
|
80
|
+
tree.root.value # -> 'ROOT'
|
|
81
|
+
|
|
82
|
+
# Root node is the root of the tree and is also a kind of tree node
|
|
83
|
+
tree.root.root? # -> true
|
|
84
|
+
tree.root.tree_node? # -> true
|
|
85
|
+
|
|
86
|
+
# Root node is not a nil node
|
|
87
|
+
tree.root.nil? # -> false
|
|
88
|
+
|
|
89
|
+
# Create a node which holds the value 'CHILD'
|
|
90
|
+
node = Kaninchen::DataStructure::Node.new 'CHILD'
|
|
91
|
+
|
|
92
|
+
# Node currently is not a tree node, which is also a kind of "nil node"
|
|
93
|
+
node.tree_node? # -> false
|
|
94
|
+
node.nil? # -> true
|
|
95
|
+
|
|
96
|
+
# Attach the node to the tree root node using the #<< method
|
|
97
|
+
tree.root << node
|
|
98
|
+
|
|
99
|
+
# Now the tree has a child node and the node's parent is the root node
|
|
100
|
+
tree.root.children.size # -> 1
|
|
101
|
+
tree.root.children[0] === node # -> true
|
|
102
|
+
node.parent === tree.root # -> true
|
|
103
|
+
|
|
104
|
+
# Now node is not nil node anymore, it belongs to the tree node
|
|
105
|
+
node.nil? # -> false
|
|
106
|
+
node.tree_node? # -> true
|
|
107
|
+
node.tree === tree # -> true
|
|
108
|
+
node.root? # -> false
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Attaching Nodes
|
|
112
|
+
|
|
113
|
+
Chained `#<<` method:
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
# Assume tree is the Kaninchen::DataStructure::Tree type and n1, n2, n3
|
|
117
|
+
# are Kaninchen::DataStructure::Node type
|
|
118
|
+
|
|
119
|
+
tree.root << n1 << n2 << n3
|
|
120
|
+
tree.root.children.size # -> 3
|
|
121
|
+
tree.root.children[0] === n1 # -> true
|
|
122
|
+
tree.root.children[1] === n2 # -> true
|
|
123
|
+
tree.root.children[2] === n3 # -> true
|
|
124
|
+
n1.parent === tree.root # -> true
|
|
125
|
+
n2.parent === tree.root # -> true
|
|
126
|
+
n3.parent === tree.root # -> true
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Array of nodes case:
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
# Assume tree is the Kaninchen::DataStructure::Tree type and n1, n2, n3
|
|
133
|
+
# are Kaninchen::DataStructure::Node type
|
|
134
|
+
tree.root << [n1, n2, n3]
|
|
135
|
+
tree.root.children.size # -> 3
|
|
136
|
+
tree.root.children[0] === n1 # -> true
|
|
137
|
+
tree.root.children[1] === n2 # -> true
|
|
138
|
+
tree.root.children[2] === n3 # -> true
|
|
139
|
+
n1.parent === tree.root # -> true
|
|
140
|
+
n2.parent === tree.root # -> true
|
|
141
|
+
n3.parent === tree.root # -> true
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Hash of nodes case:
|
|
145
|
+
```ruby
|
|
146
|
+
# Assume tree is the Kaninchen::DataStructure::Tree type and n1, n2, n3
|
|
147
|
+
# are Kaninchen::DataStructure::Node type
|
|
148
|
+
tree.node << { n1 => n2, n3 => nil }
|
|
149
|
+
tree.root.children.size # -> 2
|
|
150
|
+
tree.root.children[0] === n1 # -> true
|
|
151
|
+
tree.root.children[1] === n3 # -> true
|
|
152
|
+
tree.root.children[0].size # -> 1
|
|
153
|
+
tree.root.children[1].size # -> 0
|
|
154
|
+
tree.root.children[0].children.size # -> 1
|
|
155
|
+
tree.root.children[0].children[0] === n2 # -> true
|
|
156
|
+
n1.parent === tree.root # -> true
|
|
157
|
+
n2.parent === n1 # -> true
|
|
158
|
+
n3.parent === tree.root # -> true
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Mixed structure case (array and hash composition):
|
|
162
|
+
```ruby
|
|
163
|
+
# Assume tree is the Kaninchen::DataStructure::Tree type and n1, n2, n3
|
|
164
|
+
# n4, n5 are Kaninchen::DataStructure::Node type
|
|
165
|
+
tree.node << [n1, { n2 => [n3, n4], { n5 => nil } }]
|
|
166
|
+
|
|
167
|
+
# Tree Structure:
|
|
168
|
+
# ROOT ---> n1
|
|
169
|
+
# |-> n2 ---> n3
|
|
170
|
+
# | |-> n4
|
|
171
|
+
# |-> n5
|
|
172
|
+
#
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Tree Node Order & Traversal
|
|
176
|
+
|
|
177
|
+
Available methods associated with tree node order and traversal is listed below:
|
|
178
|
+
|
|
179
|
+
- `Tree#nodes`: Default returns an array of `Node` type objects which represents the preorder of the tree nodes
|
|
180
|
+
- `Tree#node_values`: Default returns an array of `Node` type objects' values which represents the preorder of the tree nodes
|
|
181
|
+
- `Tree#each_node`: Default iterates the tree nodes in preorder format which requires a given block
|
|
182
|
+
- `Tree#each_node_with_index`: Default iterates the tree nodes with index specified in preorder format which requires a given block
|
|
183
|
+
|
|
184
|
+
These methods can pass in optional parameter, when pass in:
|
|
185
|
+
|
|
186
|
+
- `:preorder` or `:depth_first`: Preorder mode
|
|
187
|
+
- `:inorder`: Inorder mode
|
|
188
|
+
- `:postorder`: Postorder mode
|
|
189
|
+
- `:levelorder` or `:breadth_first`: Level order mode
|
|
190
|
+
|
|
191
|
+
### Properties of Tree
|
|
192
|
+
|
|
193
|
+
- `Tree#height`: The height of the tree
|
|
194
|
+
- `Tree#leaves`: The leaves of the tree
|
|
195
|
+
|
|
196
|
+
### Properties of Tree Nodes
|
|
197
|
+
|
|
198
|
+
- `Node#type`: Returns the symbol object `:tree`
|
|
199
|
+
- `Node#degree`: The degree of the tree node (which is the count of the subtrees of the node)
|
|
200
|
+
- `Node#depth`: The depth of the tree node (which is the distance between the node and the tree root of the node)
|
|
201
|
+
- `Node#height`: The height of the tree node (which is the longest path to the leaves of the subtree of the node)
|
|
202
|
+
- `Node#subtree`: Returns the new tree type object which is the subtree of the node
|
|
203
|
+
- `Node#path`: Returns the path from the node to the root node as an array
|
|
204
|
+
- `Node#parent`: Returns the parent node of the node
|
|
205
|
+
- `Node#children`: Returns the child nodes of the node
|
|
206
|
+
- `Node#left_child`: Returns the left child node of the node
|
|
207
|
+
- `Node#right_child`: Returns the right child node of the node. (If there are over two children, it will return the second child node in default)
|
|
208
|
+
- `Node#leaf?`: Returns `true` if the node is the leaf of the tree
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'kaninchen'
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require 'pry'
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require 'irb'
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/kaninchen.gemspec
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require 'kaninchen/version'
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |spec|
|
|
8
|
+
spec.name = 'kaninchen'
|
|
9
|
+
spec.version = Kaninchen::VERSION
|
|
10
|
+
spec.authors = %w[Maxwell-Alexius]
|
|
11
|
+
spec.email = %w[destinydragon85614@gmail.com]
|
|
12
|
+
|
|
13
|
+
spec.summary = %q(Kaninchen gem contains a collection of fundamental data structures and algorithms in practice)
|
|
14
|
+
spec.description = %q(A simple implementation of basic data structure in Ruby)
|
|
15
|
+
# spec.homepage = 'TODO: Put your gem\'s website or public repo URL here.'
|
|
16
|
+
spec.license = 'MIT'
|
|
17
|
+
|
|
18
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
|
19
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
|
20
|
+
if spec.respond_to?(:metadata)
|
|
21
|
+
# spec.metadata['allowed_push_host'] = 'TODO: Set to "http://mygemserver.com"'
|
|
22
|
+
else
|
|
23
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
|
24
|
+
'public gem pushes.'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
28
|
+
f.match(%r{^(test|spec|features)/})
|
|
29
|
+
end
|
|
30
|
+
spec.bindir = 'exe'
|
|
31
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
32
|
+
spec.require_paths = %w[lib]
|
|
33
|
+
|
|
34
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
|
35
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
36
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
37
|
+
end
|
data/lib/kaninchen.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'kaninchen/data_structure/stack'
|
|
4
|
+
require 'kaninchen/data_structure/queue'
|
|
5
|
+
require 'kaninchen/data_structure/node'
|
|
6
|
+
require 'kaninchen/data_structure/tree'
|
|
7
|
+
require 'kaninchen/data_structure/set'
|
|
8
|
+
|
|
9
|
+
module Kaninchen
|
|
10
|
+
module DataStructure
|
|
11
|
+
def self.enable_extension!
|
|
12
|
+
require 'kaninchen/data_structure/extension'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kaninchen
|
|
4
|
+
module DataStructure
|
|
5
|
+
class Node
|
|
6
|
+
attr_reader :type, :value
|
|
7
|
+
def initialize(params = {})
|
|
8
|
+
if params.is_a? Hash
|
|
9
|
+
@type = params[:type]
|
|
10
|
+
@value = params[:value]
|
|
11
|
+
else
|
|
12
|
+
@value = params
|
|
13
|
+
@type = nil
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def nil?
|
|
18
|
+
@type.nil?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
case @type
|
|
23
|
+
when nil
|
|
24
|
+
"<NilNode value=\"#{value}\">"
|
|
25
|
+
when :tree
|
|
26
|
+
"<TreeNode value=\"#{value}\" depth=\"#{depth}\" level=\"#{level}\" degree=\"#{degree}\">"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
alias :inspect :to_s
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
def node_type(type)
|
|
33
|
+
define_method "#{type}_node?" do
|
|
34
|
+
@type === type
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
define_singleton_method "#{type}_node_attr_reader" do |*attrs|
|
|
38
|
+
attrs.each do |attr|
|
|
39
|
+
define_method attr do
|
|
40
|
+
send("#{type}_node?") ? instance_variable_get("@#{attr}") : nil
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kaninchen
|
|
4
|
+
module DataStructure
|
|
5
|
+
class Stack
|
|
6
|
+
def initialize(*items)
|
|
7
|
+
@stack ||= items
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def push(item)
|
|
11
|
+
@stack.push item
|
|
12
|
+
self
|
|
13
|
+
end
|
|
14
|
+
alias :<< :push
|
|
15
|
+
|
|
16
|
+
def pop
|
|
17
|
+
@stack.pop
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def pop!
|
|
21
|
+
popped = self.pop
|
|
22
|
+
raise Kaninchen::PopEmptyStackError, 'Popping out empty stack' if popped.nil?
|
|
23
|
+
popped
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def empty?
|
|
27
|
+
@stack.size.zero?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def size
|
|
31
|
+
@stack.size
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'kaninchen/data_structure/tree/properties'
|
|
4
|
+
require 'kaninchen/data_structure/tree/nodes'
|
|
5
|
+
require 'kaninchen/data_structure/tree/each_node'
|
|
6
|
+
|
|
7
|
+
module Kaninchen
|
|
8
|
+
module DataStructure
|
|
9
|
+
class Tree
|
|
10
|
+
attr_reader :root
|
|
11
|
+
def initialize(value)
|
|
12
|
+
if value.is_a? Kaninchen::DataStructure::Node
|
|
13
|
+
@root = value
|
|
14
|
+
else
|
|
15
|
+
@root = Kaninchen::DataStructure::Node.new value
|
|
16
|
+
end
|
|
17
|
+
@root.send(:set_tree_node_data, tree: self)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_s
|
|
21
|
+
"<Tree root=\"#{root}\" height=\"#{height}\">"
|
|
22
|
+
end
|
|
23
|
+
alias :inspect :to_s
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Node
|
|
27
|
+
node_type :tree
|
|
28
|
+
tree_node_attr_reader :tree, :parent, :children
|
|
29
|
+
|
|
30
|
+
def <<(params)
|
|
31
|
+
case
|
|
32
|
+
when (params.is_a?(Kaninchen::DataStructure::Node) and params.nil?)
|
|
33
|
+
params.send(:set_tree_node_data, tree: self.tree, parent: self)
|
|
34
|
+
set_tree_node_data(children: @children.push(params))
|
|
35
|
+
when params.is_a?(Array) then params.each { |node| self << node }
|
|
36
|
+
when params.is_a?(Hash)
|
|
37
|
+
params.each_pair do |key, value|
|
|
38
|
+
self << key
|
|
39
|
+
key << value if key.is_a? Kaninchen::DataStructure::Node
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def root?
|
|
46
|
+
@parent.nil?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def set_tree_node_data(params)
|
|
52
|
+
@type = :tree
|
|
53
|
+
@tree ||= params[:tree]
|
|
54
|
+
@parent ||= params[:parent]
|
|
55
|
+
@children ||= params[:children] || []
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kaninchen
|
|
4
|
+
module DataStructure
|
|
5
|
+
class Tree
|
|
6
|
+
def each_node(type = :preorder)
|
|
7
|
+
case
|
|
8
|
+
when %i[preorder depth_first].include?(type)
|
|
9
|
+
yield self.root
|
|
10
|
+
recursive_preorder_loop(self.root) { |node| yield node }
|
|
11
|
+
when type === :inorder
|
|
12
|
+
recursive_inorder_loop(first_leaf, :left_most) { |node| yield node }
|
|
13
|
+
when type === :postorder
|
|
14
|
+
recursive_postorder_loop(self.root) { |node| yield node }
|
|
15
|
+
when %i[levelorder breadth_first].include?(type)
|
|
16
|
+
yield self.root
|
|
17
|
+
recursive_levelorder_loop(self.root) { |node| yield node }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def each_node_with_index(type = :preorder)
|
|
22
|
+
index = 0
|
|
23
|
+
self.each_node(type) do |node|
|
|
24
|
+
yield node, index
|
|
25
|
+
index += 1
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def recursive_preorder_loop(parent_node)
|
|
32
|
+
parent_node.children.each do |child_node|
|
|
33
|
+
yield child_node
|
|
34
|
+
recursive_preorder_loop(child_node) { |node| yield node }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def recursive_inorder_loop(node, current_role, end_node = nil)
|
|
39
|
+
yield node
|
|
40
|
+
case current_role
|
|
41
|
+
when :left_most
|
|
42
|
+
until node === end_node or node.root?
|
|
43
|
+
recursive_inorder_loop(node.parent, :right_recursive, end_node) { |n| yield n } unless node.parent === end_node
|
|
44
|
+
node = node.parent
|
|
45
|
+
end
|
|
46
|
+
when :right_recursive
|
|
47
|
+
node.send(:right_children).each do |child_node|
|
|
48
|
+
left_most_child = child_node.send(:left_most_child)
|
|
49
|
+
recursive_inorder_loop(left_most_child, :left_most, end_node = node) { |n| yield n }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def recursive_postorder_loop(node)
|
|
55
|
+
unless node.leaf?
|
|
56
|
+
recursive_postorder_loop(node.left_child) { |n| yield n }
|
|
57
|
+
node.send(:right_children).each do |child_node|
|
|
58
|
+
recursive_postorder_loop(child_node) { |n| yield n }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
yield node
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def recursive_levelorder_loop(node)
|
|
65
|
+
children = node.children
|
|
66
|
+
children.each { |child_node| yield child_node }
|
|
67
|
+
children.each { |child_node| recursive_levelorder_loop(child_node) { |n| yield n } }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kaninchen
|
|
4
|
+
module DataStructure
|
|
5
|
+
class Tree
|
|
6
|
+
def nodes(type = nil)
|
|
7
|
+
if type.nil?
|
|
8
|
+
{ self.root => recursive_get_struct(self.root) }
|
|
9
|
+
else
|
|
10
|
+
result = []
|
|
11
|
+
each_node(type) { |node| result.push(node) }
|
|
12
|
+
result
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def node_values(type = nil)
|
|
17
|
+
if type.nil?
|
|
18
|
+
{ self.root.value => recursive_get_struct_value(self.root) }
|
|
19
|
+
else
|
|
20
|
+
nodes(type).map(&:value)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def recursive_get_struct(node)
|
|
27
|
+
result = {}
|
|
28
|
+
node.children.each do |child_node|
|
|
29
|
+
result[child_node] = recursive_get_struct(child_node)
|
|
30
|
+
end
|
|
31
|
+
result.empty? ? nil : result
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def recursive_get_struct_value(node)
|
|
35
|
+
result = {}
|
|
36
|
+
node.children.each do |child_node|
|
|
37
|
+
result[child_node.value] = recursive_get_struct_value(child_node)
|
|
38
|
+
end
|
|
39
|
+
result.empty? ? nil : result
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kaninchen
|
|
4
|
+
module DataStructure
|
|
5
|
+
class Tree
|
|
6
|
+
def leaves
|
|
7
|
+
self.nodes(:preorder).select { |node| node.children.empty? }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def height
|
|
11
|
+
self.nodes(:preorder).map do |node|
|
|
12
|
+
count = 1
|
|
13
|
+
until node.parent.nil?
|
|
14
|
+
count += 1
|
|
15
|
+
node = node.parent
|
|
16
|
+
end
|
|
17
|
+
count
|
|
18
|
+
end.max
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def first_leaf
|
|
24
|
+
self.each_node(:preorder) { |node| return node if node.children.empty? }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Node
|
|
29
|
+
def degree
|
|
30
|
+
self.children.size
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def path
|
|
34
|
+
node = self
|
|
35
|
+
arr = [node]
|
|
36
|
+
until node.root?
|
|
37
|
+
node = node.parent
|
|
38
|
+
arr << node
|
|
39
|
+
end
|
|
40
|
+
arr
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def left_child
|
|
44
|
+
self.degree.zero? ? nil : self.children[0]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def right_child
|
|
48
|
+
self.degree < 2 ? nil : self.children[1]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def depth
|
|
52
|
+
count = 0
|
|
53
|
+
current_node = self
|
|
54
|
+
until current_node.root?
|
|
55
|
+
count += 1
|
|
56
|
+
current_node = current_node.parent
|
|
57
|
+
end
|
|
58
|
+
count
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def level
|
|
62
|
+
depth + 1
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def subtree
|
|
66
|
+
tree = Kaninchen::DataStructure::Tree.new(self.value)
|
|
67
|
+
recursive_attach_subtree_nodes(tree.root, self)
|
|
68
|
+
tree
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def height
|
|
72
|
+
self.subtree.height
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def leaf?
|
|
76
|
+
self.children.empty?
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def recursive_attach_subtree_nodes(new_node, origin_node)
|
|
82
|
+
origin_node.children.each do |origin_child_node|
|
|
83
|
+
new_child_node = self.class.new(origin_child_node.value)
|
|
84
|
+
new_node << new_child_node
|
|
85
|
+
recursive_attach_subtree_nodes(new_child_node, origin_child_node)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Right children is for the n-ary but not for the binary-tree system
|
|
90
|
+
# which will be served as private method due to the needs of the
|
|
91
|
+
# implementation of traversal
|
|
92
|
+
def right_children
|
|
93
|
+
self.degree < 2 ? [] : self.children[1..-1]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def left_most_child(node = self)
|
|
97
|
+
node = node.left_child until node.left_child.nil?
|
|
98
|
+
node
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
Binary file
|
metadata
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: kaninchen
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Maxwell-Alexius
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-08-12 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.15'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.15'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.0'
|
|
55
|
+
description: A simple implementation of basic data structure in Ruby
|
|
56
|
+
email:
|
|
57
|
+
- destinydragon85614@gmail.com
|
|
58
|
+
executables: []
|
|
59
|
+
extensions: []
|
|
60
|
+
extra_rdoc_files: []
|
|
61
|
+
files:
|
|
62
|
+
- ".gitignore"
|
|
63
|
+
- ".rspec"
|
|
64
|
+
- ".travis.yml"
|
|
65
|
+
- Gemfile
|
|
66
|
+
- LICENSE.txt
|
|
67
|
+
- README.md
|
|
68
|
+
- Rakefile
|
|
69
|
+
- bin/console
|
|
70
|
+
- bin/setup
|
|
71
|
+
- kaninchen.gemspec
|
|
72
|
+
- lib/kaninchen.rb
|
|
73
|
+
- lib/kaninchen/algorithm.rb
|
|
74
|
+
- lib/kaninchen/data_structure.rb
|
|
75
|
+
- lib/kaninchen/data_structure/extension.rb
|
|
76
|
+
- lib/kaninchen/data_structure/node.rb
|
|
77
|
+
- lib/kaninchen/data_structure/queue.rb
|
|
78
|
+
- lib/kaninchen/data_structure/set.rb
|
|
79
|
+
- lib/kaninchen/data_structure/stack.rb
|
|
80
|
+
- lib/kaninchen/data_structure/tree.rb
|
|
81
|
+
- lib/kaninchen/data_structure/tree/each_node.rb
|
|
82
|
+
- lib/kaninchen/data_structure/tree/nodes.rb
|
|
83
|
+
- lib/kaninchen/data_structure/tree/properties.rb
|
|
84
|
+
- lib/kaninchen/errors.rb
|
|
85
|
+
- lib/kaninchen/version.rb
|
|
86
|
+
- readme_img/kaninchen_tree.png
|
|
87
|
+
homepage:
|
|
88
|
+
licenses:
|
|
89
|
+
- MIT
|
|
90
|
+
metadata: {}
|
|
91
|
+
post_install_message:
|
|
92
|
+
rdoc_options: []
|
|
93
|
+
require_paths:
|
|
94
|
+
- lib
|
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '0'
|
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '0'
|
|
105
|
+
requirements: []
|
|
106
|
+
rubyforge_project:
|
|
107
|
+
rubygems_version: 2.6.12
|
|
108
|
+
signing_key:
|
|
109
|
+
specification_version: 4
|
|
110
|
+
summary: Kaninchen gem contains a collection of fundamental data structures and algorithms
|
|
111
|
+
in practice
|
|
112
|
+
test_files: []
|